Do not add document to collection if already exist in MongoDB [duplicate] - mongodb

This question already has answers here:
MongoDB atomic "findOrCreate": findOne, insert if nonexistent, but do not update
(4 answers)
Closed 3 years ago.
Is there a way to omit adding/updating document if it was found in the collection without doing two requests to Mongo server? It would be perfect if this can be done in bulk, but I would appreciate to hear other options or workarounds.
What I'm looking for is sort of opposite of upsert option:
var bulk = MyCollection.initializeUnorderedBulkOp();
bulk.find({ x: val }).upsertOnlyIfNotFound({ x: newVal });
bulk.execute();

What you are looking for is $setOnInsert.
db.MyCollection.update(
{ x: val },
{
$setOnInsert: { x: "newVal" }
},
{ upsert: true }
)
From the documentation :
If an update operation with upsert: true results in an insert of a
document, then $setOnInsert assigns the specified values to the fields
in the document. If the update operation does not result in an insert,
$setOnInsert does nothing.

Related

MongoDB query to get all documents matching with key with mutliple values [duplicate]

This question already has answers here:
MongoDB select where in array of _id?
(5 answers)
Closed 1 year ago.
I have documents in mongodb which has a transaction_id. Data type of transaction_id is ObjectId.
If I do below query, I get the document:
db.collection.find({ 'transaction_id': ObjectId('609cfef4ad16361274eb12e2') })
.projection({})
.sort({_id:-1})
.limit(100)
But what if I want to get all the documents for multiple transaction ids. So I did:
db.collection.find({ 'transaction_id': [ObjectId('609cfef4ad16361274eb12e2'), ObjectId('609cfeecad16361274eb12e1')] })
.projection({})
.sort({_id:-1})
.limit(100)
I get no documents. How can I get all the documents for matching transaction ids. Thanks
You can use in operator:
db.collection.find( { 'transaction_id': { $in: [ObjectId('609cfef4ad16361274eb12e2'), ObjectId('609cfeecad16361274eb12e1')] } } )

Mongodb how to insert or update all? [duplicate]

This question already has answers here:
Spring Data Mongo: upsert with various fields updated
(1 answer)
Spring Data MongoDB and Bulk Update
(3 answers)
Closed 3 years ago.
Spring boot mongo repository support saveAll,but it cause unique index insert error ,so I want use update.
In my case,I want to insert or update 10 documents together.
how to use updateAll?
Though I'm not crystal clear on your question, it sounds like you need to append { multi: true } to your update query. Please see Update Multiple Documents.
Setting the multi option updates all documents found by match.
To update multiple documents, set the multi option to true. For
example, the following operation updates all documents where stock is
less than or equal to 10:
db.books.update(
{ stock: { $lte: 10 } },
{ $set: { reorder: true } },
{ multi: true }
)
you can use updateMany:
db.collections.updateMany({ query }, {"$set":{ update }}

Using MongoDB mongo go driver for counters persistent collection [duplicate]

as the title says, I want to perform a find (one) for a document, by _id, and if doesn't exist, have it created, then whether it was found or was created, have it returned in the callback.
I don't want to update it if it exists, as I've read findAndModify does. I have seen many other questions on Stackoverflow regarding this but again, don't wish to update anything.
I am unsure if by creating (of not existing), THAT is actually the update everyone is talking about, it's all so confuzzling :(
Beginning with MongoDB 2.4, it's no longer necessary to rely on a unique index (or any other workaround) for atomic findOrCreate like operations.
This is thanks to the $setOnInsert operator new to 2.4, which allows you to specify updates which should only happen when inserting documents.
This, combined with the upsert option, means you can use findAndModify to achieve an atomic findOrCreate-like operation.
db.collection.findAndModify({
query: { _id: "some potentially existing id" },
update: {
$setOnInsert: { foo: "bar" }
},
new: true, // return new doc if one is upserted
upsert: true // insert the document if it does not exist
})
As $setOnInsert only affects documents being inserted, if an existing document is found, no modification will occur. If no document exists, it will upsert one with the specified _id, then perform the insert only set. In both cases, the document is returned.
Driver Versions > 2
Using the latest driver (> version 2), you'll use findOneAndUpdate as findAndModify was deprecated. The new method takes 3 arguments, the filter, the update object (which contains your default properties, that should be inserted for a new object), and options where you have to specify the upsert operation.
Using the promise syntax, it looks like this:
const result = await collection.findOneAndUpdate(
{ _id: new ObjectId(id) },
{
$setOnInsert: { foo: "bar" },
},
{
returnOriginal: false,
upsert: true,
}
);
const newOrUpdatedDocument = result.value;
Its a bit dirty, but you can just insert it.
Be sure that the key has a unique index on it (if you use the _id it's ok, it's already unique).
In this way if the element is already present it will return an exception that you can catch.
If it isn't present, the new document will be inserted.
Updated: a detailed explanation of this technique on the MongoDB Documentation
Here's what I did (Ruby MongoDB driver):
$db[:tags].update_one({:tag => 'flat'}, {'$set' => {:tag => 'earth' }}, { :upsert => true })}
It will update it if it exists, and insert it if it doesn't.

updating multiple documents by passing a list objectids to findByIdAndUpdate [duplicate]

This question already has answers here:
MongoDB: How to update multiple documents with a single command?
(13 answers)
FindAndModify, return array of Objects
(1 answer)
Closed 5 years ago.
I am trying to use mongoose's findByIdAndUpdate method to pass in a list of object id's and updating them at once. However, I am getting a "Error: Can't use $set with ObjectId." error which I can't seem to associate with my code.
Here's my code.
return ComponentModel.findByIdAndUpdate({
_id: {
$in: input.subjectIds
},
$set: { location: input.newLocation }
}).then(res => res);
findByIdAndUpdate is for one document. For multiple documents you can use update with multi flag true.
return ComponentModel.update(
{_id: {$in: input.subjectIds}},
{$set: {location: input.newLocation}},
{"multi": true}
).then(res => res);

MongoDB : Add field in each array elements [duplicate]

This question already has answers here:
How to Update Multiple Array Elements in mongodb
(16 answers)
Closed 5 years ago.
I'm starting with mongoDB and I want to update a nested array in my documents to add some initial value, but I can't find a way to do it with mong.
here is my document :
{
"_id":"cTZDL7WThChSvsvBT",
"name":"abc",
"players":[
{
"playerName":"Name1"
},
{
"playerName":"Name2"
}
]
}
What I want to do :
{
"_id":"cTZDL7WThChSvsvBT",
"name":"abc",
"players":[
{
"playerName":"Name1",
"NewField1":0,
"NewField2":0
},
{
"playerName":"Name2",
"NewField1":0,
"NewField2":0
}
]
}
Does anyone have a solution for this kind of situation?
This adds the new fields to the player array ...
db.collection.update({_id: 'cTZDL7WThChSvsvBT', players: {$exists: true}}, {$set: {'players.$.NewFieldOne': 0, 'players.$.NewFieldTwo': 0}})
... but since Mongo will only update the first element of an array which matches the query you are a bit stuffed. You can, of course, choose which array element to update by using the positional operator (as in my example) or by choosing a specific element (as the previous poster suggested) but until Mongo supports 'array updates' on all elements I think you're left with a solution such as: find the relevant documents and then update each one (i.e. a client side update solution).
I finally found a way by editing directly the document in JS like this :
db.doc.find({_id: myDocId}).forEach(function (channel) {
channel.players.forEach(function (player) {
player.newField1 = 0;
player.newField2 = 0;
});
db.doc.update({_id: myDocId}, channel);
});
considering you want to update an element which is an object also,
how about this?
db.collections.updateOne({_id: "cTZDL7WThChSvsvBT"}, {$set: {"players.0.NewField1": 0, "players.0.NewField2: 0}});