Pull only one element from and Array in Mongoose - node.js

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.

Related

mongoose: findOne using mongo _id

I get that this can be a duplicated question. I looked up at least 10 related questions and answers, but I am still not able to find the document.
I am trying to get the document using .findOne(). I have the _id that created by MongoDB. But, I get null for every search I try.
await mongoose.connection.db
.collection('testing')
.findOne({ _id: req.body.test_id }, (err, result) => {
if (err) {
res.status(400);
} else {
console.log(`whaaaaaahsidufh ${result}`);
}
});
I tried _id: mongoose.Type.ObjectId(req.body.test_id) and other possible way to search. How can I retrieve the result by using _id on mongoose?
you can use findById();
try {
const test = await mongoose.connection.db.collection('testing').findById(req.body.test_id);
if (test ) {
console.log(`whaaaaaahsidufh ${test}`);
} else {
console.log(`test not found`);
}
}catch(err){
res.status(400);
}

CosmosDB + MongoAPI, updating document workaround?

I've been trying to simply update a CosmosDB document via the mongodb api in my node application, I've been testing in and out, no errors but the value does not update no matter what.
I know updating array elements is not supported which is fine, but this is a top-level key-value pair. Changes simply don't happen with no error whatsoever.
I've been following the Mean.js project with uses CosmosDB + Mongoose + Node + Angular, looking at the API for updating hero and trying some of that code but it still doesn't update.
I've been reading the documentation trying to figure out the default way of handling CRUD operations within CosmosDB and which parts of the MongoAPI it supports but so far no luck.
For tests purposes, I'm using this code:
async function updateUser(id) {
try {
let user = await User.findById(id);
console.log (id);
console.log(user);
if (!user) return
user.id = id
user.firstName = 'ASDASDASASDASDASDASDASDA'
const result = await user.save()
console.log(result);
}
catch(err) {
console.log("There was an error updating user", err);
}
}
So, I've been playing around some more and managed to update a hero using this code:
updateHero('10')
async function updateHero(id) {
const originalHero = {
uid: id,
name: 'Hero2',
saying: 'nothing'
};
Hero.findOne({ uid: id }, (error, hero) => {
hero.name = originalHero.name;
hero.saying = originalHero.saying;
hero.save(error => {
return(hero);
console.log('Hero updated successfully!');
});
});
}
Now I'm just not sure why this has actually worked and why it hasn't before. The main thing that is different is that I'm using an 'uid' instead of the actual ID assigned by CosmosDB.
I tested sample code you provided and they both updated document successfully.
Sample document:
Snippet One:
updateUser('5b46eb0ee1a2f12ea0af307f')
async function updateUser(id) {
try {
let user = await Family.findById(id);
console.log (id);
console.log(user);
if (!user) return
user.id = id
user.name = 'ASDASDASASDASDASDASDASDA'
const result = await user.save()
console.log(result);
}
catch(err) {
console.log("There was an error updating user", err);
}
}
Output One:
Snippet Two:
updateFamily('5b46eb0ee1a2f12ea0af307f')
async function updateFamily(id) {
const updateFamily = {
_id: id,
name: 'ABCD',
};
Family.findOne({ _id : id }, (error, family) => {
family.name = updateFamily.name;
family.save(error => {
console.log(JSON.stringify(family));
console.log('Hero updated successfully!');
return(family);
});
});
}
Output Two:
In addition, you could use db.collection.update() to update document.
db.families.update(
{ _id: '5b46eb0ee1a2f12ea0af307f' },{ $set:
{
name: 'AAAA'
}
})
More details,please refer to the doc: https://docs.mongodb.com/manual/reference/method/db.collection.update/
Hope it helps you.

Making a double query ( Find inside a Find) in Mongoose

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);
});

Selecting only modified subdocument from Mongo

I have a mongoose query like this:
var query = Events.findOneAndUpdate({ '_id': event._id,'participants._id':participant._id},{'$set': {'participants.$': participant}}, {upsert:false,new: true},function(err,result){
if(err){
return res.status(500).jsonp({
error: 'Unable to update participant'
});
}
console.log(result.participants[0]);
res.jsonp(result.participants[0]);
});
and the query works properly modifying the participants subdocument inside Events collection.
The problem:
I need only the modified participant to be returned as JSON and I am not in need of the entire participants array but I am not able to achieve this since I get all the participants when I do console.log(result.participants);
How do I get only the modified subdocument after the query?
You may have to use the native JS filter() method as in the following:
Events.findOneAndUpdate(
{ '_id': event._id, 'participants._id': participant._id },
{ '$set': { 'participants.$': participant } },
{ upsert: false, new: true },
function(err, result){
if(err){
return res.status(500).jsonp({
error: 'Unable to update participant'
});
}
var modified = result.participants.filter(function(p){
return p._id === participant._id
})[0];
console.log(modified);
res.jsonp(modified);
}
);

mongodb/mongoose findMany - find all documents with IDs listed in array

I have an array of _ids and I want to get all docs accordingly, what's the best way to do it ?
Something like ...
// doesn't work ... of course ...
model.find({
'_id' : [
'4ed3ede8844f0f351100000c',
'4ed3f117a844e0471100000d',
'4ed3f18132f50c491100000e'
]
}, function(err, docs){
console.log(docs);
});
The array might contain hundreds of _ids.
The find function in mongoose is a full query to mongoDB. This means you can use the handy mongoDB $in clause, which works just like the SQL version of the same.
model.find({
'_id': { $in: [
mongoose.Types.ObjectId('4ed3ede8844f0f351100000c'),
mongoose.Types.ObjectId('4ed3f117a844e0471100000d'),
mongoose.Types.ObjectId('4ed3f18132f50c491100000e')
]}
}, function(err, docs){
console.log(docs);
});
This method will work well even for arrays containing tens of thousands of ids. (See Efficiently determine the owner of a record)
I would recommend that anybody working with mongoDB read through the Advanced Queries section of the excellent Official mongoDB Docs
Ids is the array of object ids:
const ids = [
'4ed3ede8844f0f351100000c',
'4ed3f117a844e0471100000d',
'4ed3f18132f50c491100000e',
];
Using Mongoose with callback:
Model.find().where('_id').in(ids).exec((err, records) => {});
Using Mongoose with async function:
const records = await Model.find().where('_id').in(ids).exec();
Or more concise:
const records = await Model.find({ '_id': { $in: ids } });
Don't forget to change Model with your actual model.
Combining Daniel's and snnsnn's answers:
let ids = ['id1', 'id2', 'id3'];
let data = await MyModel.find({
'_id': {
$in: ids
}
});
Simple and clean code. It works and tested against:
"mongodb": "^3.6.0",
"mongoose": "^5.10.0",
Use this format of querying
let arr = _categories.map(ele => new mongoose.Types.ObjectId(ele.id));
Item.find({ vendorId: mongoose.Types.ObjectId(_vendorId) , status:'Active'})
.where('category')
.in(arr)
.exec();
This code works for me just fine as of mongoDB v4.2 and mongoose 5.9.9:
const Ids = ['id1','id2','id3']
const results = await Model.find({ _id: Ids})
and the Ids can be of type ObjectId or String
Both node.js and MongoChef force me to convert to ObjectId. This is what I use to grab a list of users from the DB and fetch a few properties. Mind the type conversion on line 8.
// this will complement the list with userName and userPhotoUrl
// based on userId field in each item
augmentUserInfo = function(list, callback) {
var userIds = [];
var users = []; // shortcut to find them faster afterwards
for (l in list) { // first build the search array
var o = list[l];
if (o.userId) {
userIds.push(new mongoose.Types.ObjectId(o.userId)); // for Mongo query
users[o.userId] = o; // to find the user quickly afterwards
}
}
db.collection("users").find({
_id: {
$in: userIds
}
}).each(function(err, user) {
if (err) {
callback(err, list);
} else {
if (user && user._id) {
users[user._id].userName = user.fName;
users[user._id].userPhotoUrl = user.userPhotoUrl;
} else { // end of list
callback(null, list);
}
}
});
}
if you are using the async-await syntax you can use
const allPerformanceIds = ["id1", "id2", "id3"];
const findPerformances = await Performance.find({
_id: {
$in: allPerformanceIds
}
});
I tried like below and it works for me.
var array_ids = [1, 2, 6, 9]; // your array of ids
model.find({
'_id': {
$in: array_ids
}
}).toArray(function(err, data) {
if (err) {
logger.winston.error(err);
} else {
console.log("data", data);
}
});
I am using this query to find the files in mongo GridFs. I wanted to get the by its Ids.
For me this solution is working: Ids type of ObjectId.
gfs.files
.find({ _id: mongoose.Types.ObjectId('618d1c8176b8df2f99f23ccb') })
.toArray((err, files) => {
if (!files || files.length === 0) {
return res.json('no file exist');
}
return res.json(files);
next();
});
This is not working: Id type of string
gfs.files
.find({ _id: '618d1c8176b8df2f99f23ccb' })
.toArray((err, files) => {
if (!files || files.length === 0) {
return res.json('no file exist');
}
return res.json(files);
next();
});

Resources