Making a double query ( Find inside a Find) in Mongoose - node.js

I want to query a document. here's its schema
{
_id,
notes: [{_id: 243234,
text: "hey"},
_id, 421123,
text: "hi"}
]
}
I want to first find the document by _id and then find the value of 'text' on notes[1].
Using this, I can find the actual document but how can I find the object inside notes array? I have to find and update the 'text' inside note.
socket.on("individualnote edit", function(data) {
rooms.find({ _id: data.roomId}, function( err, doc) {
if (err) {
console.log("Something wrong when updating data!");
}
console.log(doc);
});

You can use positional $ operator to find and update an element within a sub document array.
The positional $ operator identifies an element in an array to update without explicitly specifying the position of the element in the array.
rooms.findOneAndUpdate({
_id: _id,
'notes.text': 'hey'
}, {
'$set': {
'notes.$.text': 'new text'
}
}).then(() => {
console.log('Success');
}).catch((err) => {
console.log('err', err.stack);
});

Related

Mongodb update object in multi nested array

I'm trying to update an object that is inside a multi nested array in Mongodb. I know that I cannot use the positional $ operator for multi nested arrays. So I'm trying to use arrayFilters instead.
Here is my query structure:
var objTest = {
name: 'blah',
color: 'blablah'
}
SomeModel.updateOne(
{
an_id: anId,
"an_array.another_array.and_another_array.some_id": id,
},
{
$set: {
"an_array.$[element].another_array.$[another_element].and_another_array": objTest,
},
},
{
arrayFilters: [
{ "element.name": 'test' },
{ "another_element.id": 'test2' },
],
}
)
.then((result) => {
console.log("result ", result);
resolve(result);
})
.catch((err) => {
console.log("err is ", err);
reject(err);
});
So as per the example, I'm trying to update the object that matches some_id in the and_another_array array. When I try this, I'm receiving the error The top-level field name must be an alphanumeric string beginning with a lowercase letter, found 'another_element'
I don't understand what I'm doing wrong here.
I was able to figure out what the issue was. For some reason, mongodb didn't like the in another_element. renaming it to anotherelement worked.

Pull only one element from and Array in Mongoose

I was trying to pull only one element from an Array which is a mongo document.
My db looks like this:
product: ['foo','foo','foo'],
...
I want to remove only one element from this array.
My db should Look like this:
product: ['foo','foo'],
...
When I was using model.findByIdAndUpdate( id, { $pull: {product: 'foo'} } )
I loose all my values from product
`
doc.findById(productId)
.then(async (result) => {
if (!result) {
console.log("No Record Found.");
} else {
result.index = undefined;
await result.save();
console.log('Record Updated Successfully.');
}
})
.catrch(err => {
console.log('Error: ', err);
});
`
You can do this to bring the document and then make the required element as undefined and then you can save the modified document back to the database.
Else you can have a better and optimized approach.
`db.doc.update( { _id: 1 }, { $pop: { products: -1 } } )`
Here the first element from the product array will be deleted.
Note: this is the MongoDB shell syntax.

Mongoose find query gives results in wrong order

I am saving an updated array of _id's to an array on a document. If I check the document, everything is updating quite nicely, but when I populate right afterward using a new find query, it doesn't work right. populate wasn't working for me, so I decided to handle it manually and I am successful at filling them in, but they're in the wrong order.
export function sort_update(req, res) {
Action.findOneAndUpdate({
_id: req.query.action
}, {
child_actions: req.body.newArray
}, {
useFindAndModify: false, new: true
}, function(err, doc) {
if (err) return res.send(500, {
error: err
});
console.log("child action id strings after update", doc.child_actions); // ["1", "2"] correct!
Action.find({'_id': {$in: doc.child_actions }}, function(err, child_action_docs) {
if (err) return res.send(500, {
error: err
});
console.log("child action objects after fill", child_action_docs); // [{ _id: "2" }, { _id: "1" }] wrong!
doc.child_actions = child_action_docs;
res.send(doc);
});
});
}
Why are they in the wrong order? Does {'_id': {$in: doc.child_actions }} simply not guarantee any order at all? Do I have to re-sort my objects to the doc.child_actions order deliberately or is there a simpler way of telling mongodb to keep the order in the original array?

mongoose Update object without "drop"

i have there a problem with mongoose & update documents.
when i upate a object in a collection then it "clear/drop" the object, and fill it with the to update object. But i need to "add/merge" the objects.
As Example:
Model.update({name: "hello"}, {
name: "hello",
datum: {
updated: Date.now(),
//added: Date.now()
}
}, function(err, data){
console.log(err, data);
});
This replace my "datum" object with on field: "updated.
The "added" filed is deleted. WHY ?
How can i update the nested "datum" object ?
You need to use the $set operator. If you don't specify it, the first document that matches your query document (1st parameter) will get replaced by your update document (2nd parameter) :
Model.update({name: "hello"}, {
$set: {
"datum.updated": Date.now()
}
}, function(err, data){
console.log(err, data);
});

Mongoose findById returning null for first object when the object exists

Mongoose is returning null for the first object, _ID 0, in the DB even though it exists. I can retrieve the first post just fine using similar code, but I can not retrieve the first tag. I can retrieve all of my data with the exception of the first Tag, tag1 for the first post. If I add a second post with tags: tag4, tag5 and tag6 I can retrieve all of the data for the second post including tag4. If I point to tag1 in a later post it cannot be retrieved.
I have done some of searching and know that null being returned means that the record can't be found. I have also tried using find and findOne in addition to findById and get the same result. I can't figure out where I'm going wrong if the record exists. I'm sure there is probably a better way of doing it.
Thanks for the help.
I'm using mongoose, mongoose-simpledb, and tungus with node-webkit.
Save Tags:
$.each(tagArray, function(i, t) {
var tags = db.Tags();
tags.nextCount(function(err, count) {
post.tags.push(count + i); //tag ID to post
});
tags.text= tagArray[i]; //tag text
post.nextCount(function(err, count) {
tags.posts.push(count); //post ID to tag
});
tags.save(function(err) {
if (err) {throw err;}
console.log('tag saved');
});
});
Find Tags:
$.each(results[i].tags, function(j, t) {
db.Tags.findById(results[i].tags[j], function(err, tag) {
if (err) {return console.error(err);}
if (!tag) {return console.log('Could not find tag...');}
postContent += '' + tag.text + ' ';
});
});
Or if I use the following tag2 is returned instead of tag1 which is what should be returned.
db.Posts.
find({}).
populate('tags').
exec(function(error, post) {
console.log(post[0].tags[0].text);
});
Tags Model
var ObjectId = require('mongoose-simpledb').Types.ObjectId;
exports.schema = {
_id: Number,
text: String,
posts: [{type: ObjectId, ref: 'Posts', index: true}]
};
Tags DB
{"k":"0000000078","o":"0000000061","v":"001"}
{"_id":0,"_uid":1,"_dt":1409869458919,"_s":"c245621efdb176d3f4dd2db749590730"}
{"_id":0,"text":"Tag1","posts":[{"$wrap":"$oid","v":0}],"__v":0}
{"k":"0000000078","o":"0000000061","v":"001"}
{"_id":1,"_uid":1,"_dt":1409869458921,"_s":"80bc4453ee777de0177b27ba76ddc859"}
{"_id":1,"text":"Tag2","posts":[{"$wrap":"$oid","v":0}],"__v":0}
{"k":"0000000078","o":"0000000061","v":"001"}
{"_id":2,"_uid":1,"_dt":1409869458930,"_s":"12682b1c27ea57e8c09b87a2a6605510"}
{"_id":2,"text":"Tag3","posts":[{"$wrap":"$oid","v":0}],"__v":0}
Using find on the Tags DB:
db.Tags.findOne({
_id: '0'
}, function(err, result) {
if (err) return console.error(err);
console.dir('findOne: ' +result.text);
//throws error - Cannot read property 'text' of null
});
db.Tags.
findById(0, function(err, tag) {
if (err) return console.error(err);
console.log('tag by id: ' + tag);
//returns - null
});
db.Tags.
find({}).
exec(function(error, tag) {
console.log("find:" + tag[0]);
//returns - ( _id: 0, text: 'Tag1', _v: 0, posts: [0] )
//correctly finding the tag but not by id
});
If I change these find functions to find any tag other than the first tag, the correct information is returned.
The issue turned out to be mongoose-simpledb. I'm not sure if the issue is a bug in mongoose-simpledb or a conflict with tungus, but the "same" code works fine once mongoose-simpledb is removed.

Resources