Below is my mongob document structure
{
"employee_id":"123",
"employee_name":"ABC",
"elements":[
{
"element_name":"Verification Id",
"element_value":"Test Address",
"element_status":"selected"
},
{
"element_name":"Reportees",
"element_value":["ABC","DEF"],
"element_status":"selected"
}
,
{
"element_name":"Countries",
"element_value":["China","USA"],
"element_status":"selected"
}
]
}
My input will be {"countries":["Russia","Japan"],"Verification Id":"license"}.
My requirement is to update the only the countries and Verification Id element values for the given employee id. Reportees should remain untouched.
What are the ways to achieve this using java mongodb.
I tried following approaches
1)
collection.updateMany(Filters.and(Filters.eq("employee_id", "123"),Filters.eq("elements.element_name", "Verification Id"))
,
Updates.combine(
Updates.set("elements.$.element_value", "license"),
Updates.set("elements.$.element_status", "changed"),
));
and
collection.updateMany(Filters.and(Filters.eq("employee_id", "123"),Filters.eq("elements.element_name", "Countries")))
,
Updates.combine(
Updates.set("elements.$.element_value", ["Russia","Japan"]),
Updates.set("elements.$.element_status", "changed"),
));
The disadvantage here is that I end up making 2 db calls. If more such parameters come as input, then the number of db calls to perform the update increases
2.)
List<DBObject> array = new ArrayList<DBObject>();
BasicDBObject bObj=new BasicDBObject();
bObj.put("element_name", "Countries");
bObj.put("element_value", ["Russia","Japan"]);
bObj.put("element_status", "changed");
BasicDBObject bObj1=new BasicDBObject();
bObj1.put("element_name", "Verification Id");
bObj1.put("element_value", "license");
bObj1.put("element_status", "changed");
array.add(bObj);
array.add(bObj1);
collection.updateMany(Filters.eq("employee_id", "123"),
Updates.combine(
Updates.set("elements", array)
));
The disadvantage is that it completly over writes the elements array and removes the array element "element_name":"Reportees".
PLease guide me further on this. PLease let me know the best way to update select fields based on different criteria.
Related
I am trying to add a string to the end of an existing array in a mongoDB document.
I have tried looking at the documentation for mongoDB which lead me to the push page and other similar questions. None of them have worked so far as the document that i have have no ids made by me, they are auto-generated as a new element in the array is added.
Document in collection:
_id: 5ce85c1e1c9d4400003dcfd9
name: "Halloween party"
category: 2
date: 2019-10-31T23:00:00.000+00:00
address: "Sample Street, london"
description: "It's Halloween, bring your costumes and your personality to the studen..."
bookings: Array
0: "1610512"
I am able to get the document that I want to append the string in with the following code.
Java Code:
MongoDatabase database = mongoClient.getDatabase("KioskDB");
MongoCollection<Document> Kiosk = database.getCollection("Events");
Document searchQuery = new Document();
searchQuery.put("name", selectedActivityName);
searchQuery.put("bookings", username);
FindIterable<Document> documents = Kiosk.find(searchQuery);
for (Document document: documents){
System.out.println(document);
}
Giving me the following output
Document{{_id=5ce85c1e1c9d4400003dcfd9, name=Halloween party, category=2, date=Thu Oct 31 23:00:00 GMT 2019, address=Sample Street, london, description=It's Halloween, bring your costumes and your personality to the student Bar and join us in this age long celebration., bookings=[1610512]}}
How do I go about appending a new string at the end of the array giving me something like this shown below.
Desired final document
_id: 5ce85c1e1c9d4400003dcfd9
name: "Halloween party"
category: 2
date: 2019-10-31T23:00:00.000+00:00
address: "Sample Street, London"
description: "It's Halloween, bring your costumes and your personality to the studen..."
bookings: Array
0: "1610512"
1: "1859301"
EDIT:
Was able to find the answer with the following code.
DBObject listItem = new BasicDBObject("bookings", username);
Kiosk.updateOne(eq("name", selectedActivityName), new Document().append("$push", listItem));
Where username is the number (Ex: 1859301), selectedActivityName is the name of the name field (Ex: Halloween party) and Kiosk is the collection name.
I will try this code according to the documentation. Ref. https://mongodb.github.io/mongo-java-driver/3.4/driver/getting-started/quick-start/
Document doc = new Document("name", "Halloween party")
.append("bookings", Arrays.asList("1859301"));
Since the 3.0 Java driver they added helper methods for filters which make querying mongo a lot nicer and readable. In 3.1 they also added helper methods for updates which make things like this pretty straightforward and easy to understand what is happening See:
https://mongodb.github.io/mongo-java-driver/3.6/javadoc/com/mongodb/client/model/Filters.html
https://mongodb.github.io/mongo-java-driver/3.6/javadoc/com/mongodb/client/model/Updates.html
Bson query = Filters.eq("name", selectedActivityName);
Bson update = Updates.push("bookings", username);
collection.findOneAndUpdate(query, update);
Doing this in older versions is possible as well. This syntax should still hold true for pre 3.0 versions. However, if you're running older than 3.0 you'll need to replace Document with BasicDBObject.
Bson query = new Document("name", selectedActivityName);
Bson update = new Document("$push", new Document("bookings", username));
collection.findOneAndUpdate(query, update);
I'm new in Couchbase Android. I use Couchbase Lite v1.1.0 to save my data local. But I facing with some problems when to do that. I googled, read document in Couchbase Lite and find all post in stackoverflow but I still not understand what I facing.
Here is my snippet demo code to save my data in database with custom id of document is index i:
cbManager=new Manager(new AndroidContext(context),
Manager.DEFAULT_OPTIONS);
cbDatabase=cbManager.getDatabase("my_db");
.....
for(int i=0; i<10; i++){
Document document=cbDatabase.getDocument(String.valueOf(i)); // This line I custom document with id i
Map<String,Object> docContent= new HashMap<String, Object>();
docContent.put("title", title);
docContent.put("firstName", firstName);
docContent.put("lastName", lastName);
try{
document.putProperties(docContent);
} catch (CouchbaseLiteException e){
Log.e(TAG, "Cannot write document to database", e);
}
}
And get all datas from Couchbase Lite:
Query allDocumentsQuery= cbDatabase.createAllDocumentsQuery();
QueryEnumerator queryResult=allDocumentsQuery.run();
for (Iterator<QueryRow> it=queryResult;it.hasNext();){
QueryRow row=it.next();
Document doc=row.getDocument();
String id=doc.getId(); // I get the id in here but the result is the default id (UUID):(
}
So, I have two questions:
When I query all documents from database (couchbase lite), the document is returned which the default id (UUID), Why it is not return my custom ID?
( means: Saving all the document to database which custom ids: 1, 2, 3 ......9. But the result of all documents when get from database have default ids: UUID, UUID,..., UUID. )
I dont understand Why I save the document in order but the return of all documents are not in order ? (because this reason make me custom id of document)
Please give me some advises or guide me on the best way to do this. Thank you all so much.
You need to add the _rev property to your map with the id as value.
Here's an excerpt from the documentation:
putProperties(Map<String, Object> properties)
Creates and saves a new Revision with the specified properties. To succeed the specified properties must include a '_rev' property whose value maches the current Revision's id.
So your code should look like this:
Map<String,Object> docContent= new HashMap<String, Object>();
docContent.put("_rev", String.valueOf(i));
docContent.put("title", title);
docContent.put("firstName", firstName);
docContent.put("lastName", lastName);
How can I instruct Mongo to return the affected rows after doing an update?
Currently it returns
{ "serverUsed" : "localhost:27017" , "ok" : 1 , "n" : 12 , "updatedExisting" : true}
which means 12 records was updated, but I want to find out which records they were.
One workaround is to do two queries, first to find the _id's, and second to actually update them but this is not good enough.
Many thanks
R.
Use the findAndModify() API. For example, following the guideline from this blog post MongoDB findAndModify() examples using Mongo Shell and Java Driver, you can write your update query as:
// findAndModify operation. Update colour to blue for cars having speed < 45
DBObject query = new BasicDBObject("speed",
new BasicDBObject("$lt", 45));
DBObject update = new BasicDBObject();
update.put("$set", new BasicDBObject("color", "Blue"));
DBCursor cursor = coll.find();
try {
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
} finally {
cursor.close();
}
coll.findAndModify(query, update);
Below is the JSON file from which I want to retrieve the phone number:
"_data" : {
"Variable key" : {
"Name" : "Hello World",
"Phone" : "Phone : 123-456-6789 ",
"Region" : "New York",
"Description" : ""
}
}
My Java Code is:
BasicDBObject query = new BasicDBObject();
BasicDBObject field = new BasicDBObject();
field.put("_data.Phone", 1);
DBCursor cursor = table.find(query,field);
String str;
while (cursor.hasNext()) {
BasicDBObject obj = (BasicDBObject) cursor.next();
str=cursor.curr().get("_data.Phone").toString();
System.out.println(str);
}
which will return null as I'm not considering the variable key.
My problem is there are many JSON files present in the mongo database each having different "Variable Key" and this key may change after sometime. As this key may change over time, how can I retrieve the phone number ?
Thank You !!
Which phone numbers do you want? Your query will return all documents and you are trying to project out just the phone number, but with an incorrect projection specification. If you want all phone numbers, just leave out the projection specification entirely or project on { "_data" : 1 }. If you want the phone numbers associated with specific variable keys, project those out using dot notation like { "_data.key_name.Phone" : 1 }. If you don't know the names of the keys that you want to project on, then that is your root problem that you need to solve before you ask MongoDB to return something that you don't know that you want (or that you don't want).
I am new to MongoDB. My sample document is
{
"Notification" : [
{
"date_from" : ISODate("2013-07-08T18:30:00Z"),
"date_too" : ISODate("2013-07-30T18:30:00Z"),
"description" : "fdfd",
"url" : "www.adf.com"
},
{
"date_from" : ISODate("2013-07-01T18:30:00Z"),
"date_too" : ISODate("2013-07-30T18:30:00Z"),
"description" : "ddddddddddd",
"url" : "www.pqr.com"
}
],
I am trying to update the Notification whose "url" : "www.adf.com". My Java code to do this is:
BasicDBObject query=new BasicDBObject("url","www.adf.com");
DBCursor f = con.coll.find(query);
It does not search for the document whose "url" is "www.adf.com".
You have a nested document in this case. Your document has a field Notification which is an array storing multiple sub-objects with the field url. To search in a sub-field, you need to use the dot-syntax:
BasicDBObject query=new BasicDBObject("Notification.url","www.adf.com");
This will, however, return the whole document with the whole Notification array. You likely only want the sub-document. To filter this, you need to use the two-argument version of Collection.find.
BasicDBObject query=new BasicDBObject("Notification.url","www.example.com");
BasicDBObject fields=new BasicDBObject("Notification.$", 1);
DBCursor f = con.coll.find(query, fields);
The .$ means "only the first entry of this array which is matched by the find-operator"
This should still return one document with a sub-array Notifications, but this array should only contain the entry where url == "www.example.com".
To traverse this document with Java, do this:
BasicDBList notifications = (BasicDBList) f.next().get("Notification");
BasicDBObject notification = (BasicDBObject) notifications.get(0);
String url = notification.get("url");
By the way: When your database grows you will likely run into performance problems, unless you create an index to speed up this query:
con.coll.ensureIndex(new BasicDBObject("Notification.url", 1));