how can i use value of field in mongoose aggregation? (nodejs) - node.js

how can i use value of field in mongoose aggregation?
i tried with latest version of mongodb, mongoose.
Group.find({name:'1'},function(err,groups){
groups.forEach(function(g){
result=await People.countDocuments({group:g._id})
});
});
I already checked that 'result' of this code is 3, 5, 2
i want to use aggregate
Group.aggregate()
.project({_id:true,name:true})
.addFields({numOfPeople: await People.countDocuments({group:this._id})});
output
[{name:'1',numOfPeople:0},
{name:'2',numOfPeople:0},
{name:'3',numOfPeople:0}]
expected
[{name:'1',numOfPeople:3},
{name:'2',numOfPeople:5},
{name:'3',numOfPeople:2}]

You have to use group by
db.groups.aggregate(
[
{
$group : {
_id : "$name",
numOfPeople: { $sum: 1 }
}
}
]
);

Related

How to update a value in a mongoose document?

I am trying to modify a piece of code written by another person.
I need to update a mongodb document rather than removing it.
Here is the code :
const docs = await docsModel.find({});
for (const doc of docs) {
doc.remove();
}
I need to update rather than remove. I've tried this :
const docs = await docsModel.find({});
for (const doc of docs) {
doc.updateOne({field_I_want_to_update : "new_value"});
}
But it doesn't work.
Any suggestion ?
Depends on situation.
If you want to update multiple document with the same value, then better would be:
doc.updateMany(<filter>, { $set: { field_I_want_to_update : "new_value" } });
Where: <filter> would be something like: { _id: <validId> } or { _id: { $in: [<array_of_ids>] } }
If you want to update multiple documents with dynamic values, then this would work:
const docs = await docsModel.find({});
docs.forEach(function(doc) {
await docsModel.updateOne({ _id: doc._id }, { $set: { field_I_want_to_update: "new_dynamic_value" } });
});
Comparing to your case, you're missing <filter> as the first parameter, and in second you need to start with $set: { <field>: <value> } rather with { <field>: <value> }
You can use mongoose updateMany function which takes in a filter and an object of keys and values to update. wrap the object in a $set property. In theory, you could for-loop and use findByIdAndUpdate but that's a resource hog.
So something like
await docsModel.updateMany({}, {$set: { /*insert field name*/: /*insert field value*/ } });

How do I update data in mongo

So I am currently working on a project with mongodb and nodejs and I was wondering, how can you update data in mongodb via nodejs? My problem is that I want to keep the old data and add new. For example, here is the data currently in my mongodb
{
"_id" : ObjectId("5a1c0c1c3b147ec2e31cceb3"),
"event_id" : "1",
"event_medium" : "null",
"event_tags" : ["#JustTesting"]
}
So I want to add new data to the event_tags array and still keep the old data.
So for example the end result would be this:
{
"_id" : ObjectId("5a1c0c1c3b147ec2e31cceb3"),
"event_id" : "1",
"event_medium" : "null",
"event_tags" : ["#JustTesting", "#Test", "#Something"]
}
You should use the update function of MongoDB for that. MongoDB knows different update operators, in your case you may use $push or $pushAll (the second is deprecated):
update one after the other with $push
YourCollection.update({ _id: 'xxx' }, { $push: { event_tags: '#Test' } });
YourCollection.update({ _id: 'xxx' }, { $push: { event_tags: '#Something' } });
or both at once with $pushAll (deprecated now)
YourCollection.update({ _id: 'xxx' }, { $pushAll: { event_tags: ['#Test', '#Something'] } });
To interact with MongoDB form your NodeJS app, I would use a library like this one.
Your starting point is the Update function in CRUD (Create,Read, Update, Delete) operations in Mongodb.
Your node program should have among others the update function where you set the _id field you want to update and load the content fields to be update in 'data' for example as below:
myModel.prototype.update = function (_id, data, callback) {
const query = { _id: this.mongo.ObjectId(_id) };
debug(' update:' + JSON.stringify(query));
this.mongo.collection('mycollection').update(query, data, callback);
};
This piece of code should be put in your Model, if you use MVC pattern.
There is a lot to go.
Honestly I recommend a more deep tutorial like parts 3 and 4 of this one for nodejs and Mongoose (mongo db driver):
MDN tutorial for mongo/node/express
I assume you are using mongoose..
eventModel.findOne({event_id:1 },
function(err, eventObj){
if(err){
//handle error
} else {
if(eventObj === null) {
//event doesnot exist
}
var tagList = eventObj.event_tags;
tagList.push('new_tag1');
tagList.push('new_tag2');
eventObj.event_tags = tagList;
eventObj.save(function(err){
if(err){
//handle error
} else {
//success
}
})

Get 2 documents in 1 MongoDB call

I am using MongoDB and Mongoose to retrieve documents from the database.
I have two IDs and I want to get the corresponding documents. I use
Collection.findById(id1).then(doc1 => {
if (doc1) {
Collection.findById(id2).then(doc2 => {
if (doc2) {
Is it possible to do this in a single call?
I am wondering if it can be done with
{doc1, doc2} = Collection.find({ _id: $in: [id1, id2] });
and if this is better than my original approach.
You can use mongoDB $in operator to retrieve multiple documents, the syntax is
db.inventory.find( { id: { $in: [ 5, 15 ] } } )

Should I be using Mongoose queries in Feathersjs hooks

I have a Mongodb based Feathers service : Categories and the model is as follows
{
_id : 'SOMEKEY',
categoryName : 'XYZ'
categoryItems : [
{ item_id : 'ITEMID' }
]
}
Now I have After hooks on my Items service that on each Create I want to push the reference of that Item into the categoryItems array in the Categories document. How can I achieve that ? Neither of the built in methods for Category service will help.
Should I be writing Mongoose queries within my hook? If I do that I am depending on Mongoose MongoDB and if my database changes I will have to change all my hooks.
const categoryService = hook.app.service('categories');
categoryService.update(hook.data.item_category,
{
$push: {
"category_items": {
item_id: hook.result._id
}
}
},
{
safe: true, // This value is safely stored in the DB
upsert: true // It creates a new object if
// a previous one does not exist
});

FeathersJS Mongoose: Updating matched sub-document not working

I want to update a value of a sub-document where a message has a specific id and an user id is in a recipient array. I want to update a value of the matched object with the specified user id.
When I run the following query on the MongoDB CLI, everything works and the value is updated:
db.getCollection('messages').update({
_id : ObjectId("57d7edb8c497a75a6a7fde60"),
"recipients.userId" : "5789127ae2bcc79326462dbc"
},{
$set : {"recipients.$.read": true}
});
But when I run the following query via JS in my FeathersJS application:
messageService.update({
_id : '57d7edb8c497a75a6a7fde60',
"recipients.userId" : "5789127ae2bcc79326462dbc"
},{
$set: {"recipients.$.read": true}
}).then(function(e) {
console.log(e)
}).catch(function(e) {
console.log(e);
});
I get the error:
GeneralError: The positional operator did not find the match needed from the query. Unexpanded update: recipients.$.read
What am I doing wrong?
And is there a better way of updating many messages at once?
Thanks!
For updating one or multiple records by a query you need to call the service method by setting id to null and putting the query into params.query:
messageService.update(null, {
$set: {"recipients.$.read": true}
}, {
query: {
_id : '57d7edb8c497a75a6a7fde60',
"recipients.userId" : "5789127ae2bcc79326462dbc"
}
}).then(function(e) {
console.log(e)
}).catch(function(e) {
console.log(e);
});

Resources