I'm newbie with the MongoDb, there are a lot of examples about updating a collection in 2.x versions but I couldn't find any source about 3.x versions.
JAVA CODE:
MongoClient mongoClient = new MongoClient("localhost",27017);
MongoDatabase database = mongoClient.getDatabase("dbTest");
MongoCollection<Document> collection = database.getCollection("colTest");
Document updateQuery = new Document();
updateQuery.append("$set",
new Document().append("_id", "test"));
Document searchQuery = new Document();
searchQuery.append("likes", "125");
collection.updateMulti(searchQuery, updateQuery); //.updateMulti gives an error.
There isn't any updateMulti in 3.x so how can I check the id of the database and change one of the datas?
Example MongoDB:
{
"_id" : "test",
"status" : 2,
"time" : null,
"instagram" :{
"description" : "database",
"likes" : 100,
"url" : "http://www.instagram.com/",
"by", "users"
},
"batchid" : 15000234
}
Expected Output:
{
"_id" : "test",
"status" : 1,
"time" : null,
"instagram" :{
"description" : "database",
"likes" : 125,
"url" : "http://www.instagram.com/",
"by", "users"
},
"batchid" : 15000234
}
For Mongodb-java driver:
Use updateOne method
To update single Document within the collection based on the filter,
collection.updateOne(searchQuery, updateQuery );
Use updateMany method,
To Update multiple Documents within the collection based on the filter ,
collection.updateMany(searchQuery, updateQuery );
Example,
MongoClient client = new MongoClient("localhost",27017);
MongoDatabase db = client.getDatabase("TestDB");
MongoCollection<Document> collection = db.getCollection("test");
Document query = new Document();
query.append("_id","test");
Document setData = new Document();
setData.append("status", 1).append("instagram.likes", 125);
Document update = new Document();
update.append("$set", setData);
//To update single Document
collection.updateOne(query, update);
so i wrote this function
public void SetValueFromDB(String collectionName, String id, String id_value, String fieldOfChange, Object changToValue) {
MongoCollection<Document> collection = database.getCollection(collectionName);
BasicDBObject searchQuery = new BasicDBObject();
searchQuery.append(id, id_value);
Document setData = new Document();
setData.append(fieldOfChange, changToValue);
Document updateQuery = new Document();
updateQuery.append("$set", setData);
collection.updateOne(searchQuery, updateQuery);
}
so for use it
db.SetValueFromDB("MyCollection","_id","test","likes",150);
Related
I have following document :
{
"_id" : ObjectId("5d42501efbf6f6108277ceb3"),
"customer" : {
"id" : "02c59458-8f0a-4a11-bff6-55b4710bc546",
"name" : "brookfield"
},
"userId" : "86c241de-16de-417d-8537-ed441fee9b0e",
"username" : "Fonville_f888f976_un_",
"userGroups" : [],
"lastSeen" : ISODate("2020-05-06T20:21:49.140Z"),
"devices" : [
{
"id" : "A920B6F24B63479B8796B709EA542951",
"displayId" : "A920B6F24B63479B8796B709EA542951",
"manufacturedId" : false,
"lastSeen" : ISODate("2020-03-20T14:36:24.961Z"),
"product" : {
"manufacturer" : "PSman",
"manufacturerCode" : 10,
"name" : "BlackHawk 880 series",
"modelId" : "C053"
}
},
{
"id" : "2476B0E045712cc-5904-11ea-af28-0612af3fc862",
"displayId" : "2476B0E16929512870992618563",
"lastSeen" : ISODate("2020-01-09T20:59:48.650Z"),
"product" : {
"manufacturer" : "GN",
"manufacturerCode" : 5,
"name" : "Telenor Speak 710",
"modelId" : "2476",
"vendorId" : "B0E"
}
}
],
"software" : {
"applicationId" : "f81d4fae-7dec-11d0-a765-00a0c91e6bf6",
"version" : "3.12.52334.30629",
"displayVersion" : "3.12.0"
},
"lastHost" : {
"name" : "hn_5934d3c5dbf",
"platform" : "WIN",
"osVersion" : "10.0.17763"
}
}
I have to update every product name inside devices array based on product modelId field.
So, user will pass two modelId values and if one of them match product's modelId than product name for that product should be updated.
I wrote following code, and I tested it with mongo db version 4.2, and it works. The problem is that when i tested it with older version of mongo db (3.4.23), it doesn't work,and I'm getting following exception :
com.mongodb.MongoCommandException: Command failed with error 9 (FailedToParse): 'Unrecognized field in update operation: arrayFilters' on server localhost:27017. The full response is { "ok" : 0.0, "errmsg" : "Unrecognized field in update operation: arrayFilters", "code" : 9, "codeName" : "FailedToParse" }
Here is how my method looks like :
private void updateCollection(String firstPid,String secondPid, String newProductName) {
MongoCollection<Document> collection = mongoTemplate.getCollection("user");
BasicDBObject searchQueryOne = new BasicDBObject();
BasicDBObject searchQueryTwo = new BasicDBObject();
BasicDBList or = new BasicDBList();
BasicDBObject query = new BasicDBObject("$or", or);
BasicDBObject updateQuery = new BasicDBObject();
searchQueryOne.append("devices.product.modelId", firstPid);
searchQueryTwo.append("devices.product.modelId", secondPid);
or.add(searchQueryOne);
or.add(searchQueryTwo);
updateQuery.append("$set",
new BasicDBObject().append("devices.$[elem].product.name", newProductName));
collection.updateMany(query, updateQuery, new UpdateOptions().arrayFilters(
Collections.singletonList( Filters.in("elem.product.modelId", Arrays.asList(firstPid,secondPid)))));
}
Please help
After some resarching, I managed to solve my problem. If someone have similar issue, here is the code that worked for me
public void updateUserCollection(String pidOne, String pidTwo) {
MongoCollection<Document> userCollection = mongoTemplate.getCollection("user");
BasicDBObject deviceCriteria = new BasicDBObject("devices.product.modelId", new BasicDBObject("$in", Arrays.asList(pidOne)));
FindIterable<Document> cursor = userCollection.find(deviceCriteria);
MongoCursor<Document> iterator = cursor.iterator();
while (iterator.hasNext()) {
Document user = iterator.next();
String userId = user.get("userId", String.class);
List<Document> devices = user.get("devices", List.class);
for (Document device : devices) {
Document product = device.get("product", Document.class);
String modelId = product.get("modelId", String.class);
if (modelId != null && (modelId.equals(pidOne) || modelId.equals(pidTwo))) {
product.put("name", newProductName);
}
}
saveUser(userId, user, userCollection);
}
iterator.close();
}
private void saveUser(String userId, Document user, MongoCollection<Document> userCollection) {
BasicDBObject updateQuery = new BasicDBObject("$set", user);
BasicDBObject searchQuery = new BasicDBObject("userId", userId);
userCollection.updateMany(searchQuery, updateQuery);
}
My data is formatted as:
{
"_id" : "149",
"books" : {
"32" : "0.12",
"33" : "0.21"
}
}
I would like to update/insert values inside the nested books document. If I insert a new row say "39" : "0.19", then the updated document should look as below:
{
"_id" : "149",
"books" : {
"32" : "0.12",
"33" : "0.21",
"39" : "0.19"
}
}
And updates should work, the way they are meant to work. By updating the values.
I tried several ways, but couldn't update the way I wanted.
Method1: Working but wrong result
MongoCollection<Document> document = mongoTemplate.getCollection("booksCollection");
BasicDBObject query = new BasicDBObject();
query.put("_id", storeId);
BasicDBObject bookDiscount = new BasicDBObject();
bookDiscount.put(bookId, discount);
BasicDBObject update = new BasicDBObject();
update.put('$push', new BasicDBObject("books", bookDiscount));
document.findOneAndUpdate(query, update);
Method1 Output: Each value is added in a new row
{
"_id" : "1664",
"books" : [
{
"28" : NumberDecimal("0.75")
},
{
"29" : NumberDecimal("0.18")
},
{
"30" : NumberDecimal("0.23")
},
{
"245" : NumberDecimal("0.26")
},
{
"277" : NumberDecimal("0.13")
},
{
"270" : NumberDecimal("0.19")
}
]
}
Method2: Working but wrong result
MongoCollection<Document> document = mongoTemplate.getCollection("booksCollection");
BasicDBObject query = new BasicDBObject();
query.put("_id", storeId);
BasicDBObject bookDiscount = new BasicDBObject();
bookDiscount.put(bookId, discount);
BasicDBObject update = new BasicDBObject();
update.put('$set', new BasicDBObject("books", bookDiscount));
document.findOneAndUpdate(query, update);
Method2 Output: Value always gets replaced
{
"_id" : "16644158",
"locationInfRate" : {
"2857" : NumberDecimal("0.68")
},
"_class" : "com.test.books"
}
What I learned:
$push method pushes the data as a member of a list.
$set method updates the data, but for maps, it replaces data if the map is not correctly formatted in the query.
I edited my $set query to below format and it worked:
MongoCollection<Document> document = mongoTemplate.getCollection("booksCollection");
BasicDBObject query = new BasicDBObject();
query.put("_id", storeId);
BasicDBObject bookDiscount = new BasicDBObject();
bookDiscount.put("books." + bookId, discount);
update.put('$set', bookDiscount);
document.findOneAndUpdate(query, update);
I am new to Mongodb. I have the following dataset in mongodb.
{
"_id": {
"$oid": "563644f44b17ca12886440a9"
},
"data": [
{
"uid": 1,
"character": " ",
"unicode": 32,
"color": -7309587
},
{
"uid": 2,
"character": "!",
"unicode": 33,
"color": -8911704
},
{
"uid": 3,
"character": "\"",
"unicode": 34,
"color": -1778539
}
I am trying to retrieve the color from this field using the _id and character. I am not able to execute the query.
This is what I tried.
DBObject clause1 = new BasicDBObject("_id",new ObjectId(KEY1));
DBObject clause2 = new BasicDBObject("data.character",text[i]);
BasicDBList or = new BasicDBList();
or.add(clause1);
or.add(clause2);
DBObject query = new BasicDBObject("$and", or);
Also I am having a lot of issues in finding ways to query in mongodb-java for the 3.0.0+ api. Could someone please help?
MongoClient mongoClient = new MongoClient(new ServerAddress("localhost", 27017));
MongoDatabase db = mongoClient.getDatabase("testDB");
AggregateIterable<Document> iterable = db.getCollection("testCollection").aggregate(
asList(new Document("$unwind", "$data"), new Document("$match", (new Document("_id", new ObjectId(
"5636f106b2acf98ecb033b98")).append("data.character", " "))), new Document("$project",
new Document("data.color", 1).append("_id", 0))));
iterable.forEach(new Block<Document>()
{
#Override
public void apply(final Document document)
{
System.out.println(document.toJson());
}
});
For more details check MongoDB Documentation.
A simple solution
In your document,
oid is an unique key for each document and hence your query should be like this
DBObject query = new BasicDBObject("_id.oid", KEY1);
// Query with value - DBObject query = new BasicDBObject("_id.oid","563644f44b17ca12886440a9");
Assign this to a cursor as shown below
DBCollection coll = db.getCollection("mycollection");
DBCursor cursor = coll.find(query);
Iterate the collection and retrieve your desired value.
Here's my code
ServerAddress sa = new ServerAddress("localhost", 27017);
MongoClient mongoClient = new MongoClient(sa);
MongoDatabase db = mongoClient.getDatabase("waitinglist");
MongoCollection<Document> coll = db.getCollection("users");
MongoCursor<Document> f = coll.find(eq("users.email", "marc#berger.com")).iterator();
try {
while (f.hasNext()) {
System.out.println("Mongo Cursor: " +f.next().toJson());
}
} finally {
f.close();
}
And here is how my collection looks:
{
"_id" : ObjectId("560b8b76a37991ab2d650ca9"),
"users" : [
{
"firstname" : "Marc",
"lastname" : "Berger",
"email" : "marc#berger.com",
"phone" : "12345"
},
{
"firstname" : "Arnold",
"lastname" : "Schwarzenegger",
"email" : "pumping#iron.com",
"phone" : "12345"
}]
}
I bassically want to get the document in users where the email is equal marc#berger.com, but it returns the whole document with the array as one. I think the problem is the first parameter in the eq method but I can't find a solution on google how make that statement.
You use the positional $ operator in projection in order to return only the matched element of the array. This uses the .projection() method upon .find() with the MongoDB 3.x java driver:
MongoCursor<Document> f = coll.find(eq("users.email", "marc#berger.com"))
.projection(new Document("users.$",1)).iterator();
Then all results will only return the matched array element rather than all array elements.
This is my sample doc.
{
"_id" : ObjectId("51f20148a85e39af87510305"),
"group_name" : "sai",
"privileges" : [
"Notification",
"News Letter"
],
"users" : [
{
"full_name" : "sumit",
"user_name" : "sumitdesh",
"password" : "magicmoments",
"status" : "Active"
},
{
"full_name" : "ad",
"user_name" : "asd",
"password" : "asdf",
"status" : "Active"
}
]
}
I want to replace inner doc from users array with a new doc.
This is my java code:
BasicDBObject g1=new BasicDBObject();
g1.put("full_name", "ram");
g1.put("user_name", "ram123");
g1.put("password", "pass$123");
g1.put("status", "Inactive");
BasicDBObject doc=new BasicDBObject();
doc.put("users",g1);
BasicDBObject q=new BasicDBObject("users.user_name","asd");
con.update(q,doc);
Any help is appreciated
Expected output is as follows
I want to replace inner doc with these values
{
"_id" : ObjectId("51f20148a85e39af87510305"),
"group_name" : "sai",
"privileges" : [
"Notification",
"News Letter"
],
"users" : [
{
"full_name" : "sumit",
"user_name" : "sumitdesh",
"password" : "magicmoments",
"status" : "Active"
},
{
"full_name" : "ram",
"user_name" : "ram123",
"password" : "pass$123",
"status" : "Inactive"
}
]
}
I must combine $set and $ operators, then you can update an specific item of array.
BasicDBObject g1 = new BasicDBObject();
g1.put("users.$.full_name", "ram");
g1.put("users.$.user_name", "ram123");
g1.put("users.$.password", "pass$123");
g1.put("users.$.status", "Inactive");
BasicDBObject doc = new BasicDBObject();
doc.put("$set", g1);
BasicDBObject q = new BasicDBObject("users.user_name","asd");
con.update(q,doc);
Your code will create a new document consisting only of the new user. To add a new element to an array in an existing document, use the $push operator
BasicDBObject where = new BasicDBObject("_id", new ObjectId("51f20148a85e39af87510305");
BasicDBObject doc = //... your new user object
BasicDBObject push = new BasicDBObject("$push", doc);
con.update(where, push);
To modify a field of an existing document, you can use the set-operator combined with the $-placeholder. This changes the user_name from "foo" to "bar"
BasicDBObject where = new BasicDBObject("users.user_name", "foo");
BasicDBObject value = new BasicDBObject("users.$.user_name", "bar");
BasicDBObject set = new BasicDBObject("$set", value);
con.update(where, set);
But the least headache-inducing way is to just keep the whole DBObject around when you retrieve an object from the database, mirror all modifications in the DBObject, and then call
con.save(dbObject);
An ORM wrapper library can do this for you. But while it is the easiest way, it isn't the most efficient way, because the whole document will be sent to the database. This is a problem which can be easily filed under "premature optimization" when writes are infrequent and the documents are small, but when you save often and have huge documents, it can become an issue.
This is actually fairly simple, if you follow the documentation.
The first difficulty is finding the document to update. You're looking for the user whose user_name field is 'asd', which is done, rather neatly, through the following query:
{'users.user_name': 'asd'}
The field name needs to be escaped in the mongo shell (it's a compound name) but you need not worry about that in Java.
Now that you've found your user, you need to change it. MongoDB magically stores the matched array index as $, which allows you to write the update criteria as:
{
$set: {
'users.$': {
full_name: 'ram',
user_name: 'ram123',
password: 'pass$123',
status: 'inactive'
}
}
}
You obviously know your way around the Java connector, I'll leave the transformation of my JSON object to instances of BasicDBObject to you.