Can't retrieve data from the result of mongoose's find method - node.js

I want to get the data from result of mongoose's find method.
SinceIdLog.find({},['since_id','saved_date'],{sort:{'saved_date': -1}, limit:1}, function(err, docs) {
console.log(docs[0]);
// some processes
});
the output of 'console.log' in this case is what I want like following.
{ since_id: '214320642386968576',
saved_date: Sun, 17 Jun 2012 13:16:04 GMT,
_id: 4fddd8941390b38712000143 }
But, when I write like below
SinceIdLog.find({},['since_id','saved_date'],{sort:{'saved_date': -1}, limit:1}, function(err, docs) {
console.log(docs[0].since_id);
// some processes
});
the output is 'undifined'.
Do you know why?
I save the 'since_id' of Twitter API's parameter in MongoDB.
In this code, I want to get the since_id to retrieve the tweets newly updated in using OAuth.
Regards,

Remove the extraneous ] after since_id in the console.log statement.

Maybe you have getter function for since_id field which doesn't return anything? Check the schema.

I had the same problem once and I think parsing the result helped.
Try the following
SinceIdLog.find({},['since_id','saved_date'],{sort:{'saved_date': -1}, limit:1}, function(err, docs) {
docs = JSON.parse(docs);
console.log(docs[0].since_id);
// some processes
});

Thank you everyone,
I found the cause.
I haven't correctly defined the Schema like following
var Schema = mongoose.Schema,
SinceIdLog = mongoose.model('SinceIdLog', new Schema());
this works when saving the data.
var XXX = new SinceIdLog(Object);
XXX.save(function(err) {});
But it doesn't seem work well in finding.
I modified it and now it's working correctly.
var Schema = mongoose.Schema,
SinceIdLog = new Schema({
since_id: String,
saved_date: Date
}),
SinceIdSchema = mongoose.model('SinceIdLog', SinceIdLog);
Thanks!!

Related

Is collection.findOne({query}) not supposed to return the document itself?

I see a lot of tutorials/guides using collection.findOne({query}).field to get a value of a field in the document that is returned, but for me that doesn't seem to work and I wonder why. I did figure out another way to do it though. See below:
var rank = function(id) {
// My way of doing it
collection.findOne({ _id: id }, function(err, doc) {
console.log(doc.score); // Prints the actual score
});
// How some tutorials do it
var score = collection.findOne({ _id: id }).score;
console.log(score); // Gives a TypeError (Cannot read property 'score' of undefined)
};
// How some tutorials do it
Those tutorials are likely using mongodb's shell, not node.js api. The shell's api looks similar (all the same words, findOne, etc.), but it doesn't use callbacks. Shell's findOne does return the document inline.

node-mongodb-native remove by DBRef $id (dot issue)

I have 2 collections in my mongodb database: users and posts.
And in posts collection I have DBRef field like this:
user : DBRef('users', ObjectId('...'), null)
When I'm going to remove some post by user id, I do the following:
db.posts.remove({ 'user.$id' : ObjectId('...') })
And it works great, but not from node-mongodb-native. From node-mongodb-native I'm getting following error while doing this request:
key must not contain '.'
Can anyoune see that? Thank you for your help and explanations if I'm wrong in something.
Update
find requests by DBRef $id work fine!
Node.js code:
var mongodb = require('mongodb')
, nconf = require('nconf')
, MongoClient = mongodb.MongoClient;
MongoClient.connect(nconf.get('db:connectionString'), function(mongoConnectionError, db) {
if (mongoConnectionError) throw mongoConnectionError;
db
.collection('posts')
.remove({ 'user.$id' : new mongodb.ObjectID('...') }, {}, function(err, removedItems) {
if (err) { throw err; }
console.log('Removed items: ' + removedItems);
});
});
I've used a similar model, but my post was from ONE user, making it simply:
db.posts.remove({'user_id' : ObjectID('...') });
In this case, it looks more like the collection posts has an array user with id in it.
If I'm not mistaken, you should use the $ in the user array to do something to an element in an array once you've matched.
If your purpose is removing the entire post, simply remove it by matching the id in the users array:
db.posts.remove({user:{$in:ObjectID('...'}});
Otherwise, $pull, as said above.

Updating array within mongodb record with mongoose

What is the best way to update a value within an array saved in a mongodb record? Currently, I'm trying it this way:
Record.find({ 'owner': owner}, {}, {sort: { date: -1 }}, function(err, record){
if(!err){
for (var i = 0; i < record[0].array.length; i++){
record[0].array[i].score = 0;
record[0].array[i].changed = true;
record[0].save();
}
}
});
And the schema looks like this:
var recordSchema = mongoose.Schema({
owner: {type: String},
date: {type: Date, default: Date.now},
array: mongoose.Schema.Types.Mixed
});
Right now, I can see that the array updates, I get no error in saving, but when I query the database again, the array hasn't been updated.
It would help if you explained your intent here as naming a property "array" conveys nothing about its purpose. I guess from your code you hope to go and set the score of each item there to zero. Note your save is currently being ignored because you can only save top-level mongoose documents, not nested documents.
Certain find-and-modify operations on arrays can be done with a single database command using the Array Update Operators like $push, $addToSet, etc. However I don't see any operators that can directly make your desired change in a single operation. Thus I think you need to find your record, alter the array date, and save it. (Note findOne is a convenience function you can use if you only care about the first match, which seems to be the case for you).
Record.findOne({ 'owner': owner}, {}, {sort: { date: -1 }}, function(err, record){
if (err) {
//don't just ignore this, log or bubble forward via callbacks
return;
}
if (!record) {
//Record not found, log or send 404 or whatever
return;
}
record.array.forEach(function (item) {
item.score = 0;
item.changed = true;
});
//Now, mongoose can't automatically detect that you've changed the contents of
//record.array, so tell it
//see http://mongoosejs.com/docs/api.html#document_Document-markModified
record.markModified('array');
record.save();
});
If you have a mongoose object of a document, you can of course update the array as in the question, with the following Caveat.
This is in fact a mongoose gotcha. Mongoose cannot track changes in the array of mixed, one has to use markModified:
doc.mixed.type = 'changed';
doc.markModified('mixed.type');
doc.save() // changes to mixed.type are now persisted

Mongoose: Using addToSet with ObjectIds Results in Orphan Id

I am having a rather interesting problem using mongoDB's $addToSet to an array full of ObjectIds.
In my mongoose schema ("Happening"), I declare an array of ObjecIds called "expected", to be used by .populate().
expected: [{type: Schema.Types.ObjectId, ref: "User" }]
... which works nicely everywhere I use it. So far so good.
I then attempt to update the Happening.expected array using $addToSet as outlined here:
http://docs.mongodb.org/manual/reference/operator/addToSet/
like so:
app.get("/happening/yamobethere/:id", ensureLoggedIn("/login"),
function (req, res) {
// userId is the mongo ObjectId of the user record
var userId = req.session.user.id,
eventId = req.params.id;
models.Happening.update(
{_id: eventId}, {
$addToSet: {expected: userId}
},
function(err, updated){
if (err) {
res.json({"error": err});
}
res.json({"updated": updated});
});
});
... which always yields:
{updated: 1}
Now the docs lead me to expect the actual userId that I passed in, so the "1" is a bit odd. I expected it to be a fail, and in light of the weirdness that happens next, it appears to be a mongodb error of some sort percolating it's way back to me as results.
The weirdness is, when I check my database, I see that indeed a new ObjectId has been added: just not the one I passed in.
"expected" : [
ObjectId("51cb18623ade2b9f1e000004"),
ObjectId("51cdb7c12f0e58bdb3000001")
],
becomes
"expected" : [
ObjectId("51cb18623ade2b9f1e000004"),
ObjectId("51cdb7c12f0e58bdb3000001"),
ObjectId("51cdb80e09612bfab3000002")
],
The new ObjectId does not appear in any of my collections. It appears to be an orphan, but I'm a mongo noob, so I may be full of compost on this.
I did attempt to cast the userId as an ObjectId:
$addToSet: {expected: mongoose.Types.ObjectId.fromString(userId)}
but that changed nothing, and really should not be necessary, since the schema should handle it.
I'd really rather not resort to downloading the entire object, appending the value to the "expected" array, then sending the whole schmear back for an update.
Any help appreciated, folks. Thanks!
Update:
A colleague suggested the following technique:
var addMe = {$addToSet: {expected: userId}};
models.Happening.findByIdAndUpdate(eventId, addMe, function(err, me) {
if (err) {
return json(err);
}
res.json(200, me);
});
... which is a bit of an improvement, since it actually returns an object for me to inspect. Unfortunately, it also results in orphaned ObjecIds appearing in the array, rather than the existing userId value I specified.
Thanks again!
It appears that my passport strategy is returning the ObjectID of the rejected attempted creation of a new user in the db via data from oauth. So, the code is fine, my data is garbage.
Never trust anything, and be prepared to look like a boob. :-)
Thanks for the clarification on my return values JohnnyHK.

remove _id from mongo result

I'm pretty new with mongo and nodejs
I've a json as result of my query and I simply want to return the result as an http request, as following:
app.get('/itesms', function(req, res) {
items.find().toArray(function (err, array) {
res.send(array);
})
});
It works, only problem is that I want to hide the _id fields (recursively) from the result.
Any suggestion to do that in an elegant way?
Try this solution:
app.get('/itesms', function(req, res) {
items.find({}, { _id: 0 }).toArray(function (err, array) {
res.send(array);
})
});
The usual .find({}, {_id:0}) approach wasn't working for me, so I went hunting and found in another SO answer that in version 3 of the Mongo API, you need to write it like this: .find({}, {projection:{_id:0}}). So, for example:
let docs = await db.collection("mycol").find({}, {projection:{_id:0}}).toArray();
It seems that (in the nodejs API, at least) you can also write it like this:
let docs = await db.collection("mycol").find({}).project({_id:0}).toArray();
The problem is that you can't project inclusions and exclusions, ie you can't run a query with a 'project' statement that declares what should be included in the response as well as what must be excluded from the response.
From MongoDB documentation:
A projection cannot contain both include and exclude specifications, except for the exclusion of the _id field. In projections that explicitly include fields, the _id field is the only field that you can explicitly exclude.
The way I handled this problem was to go to the end of the process, right before returning the response:
const dbObjectJSON = dbObject.toJson();
delete dbObjectJSON._id;
delete dbObjectJSON.__v;
...
response.json(dbObjectJSON);
Hope this helps.

Resources