updateMany based on other field in mongodb - mongodb

I have two documents
/* 1 */
{
"lastUpdated" : ISODate("2019-01-01T01:01:20.201Z"),
"content" : "someText01",
}
/* 2 */
{
"lastUpdated" : ISODate("2020-11-11T16:11:20.202Z"),
"content" : "someText02",
}
Now I would like to update documents - create new field as copy of lastUpdated field;
In robo3T I can do something like this
db.getCollection('someDocuments').update({},
[
{"$set": {"byMongoQuery": "$lastUpdated", }}
],
{"multi": true}
)
And it works.
Now I would like to do same using java code (mongo-java-driver 3.9.0)
And I do something like
mongodb.getCollection("someDocuments").updateMany(Document.parse("{}"), Document.parse("{$set: {'byJavaApi': '$lastUpdated'}}"))
mongodb is instance of com.mongodb.client.MongoDatabase
Final results is like this:
Value is set as plaintext for some reason.
I'm using
Mongodb 4.2.6
mongo-java-driver 3.9.0
Questions:
How to set this field using java code. I would prefer updateMany as there is a lot of those records
Why results are different. I was expecting there is some common engine in mongdb that executes it. And this is exactly the same query.

Your update is using the MongoDB v4.2 feature of updating using a pipeline. You can code this using MongoDB Java Driver v3.11 or higher. Update a field using value from another field:
Bson query = new Document();
List<Bson> updatePipeline = Arrays.asList(Fiters.eq("$set", Filters.eq("byMongoQuery", "$lastUpdated")));
UpdateResult result = collection.updateMany(query, updatePipeline);

Related

Retrieving a single field from MongoDB using Selenium/Java

I'm just switching from MySQL to MongoDB and it's a little confusing. We have our database stored in MongoDB and using Java-Selenium in the front end. I am trying to retrieve just one single data from the database. The code below retrieves all the data present in the database:
DBCursor cursor = dbCollection.find();
while(cursor.hasNext())
{
int i=1;
System.out.println(cursor.next());
i++;
}
This is my database lets say:
{
"name" : "Su_123",
"email" : "test#gmail.com",
"_id" : ObjectId("12345656565656")
}
I want to retrieve just the email field (test#gmail.com) from the document where _id = ObjectId("12345656565656") and store this in a String field.
How do I go about coding this? find() retrieves the entire row.
For newer drivers, since 3.7.1
To get specific document that matches a filter:
Document doc = collection.find(eq("email", "test#gmail.com")).first();
It can be used to find the first document where the field email has the value test#gmail.com. And pass an eq filter object to specify the equality condition.
By the same logic using id:
Document document = myCollection.find(eq("_id", new ObjectId("12345656565656"))).first();
To get specific value of the field from selected document:
String value = (String) doc.get("email");
For older drivers like 2.14.2 and 2.13.3
To get a single document with a query:
BasicDBObject query = new BasicDBObject("email", "test#gmail.com");
cursor = coll.find(query);
try {
while(cursor.hasNext()) {
//System.out.println(cursor.next());
}
} finally {
cursor.close();
}
To see more details for newer Mongodb Java driver.
To see more details for older Mongodb Java driver.
To see more details from Mongodb Official Docs.

MongoDB - update a property with incremental values

I have a collection called dealers as follows.
{
"_id" : ObjectId("5b9ba196cd5f5af83bb0dc71"),
"name" : "SOME COMPANY",
"outletID" : "GS0061920",
"companyID" : "GC0050397"
}
I have about 5000 documents in this collection where outletID and companyID properties are empty.
I would like to update both of these properties for all documents in this collection with incremental values.
I'm not sure how I should go about this.
Note: MongoDB 3.4 is in use.
Assuming you are running on mongodb shell. You can use the following:
> var counter = 1;
> db.collection.find().forEach(
function(elem) {
db.myColl.update(
{ "outletID" : null, "companyID" : null},
{$set:{ outletID: counter , companyID: counter }
});
counter++;
});
The mongo shell is an interactive JavaScript interface. I have used JS for the task. counter is a simple variable which is used to update values. $set is used to update the fields.
The $set operator replaces the value of a field with the specified value. You can find more data in its official documentation.
I created a sample data and tested my function. Hope it works fine.

How to remove _id from MongoDB results?

I am inserting json file into Mongodb(with Scala/Play framework) and the same getting/downloading it into my view page for some other requirement, but this time it is coming with one "_id" parameter in the json file.
But I need only my actual json file only that is not having any any "_id" parameter. I have read the Mongodb tutorial, that by default storing it with one _id for any collection document.
Please let me know that how can I get or is there any chance to get my actual json file without any _id in MongoDB.
this is the json result which is storing in database(I don't need that "_id" parameter)
{
"testjson": [{
"key01": "value1",
"key02": "value02",
"key03": "value03"
}],
"_id": 1
}
If you have a look at ReactiveMongo dev guide and to its API, you can see it support projection in a similar way as the MongoDB shell.
Then you can understand that you can do
collection.find(selector = BSONDocument(), projection = BSONDocument("_id" -> 0))
Or, as you are using JSON serialization:
collection.find(selector = Json.obj(), projection = Json.obj("_id" -> 0))
You can use this query in the shell:
db.testtable.find({},{"_id" : false})
Here we are telling mongoDB not to return _id from the collection.
You can also use 0 instead of false, like this:
db.testtable.find({},{"_id" : 0})
for scala you need to convert it in as per the driver syntax.

Will upsert work with array Elements as well as the normal ID in MongoDB through Java driver

Mongo DB contains the following data:
The requirement is if inside this document an Field exists incremnt the counter else insert the field.
Generally we use upsert for situations when we are not sure if its going to be insert or Update.But will this work with
array Elements as well
db.arrayexample.find()
{ "_id" : "userID", "addresses" : [ { "arrayid" : NumberLong(16694), "count" : 12 } ] }
My Java code is as follows:
MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase mongoDatabase = mongoClient.getDatabase("testdb3");
MongoCollection mongoCollection = mongoDatabase.getCollection("arrayexample");
BasicDBObject query = new BasicDBObject();
query.put("_id", "userID");
query.put("addresses.arrayid",Long.valueOf(16695) );
mongoCollection.findOneAndUpdate(query,new Document("$inc", new Document("addresses.$.count", 1)),new FindOneAndUpdateOptions().upsert(true));
I am getting the following error when i run the Program:
'exception: Cannot apply the positional operator without a corresponding query field containing an array.' on server localhost:27017. The full response is
"value" : null, "errmsg" : "exception: Cannot apply the positional operator without a corresponding query field containing an array.", "code" : 16650,
Will $Upset work with array Elements as well as the normal ID
No, upserts will not work when using the $positional operator, as noted in the MongoDB documentation.
http://docs.mongodb.org/manual/reference/operator/update/positional/#upsert
Edit: As some flavour, it appears that there is an open feature request to support this particular kind of update when combined with the $setOnInsert operator within MongoDB's Jira https://jira.mongodb.org/browse/SERVER-10711

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.