mongoengine bulk update fields with JSON - mongodb

I am new to Mongodb and Mongoengine. And I am wondering if there is a way to bulk update MongoDB fields with a json script, for instance:
jsonData = {'name': 'Stak', 'password':'oVeRfLoW'}
User.objects.get(username='u_name').update(jsonData)
Thanks for your answers!

Mongodb's built-in update function, db.collection.update() is very customizable, has options for updating multiple documents at once and doesn't require getting anything beforehand.
You can use it like so:
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
So in this case:
db.collection.update(
{username:'u_name'}, //1
{$set:jsonData}, // 2
{
multi: true, // 3
}
)
(
the query searches for documents that have
$set is IMPORTANT! If you do not use $set, your entire document will be erased and updated to a document containing only your new values. (it will delete all the other fields)
Update multiple documents at once.
Keep in mind this is a guideline and you'll have to modify the above code a bit.

Related

mongodb upsert with condition

is there a way with mongodb to bulk upsert but choose what to do when inserting and when updating.
for example:
I have this document in the mongodb:
{name:"david", last_name:"family_name", published:true}
now arrives a new document that is like this:
{name:"david", last_name:"family_name_changed", published:false}
now I want to replace the document that is in the DB (document 1)
that will only update the last_name field (or any other field) but I dont want it to update the published field. (ever)
what is the way to do that?
thank you
You can use $set to update a specific field, for instance:
db.<name of your collection>.update(<query>,
{
$set:
{
last_name: <value to set>
}
}, { multi: true } );

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.

Add a new field point type filed to a collection with value of an existing field

I have a huge mongodb collection with 6 million records. I have two fields (latitude, longitude), and I would like to add a third field to the collection with the type of point (spatial). How to do this in command line or PHP?
It you'd like to add a new field (with the same value) to all documents in a collection, that can be done easily with an update() operation. Consider the following shell example:
db.collection.update(
{},
{ $set: { type: "spatial" }},
{ multi: true }
);
This would set the type field to "spatial" for all documents matching empty criteria {} (i.e. everything), and the multi option allows the update to modify multiple documents instead of just the first document matched (default behavior).
If you only wanted to set the type field where it doesn't already exist, you could tweak the criteria like so:
db.collection.update(
{ type: { $exists: false }},
{ $set: { type: "spatial" }},
{ multi: true }
);
Since you're storing geospatial data, you may want to have a look at MongoDB's 2dsphere indexes. This would allow you to store and index well-formed GeoJSON objects in your document. See this previous answer from a related question for more introductory information on the subject.

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