Update a value inside array of objects, inside a document in MongoDB - node.js

Here is what my collection looks like
Now suppose I have to update count of 2nd document whose reportTypes.reasonId is 300. I have access to _id as well as reasonId to update the count. I am using Mongoose to query things in my Node application.
What can I try to solve this?

You can do it via arrayFilters:
db.collection.update(
{
managerId:3
},
{
$inc:{"reportTypes.$[x].count":1}
},
{
arrayFilters:[{"x.reasonId":300 }]
}
)
playground
Explained:
Specify the matching document in the query part and create arrayFilter "x" matching the correct reportTYpes array subdocument , in the update part use the $inc operation to increment the count value in the example with 1

you should use dot notation and the $ update operator to do this:
(I'm assuming your collection is called Reason)
var conditions = {
'_id': '6244........',
'reasonTypes.reasonId': 300
}
var update = {
$inc: {
'reasonTypes.$.count': 1
}
};
Reason.update(conditions, update, function(err) {
// Handle error here
})
You can find more on the operator here mongo $ update operator

Related

Update collection field and array

I want to update a field and array inside a mongodb collection.
myCollection.
{
position:String,
users : [String]
}
I know how to update the position using:
myCollection.updateOne({position:position})
I know how to update the users array using:
myCollection.updateOne({position:position}, { $addToSet: {users:users})
But how to update the two at the same time?
Thanks a lot guys. Backend noob here!
The first parameter of updateOne is the filter, so by running this query:
myCollection.updateOne({ position }, {
$set: { position: newPosition },
$addToSet: { users }
})
You should update the position of the document with position to newPosition and add a new users to the users array

NodeJS MongoDb updateMany() with a condition?

I want to update a MongoDb collection with an Array of JSON objects.
However, I want the update to ignore any objects that already exist in the DB.
Sounds easy, but the key that allows me to know if the object exists is not the '_id', but a different 'id' (or other key).
Is that possible ?
Currently I am using it like this:
dbHandle.collection('contents').updateMany(contents);
where 'contents' is the Array of JSON objects.
Thanks in advance
The following operation updates all documents where violations are greater than 4 and $set a flag for review:
try {
db.restaurant.updateMany(
{ violations: { $gt: 4 } }, //Your Condition
{ $set: { "Review" : true } } //YOUR JSON contents
);
} catch (e) {
print(e);
}
Change the condition accordingly.

Mongoose, Nodejs - replace many documents in one I/O?

I have an array of objects and I want to store them in a collection using only one I/O operation if it's possible. If any document already exists in the collection I want to replace it, or insert it otherwise.
These are the solutions that I found, but doesn't work exactly as I want:
insertMany(): this doesn't replace the document that already exists, but throws exception instead (This is what I found in the Mongodb documentation, but I don't know if it's the same as mongoose).
update() or ‎updateMany() with upsert = true: this doesn't help me as well, because here I have to do the same updates to all the to stored documents.
‎There is no replaceMany() in mongodb or mongoose.
Is there anyone how knows any optimal way to do replaceMany using mongoose and node.js
There is bulkWrite (https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/), which makes it possible to execute multiple operations at once. In your case, you can use it to perform multiple replaceOne operations with upsert. The code below shows how you can do it with Mongoose:
// Assuming *data* is an array of documents that you want to insert (or replace)
const bulkData = data.map(item => (
{
replaceOne: {
upsert: true,
filter: {
// Filter specification. You must provide a field that
// identifies *item*
},
replacement: item
}
}
));
db.bulkWrite(bulkData);
You need to query like this:
db.getCollection('hotspot').update({
/Your Condition/
}, {
$set: {
"New Key": "Value"
}
}, {
multi: true,
upsert: true
});
It fulfils your requirements..!!!

MongoDB & Mongoose: How do I get the index of the removed item when using pull?

I have to remove an item from an array of subschemas in a document.
SubSchema = new mongoose.Schema({...})
MySchema = new mongoose.Schema({someArray: [SubSchema]})
(...)
mydoc.somearray.pull(req.body.submodel_id);
However, I need the index of the element that has been removed to notify all connected clients.
Is there an elegant solution to this, or do I have to use _.findIndex or something like that? (I imagine that to have worse performance since it unnecessarily iterates the array twice)
Not sure if an elegant solution exists for this as MongoDB has no way of returning the index of the array element
being pulled within an update operation. One approach (though I would consider it a dirty hack) would be to get the original
array after the update operation and get the removed element index using Array.indexOf() within the update callback.
Consider the following update operation using findOneAndUpdate() to get the update document:
var submodel_id = req.body.submodel_id,
query = { "someArray": submodel_id };
Model.findOneAndUpdate(
query,
{ "$pull": { "someArray": submodel_id } },
{ "new": false },
function(err, doc) {
var removedIndex = doc.someArray.indexOf(submodel_id);
console.log(removedIndex);
}
);

Mongoose $ project

Using Mongoose 4.0.x, I need to execute the following (working) MongoDB query:
db.bookings.find(
{
user: ObjectId("10"), // I replaced the real ID
'flights.busy.from': {$gte: ISODate("2015-04-01T00:00:00Z")},
'flights.busy.to': {$lte: ISODate("2015-04-01T23:59:00Z")}
},
{
'flights.$': 1 // This is what I don't know to replicate
}
).pretty()
The Mongoose find operator does not accept a projection operator, like the MongoDB find one does.
How can I replicate the above query in Mongoose? Filtering the array once the query is returned is a solution I would like to avoid.
You want to look at the docs for Model.find, not Query.find. The second parameter can be used for field selection:
MyModel.find(
{
user: ObjectId("10"), // I replaced the real ID
'flights.busy.from': {$gte: ISODate("2015-04-01T00:00:00Z")},
'flights.busy.to': {$lte: ISODate("2015-04-01T23:59:00Z")}
},
'flights.$'
).exec(function(err, docs) {...});

Resources