I've configured a FB graph call that would retrieve data from the API, however I'm having trouble inserting it into MongoDb. Right now if I run Photos.find().count(); in the browser it shows that there are photos, however if I run db.Photos.find().count(); in MongoDb it shows nothing. Also, if I run db.users.find(); in MongoDb it returns results from the FB user account, so MongoDb is talking to the API to some extent.
Any thoughts on what might be causing the issue?
Here is my code:
Client:
Template.test.events({
'click #btn-user-data': function(e) {
Meteor.call('getUserData', function(err, data) {
if(err) console.error(err);
});
}
});
Template.facebookphoto.helpers({
pictures: function () {
return Photos.find();
}
});
Server:
function Facebook(accessToken) {
this.fb = Meteor.require('fbgraph');
this.accessToken = accessToken;
this.fb.setAccessToken(this.accessToken);
this.options = {
timeout: 3000,
pool: {maxSockets: Infinity},
headers: {connection: "keep-alive"}
}
this.fb.setOptions(this.options);
}
Facebook.prototype.query = function(query, method) {
var self = this;
var method = (typeof method === 'undefined') ? 'get' : method;
var data = Meteor.sync(function(done) {
self.fb[method](query, function(err, res) {
done(null, res);
});
});
return data.result;
}
Facebook.prototype.getUserData = function() {
return this.query('me/photos');
}
Meteor.methods({
getUserData: function() {
var fb = new Facebook(Meteor.user().services.facebook.accessToken);
var data = fb.getUserData();
_.forEach(data.data, function(photo) {
if(Photos.findOne({id: photo.id})) return;
Photos.insert(photo, function(err) {
if(err) console.error(err);
});
});
}
});
Collection:
Photos = new Meteor.Collection('picture');
Thanks in advance!
Instead of db.Photos.find().count();, try db.picture.find().count();
Photos is just the name you gave to the JavaScript variable. The actual name of the collection in MongoDB is whatever you use when you initialized the Collection - in this case, picture.
Related
I have an app that works fine local but once on heroku, it does not work. My app has a scrape function that stores the retrieved articles from the website into a database. The problem is, this does not work on Heroku for some reason and I get the error MongoError: Invalid Operation, No operations in bulk. I tried using new Promise and ORM but I still get the same error. The weird part is, this worked once on heroku when I was using the new Promise, but after I went to a route called /delete the scrape stopped working for some reason. This route just deletes all the data from both my models. I am unsure now what the problem is. Could it be that when I am doing an insertMany into my Article model, there are empty properties that do not get assigned?
Update: I just put a console.log of the array scrappedStuff inside of the scraper function and it is showing the array is empty in the heroku logs. Why is it showing the array is empty? Shouldnt this call back function that is passed the array be called once the .each() is finished?
//MY MODEL
var ArticleSchema = new Schema({
title: {
type: String
},
link: {
type: String
},
description: {
type: String
},
saved: {
type: Boolean,
default: false
},
img: {
type: String
},
comment: [{
type: Schema.Types.ObjectId,
ref: 'Comment'
}]
});
//ROUTE FILE
var scrape = require('./scrape');
var scraper = function (response, scrapedStuff, displayScrape) {
console.log("INSIDE SCRAPER CALLBACK FUNCTION (INSERTMANY)", scrapedStuff)
console.log("TWOOOOOOOOOOOOOOOOOOOOOOOOOO")
Article.collection.insertMany(scrapedStuff, { ordered: false }, function(err, docs){
if(err){
console.log(err);
}else{
console.log("INSERT MANY DOCS", docs);
console.log("FINISHED SCRAPING ELSE")
// resolve();
displayScrape(response);
}
});
}
var displayScrape = function(response){
console.log("THREEEEEEEEEEEEEEEEEEEEEEE")
Article.find({}, function(err, doc){
if(err){
console.log(err)
}else{
if(doc.length > 0){
console.log("CHECK TO SEE IF DOCS IN HOME GOT UPDATE", doc)
var articleLength = [];
for(var x = 0; x < doc.length; x++){
if(doc[x].saved === false){
articleLength.push(doc[x]);
}
}
// var finalLength = articleLength.length;
response.render('home', {data: {articles: doc, length: articleLength.length, finishScrape: true}})
}else{
response.render('home');
}
}
});
}
router.get('/scrape', function(req, response){
scrape(response, scraper, displayScrape);
});
// SCRAPE FILE
var request = require('request');
var cheerio = require('cheerio');
var scrape = function(response, scraper, displayScrape) {
console.log("ONNNNNNNNNEEEEEEEEEEE")
request('http://www.gamespot.com/', function(err, res, html){
if(err)
{
console.log(err)
// reject(err);
}
// else
var scrapedStuff = [];
console.log("GOT RESPONSE FROM GAMESPOT");
var $ = cheerio.load(html);
// var articleCounter = 1;
$('article a').each(function(i, element){
// var scrapedStuff = {};
// scrapedStuff.articleID = articleCounter;
var scrpObj = {
title: $(this).attr('data-event-title'),
link: $(this).attr('href'),
img: $(this).children('figure').children('div.media-img').children('img').attr('src'),
description: $(this).children('div.media-body').children('p.media-deck').text()
}
scrapedStuff.push(scrpObj);
});
console.log("SCRAPED RESULTS", scrapedStuff);
scraper(response, scrapedStuff, displayScrape);
});
}
module.exports = scrape;
Any ideas why this isn't working? It comes back with the success message but doesn't actually update anything.
I'm adding an FB user using Parse but since it doesn't have a func to add the username and email trying to do it this way. Any help much appreciated.
JS
Parse.Cloud.run("test", { objectId: "Q8XRUcL22N", name: "Rich", email: "rich#gmail.com"}, {
success: function(results) {
console.log(results);
},
error: function(error) {
console.log(error);
}
});
CLOUD CODE:
Parse.Cloud.define("test", function (request, response) {
Parse.Cloud.useMasterKey();
var uid;
var query = new Parse.Query("_User");
query.count({
success: function (results) {
uid = parseInt(results);
},
error: function () {
response.error("UID lookup failed");
}
});
var query = new Parse.Query(Parse.User);
query.equalTo("objectId", request.params.objectId);
query.first({
success: function (object) {
object.set("username", request.params.name);
object.set("email", request.params.email);
object.set("uid", uid);
var acl = new Parse.ACL();
acl.setPublicWriteAccess(false);
acl.setPublicReadAccess(false);
object.setACL(acl);
object.save();
response.success("Success Message");
},
error: function (error) {
response.error("Error Message");
}
});
});
Thanks
Calling success() or error() on the response halts whatever is underway at the time, including the save() on the user.
Also, it looks like you want to record in the user a count of users at the time the ACL is set. Getting the count must also be serialized with the other operations. (Also, please note that count is only good as an id "uid" to the extent the user count never goes down. What's wrong with the parse objects's id as an id?).
Most of the parse functions return promises, and using them is the only way to not go nuts trying to nest callbacks. So...
Parse.Cloud.define("test", function(request, response) {
Parse.Cloud.useMasterKey();
var uid;
var query = new Parse.Query(Parse.User);
query.count().then(function(count) {
uid = count;
return query.get(request.params.objectId);
}).then(function(object) {
object.set("username", request.params.name);
object.set("email", request.params.email);
object.set("uid", uid);
var acl = new Parse.ACL();
acl.setPublicWriteAccess(false);
acl.setPublicReadAccess(false);
object.setACL(acl);
return object.save();
}).then(function (object) {
response.success(object);
},function(error) {
response.error("Error Message");
});
});
I try to get data from an LDAP-Server via a Meteor server to the client.
But the LDAP-Request is asynchronous and the method returns false and not the result that is collected in the ldap.search function-call. So, how can i get the calls to the ldap synchronously or trigger an event on the client when the data is ready?
//defined on serverside
Meteor.methods({
searchPerson: function(account){
var data = null;
var LDAP = Npm.require('LDAP');
var ldap = new LDAP({uri: 'ldaps://ldap-server', version: 3});
var search_options = {
base: 'ou=xxx,dc=yyy,dc=zzz',
scope: '1',
filter: '(uid='+account+')',
attrs: 'surname, givenname, mail'
};
var bind_options = {
binddn: 'cn=aaa,ou=bbb,dc=ccc,dc=ddd',
password: 'password'
};
ldap.open(function(err) {
if (err) {
throw new Meteor.Error('Can not connect');
}
ldap.simpleBind(bind_options, function(err){
if (err){
throw new Meteor.Error('Can not bind');
}
ldap.search(search_options, function(err, data){
if (err){
throw new Meteor.Error('Error occured');
}
return data;
});
});
});
return false;
}
});
Thanks a lot.
torrofs
What you want is Meteor futures, as in this answer. This gist explains how.
I have an Angular service that takes in a roleId and userId and assigns the user to that role and make a pointer in User to that role.
app.service('CRUD', function () {
this.addUserToRole = function (roleId, userId) {
// first we have to find the role we're adding to
var query = new Parse.Query(Parse.Role);
return query.get(roleId, {
success: function (role) {
// then add the user to it
var Database = Parse.Object.extend("User");
var query = new Parse.Query(Database);
console.log(role);
return query.get(userId, {
success: function (user) {
console.log(user);
role.getUsers().add(user);
role.save();
// now we need to tell the user that he has this role
console.log(user);
user.attributes.role.add(role);
user.save();
return user;
},
error: function (err) {
return err;
}
});
},
error: function (err) {
console.log(err);
}
});
}
});
I'm getting {"code":206,"error":"Parse::UserCannotBeAlteredWithoutSessionError"} on user.save();
After some research, I arrived at this website. He uses this code snippet as a JS SDK example:
Parse.Cloud.run('modifyUser', { username: 'userA' }, {
success: function(status) {
// the user was updated successfully
},
error: function(error) {
// error
}
});
and mentions something about a useMasterKey() function.
I'm still unsure how to fix this error.
Add
Parse.Cloud.useMasterKey();
at the beginning of your function.
Set it up as a background job. That is the code snip you found I think and a simpler far more secure means of fondling users and roles
https://parse.com/docs/cloud_code_guide#jobs
I'm developing a express.js application, without mongoose.
What I'm trying to do is, to encapsulate calls to mongodb inside a function, pass the function some parameter and get the data back from mongodb.
The problem I'm running into is explained by the code below
function get_data()
{
var mongo = require('mongodb'),Server = mongo.Server,Db = mongo.Db;
var server = new Server('localhost', 27017, {auto_reconnect: true});
var db = new Db('test', server);
db.collection('test_collection', function(err, collection) {
collection.find().toArray(function(err, items) {
var data = items;
});
});
console.log(data);
console.log("in get");
return data;
}
How do I return the items Array I pulled from mongo db from this function.
I want to know how scoping works in javascript and how do I put the items in a variable and return them from the get_data function.
After the answer
I fixed the code. It now works and looks like this.
function get_data(callback) {
var mongo = require('mongodb'),Server = mongo.Server,Db = mongo.Db;
var server = new Server('localhost', 27017, {auto_reconnect: true});
var db = new Db('test', server);
db.open(function(err, db) {
if (err) return callback(err);
db.collection('test_collection', function(err, collection) {
if (err) return callback(err);
collection.find().toArray(callback);
});
});
}
get_data(function(err, items) {
// handle error
console.log(items);
});
Since the items are retrieved from MongoDB asynchronously, the function get_data needs to accept a callback that will be used to return the results. I believe you'll also need to explicitly open the database connection.
function get_data(callback) {
...
db.open(function(err, db) {
if (err) return callback(err);
db.collection('test_collection', function(err, collection) {
if (err) return callback(err);
collection.find().toArray(callback);
});
});
}
get_data(function(err, items) {
// handle error
console.log(items);
});