Conditional update of multiple entries in mongodb? - mongodb

I am a relative newbie in mongodb but have lots of experience in MySQL.
I want to do a simple query that would appear in MySQL as follows:
UPDATE {database}.{table} SET {FIELD1}='{VALUE1}' WHERE {FIELD2} = {VALUE2};
e.g.
UPDATE test.user SET email='test#acc.ie' WHERE ref='12';
I don't want to destroy the database or collection on my first attempt.
I have only ever ran SELECT type queries on mongo, edited individual json entries or dropped an entire database. A select in mongodb looks like the following
db.getCollection('user').find({email : "test#acc.ie"})
Is the following correct based on the MySQL example?
db.user.update({ref : "12"}, {$set: {email: test#ac.ie}}, { multi: true })
Because this is the response I am getting:
Updated 0 record(s) in 141ms

The syntax looks ok, you will get an error with how you are accessing the collection currently, change it to
db.user.update({ref: 12}, {$set: {email: 'test#ac.ie'}}, { multi: true })
or
db.getCollection('user').update({ref: 12}, {$set: {email: 'test#ac.ie'}}, { multi: true })
Note: the value of the field being set should be quoted if it's a string and unquote if a number. Best read the manual for better referencing.

Related

Sailsjs find where field is not set

I have a project in SailsJs, using waterline with a mongodb database.
I have some fields defined, which are not required fields.
I need to search records where that field is not defined. For example:
{id: 10, name: "jj"}
{id: 11, name: "kk", surname: "sr"}
I want to search where surname is not defined. Anybody has a clue how to do this?
I have tried
{surname: null}
{surname: ''}
Nothing produces the desired result.
I think what you want is Model.find( {where: {surname: null } }) Check out this link to Waterline Query language documentation
I think what you want is $exists: false. It is currently not supported by waterline. You can use Model.native() to use it.
Waterline native()
It returns MongoDB collection and you can use there native MongoDB operations:
MongoDB $exists
Complete code will look more like this
Model.native(function(err, collection) {
if (err) throw err;
collection.find({
surname: { $exists: false}
}).toArray(yourCallback);
});

MongoDB Insert Field to all documents in a collection

I am trying to add a new field into all documents in an existing collection.
Database name = test
Collection name = teams
test.teams.update({
}
,
{
$set: {
"isGolden": false
}
}
,
false,
true)
When I am trying it with MongoChef, it is giving me the following error:
What is wrong with this?
Thanks
If you want to update all the documents, use something like this:
db.teams.update({}, {$set: {isGolden: false}}, {multi: true});
your are selecting all, setting the field isGolden to false and making this update in all documents using multi: true
With MongoDB 3.2 or higher version, you can do
db.teams.updateMany({}, {$set: {isGolden: false}});
Here's the doc for updateMany function db.collection.updateMany()
With Studio 3T you were writing queries in JSON mode in which it wants JSON data but you are not writing JSON Query. You must go to InteliShell mode in which your query will execute in format that you were writing.

mongodb: upserting: only set value if document is being inserted

Considering a simple mongo document structure:
{ _id, firstTime, lastTime }
The client needs to insert a document with a known ID, or update an existing document. The 'lastTime' should always be set to some latest time. For the 'firstTime', if a document is being inserted, then the 'firstTime' should be set to current time. However, if the document is already created, then 'firstTime' remain unchanged. I would like to do it purely with upserts (to avoid look ups).
I've crawled the http://www.mongodb.org/display/DOCS/Updating, but I just don't see how that particular operation can be done.
I don't believe this is something unreasonable, there are $push and $addToSet operations that effectively do that on array fields, just nothing that would do the same on simple fields. It's like there should be something like $setIf operation.
I ran into the exact same problem and there was no simple solution for <2.4 however since 2.4 the $setOnInsert operator let's you do exactly that.
db.collection.update( <query>,
{ $setOnInsert: { "firstTime": <TIMESTAMP> } },
{ upsert: true }
)
See the 2.4 release notes of setOnInsert for more info.
I ran into a very similar problem when attempting to upsert documents based on existing content--maybe this solution will work for you also:
Try removing the _id attribute from your record and only use it in the query portion of your update (you'll have to translate from pymongo speak...)
myid = doc.get('_id')
del doc['_id']
mycollection.update({'_id':myid}, {'$set':doc}, upsert=True)
If you will trigger the following code 2 subsequent times, it will first set both firstVisit and lastVisit on document insert (and will return upsertedId in the response) and on the second it will only update lastVisit (and will return modifiedCount: 1).
Tested with Mongo 4.0.5 though I believe should be working with older versions.
db.collection.updateOne(
{_id: 1},
{
$set: {
lastVisit: Date.now()
},
$setOnInsert: {
firstVisit: Date.now()
}
},
{ upsert: true }
);
There's no way to do this with just one upsert. You'd have to do it as 2 operations - first try to insert the document, if it already exists the insert will fail due to duplicate key violation on the _id index. Then you do an update operation to set the lastTime to now.

MongoDB: update every document on one field

I have a collected named foo hypothetically.
Each instance of foo has a field called lastLookedAt which is a UNIX timestamp since epoch. I'd like to be able to go through the MongoDB client and set that timestamp for all existing documents (about 20,000 of them) to the current timestamp.
What's the best way of handling this?
Regardless of the version, for your example, the <update> is:
{ $set: { lastLookedAt: Date.now() / 1000 } }
However, depending on your version of MongoDB, the query will look different. Regardless of version, the key is that the empty condition {} will match any document. In the Mongo shell, or with any MongoDB client:
$version >= 3.2:
db.foo.updateMany( {}, <update> )
{} is the condition (the empty condition matches any document)
3.2 > $version >= 2.2:
db.foo.update( {}, <update>, { multi: true } )
{} is the condition (the empty condition matches any document)
{multi: true} is the "update multiple documents" option
$version < 2.2:
db.foo.update( {}, <update>, false, true )
{} is the condition (the empty condition matches any document)
false is for the "upsert" parameter
true is for the "multi" parameter (update multiple records)
This code will be helpful for you
Model.update({
'type': "newuser"
}, {
$set: {
email: "abc#gmail.com",
phoneNumber:"0123456789"
}
}, {
multi: true
},
function(err, result) {
console.log(result);
console.log(err);
})
I have been using MongoDB .NET driver for a little over a month now. If I were to do it using .NET driver, I would use Update method on the collection object. First, I will construct a query that will get me all the documents I am interested in and do an Update on the fields I want to change. Update in Mongo only affects the first document and to update all documents resulting from the query one needs to use 'Multi' update flag. Sample code follows...
var collection = db.GetCollection("Foo");
var query = Query.GTE("No", 1); // need to construct in such a way that it will give all 20K //docs.
var update = Update.Set("timestamp", datetime.UtcNow);
collection.Update(query, update, UpdateFlags.Multi);
You can use updateMany() methods of mongodb to update multiple document
Simple query is like this
db.collection.updateMany(filter, update, options)
For more doc of uppdateMany read here
As per your requirement the update code will be like this:
User.updateMany({"created": false}, {"$set":{"created": true}});
here you need to use $set because you just want to change created from true to false. For ref. If you want to change entire doc then you don't need to use $set

Add new field to every document in a MongoDB collection

How can I add a new field to every document in an existent collection?
I know how to update an existing document's field but not how to add a new field to every document in a collection. How can I do this in the mongo shell?
Same as the updating existing collection field, $set will add a new fields if the specified field does not exist.
Check out this example:
> db.foo.find()
> db.foo.insert({"test":"a"})
> db.foo.find()
{ "_id" : ObjectId("4e93037bbf6f1dd3a0a9541a"), "test" : "a" }
> item = db.foo.findOne()
{ "_id" : ObjectId("4e93037bbf6f1dd3a0a9541a"), "test" : "a" }
> db.foo.update({"_id" :ObjectId("4e93037bbf6f1dd3a0a9541a") },{$set : {"new_field":1}})
> db.foo.find()
{ "_id" : ObjectId("4e93037bbf6f1dd3a0a9541a"), "new_field" : 1, "test" : "a" }
EDIT:
In case you want to add a new_field to all your collection, you have to use empty selector, and set multi flag to true (last param) to update all the documents
db.your_collection.update(
{},
{ $set: {"new_field": 1} },
false,
true
)
EDIT:
In the above example last 2 fields false, true specifies the upsert and multi flags.
Upsert: If set to true, creates a new document when no document matches the query criteria.
Multi: If set to true, updates multiple documents that meet the query criteria. If set to false, updates one document.
This is for Mongo versions prior to 2.2. For latest versions the query is changed a bit
db.your_collection.update({},
{$set : {"new_field":1}},
{upsert:false,
multi:true})
Since MongoDB version 3.2 you can use updateMany():
> db.yourCollection.updateMany({}, {$set:{"someField": "someValue"}})
To clarify, the syntax is as follows for MongoDB version 4.0.x:
db.collection.update({},{$set: {"new_field*":1}},false,true)
Here is a working example adding a published field to the articles collection and setting the field's value to true:
db.articles.update({},{$set: {"published":true}},false,true)
db.collection.updateMany({}, {$set: {"fieldName": ""}})
updateMany requires a matching condition for each document, since we are passing {} it is always true. And the second argument uses $set operator to add the required field in each document.
Pymongo 3.9+
update() is now deprecated and you should use replace_one(), update_one(), or update_many() instead.
In my case I used update_many() and it solved my issue:
db.your_collection.update_many({}, {"$set": {"new_field": "value"}}, upsert=False, array_filters=None)
if you are using mongoose try this,after mongoose connection
async ()=> await Mongoose.model("collectionName").updateMany({}, {$set: {newField: value}})
The answers above does't cover this scenario. I was looking for the similar query but want to add fields to few documents based on condition.
So, we can use first variable of updateMany to update fields only in few documents.
Example: I want to add a nullable field isDeprecated? to all those Users whose userType is Employer and has country "AAA".
db.users.updateMany({"userType": "Employer", "country": "AAA"}, {"$set": { "isDeprecated?": true }})
This answer will be helpful in those scenarios as well, where we have to find the collection and then update. This can we done in single query like mentioned.