Updating value of a subfield in MongoDB with Java driver? - java

I've quite new to MongoDB and it's Java driver.
I need to update the value of a subfield, but I can't find any examples online.
The document:
{
"_id" : ObjectId("45678942342"),
"user" : "me",
"aStruct" : {
"subfield_1" : true,
"subfield_2" : true
}
}
How do I update the value of subfield subfield_1 to false, for every document that has user = me ?
Thank you.

You can do it as follows :
db.collection.update({user : "me"},{$set:{"aStruct.subfield_1" : false}}, false, true)
In Java you can do it as follows :
DBCollection coll = // Define your collection here
DBObject query = new BasicDBObject();
query.put("user", "me");
DBObject updateObj = new BasicDBObject();
updateObj.put("aStruct.subfield_1", false);
coll.updateMulti(query, new BasicDBObject("$set", updateObj));
For more information read the following document.
Update document in MongoDB

Related

MongoDB - Implementing nor query in java

I have the following query which I am trying to implement in Java (I am using 3.4.2 mongo-java driver) :
Json:
{
"_id" : "Team:2334918",
"fieldName" : [
"Delivery",
"Support"
],
"isDeleted" : false
}
Here the query:
db.myCollection.find({$nor: [{“fieldName”: {$exists: false}},{“fieldName”:{$size:0}}]})
I have written the following code to implement the above query:
MongoClient mc = ctm.getMongoConn();
db = ctm.getDatabase(mc);
col = db.getCollection(collectionName);
BasicDBObject searchObject = new BasicDBObject();
List<BasicDBObject> searchArguments = new ArrayList<BasicDBObject>();
searchArguments.add(new BasicDBObject("fieldName",new BasicDBObject("$exists",false)));
searchArguments.add(new BasicDBObject("fieldName",new BasicDBObject("$size",0)));
searchObject.put("$nor", searchArguments);
MongoCursor<Document> curs = (MongoCursor<Document>) col.find(searchObject);
while (curs.hasNext()){
Document doc = curs.next();
Object name1 = doc.get("fieldName");
System.out.println(name1.toString());
j++;
}
I am getting the following error while running:
java.lang.ClassCastException: com.mongodb.FindIterableImpl cannot be cast to com.mongodb.client.MongoCursor
Replace this:
MongoCursor<Document> curs = (MongoCursor<Document>) col.find(searchObject);
while (curs.hasNext()) {
}
With this:
FindIterable<Document> docs = col.find(searchObject);
for (Document d : docs) {
}
The suggestion from #Veeram (in the comments above) is correct too.
Try
MongoCursor<Document> curs = col.find(searchObject).iterator(); to get cursor.
You don't have to get hold of cursor. You can use the methods provided in the FindIterable which iterates the cursor for you. example at the end.
Also you are mixing Document (3.x) and BasicDBObject (2.x). You can replace your search builder with
Filters searchObject = Filters.nor(Filters.exists("fieldName"), Filters.size("fieldName", 0);
FindIterable<Document> curs = col.find(searchObject);
curs.forEach();
More info here by the author.

Querying timestamp field of mongo oplog using java

I am trying to query timestamp field of mongo oplog collection using java.
Below is the code.
BSONTimestamp timestamp1 = new BSONTimestamp(1499172935, 1);
BasicDBObject query1 = new BasicDBObject("ts", new BasicDBObject("$gt", timestamp1) );
DBCursor cursor = dbCollection.find(query1);
When I run above piece of code, it returns nothing.
Below is the converted query.
{ "ts" : { "$gt" : { "$ts" : 1499172935 , "$inc" : 1}} }
I executed the same query using robomongo and it also returns nothing.
db.getCollection('oplog.rs').find({ "ts" : { "$gt" : { "$ts" : 1499172935 , "$inc" : 1}} })
But when I changed the query to use Timestamp and executed it, it returns list of oplog records. Below is the working mongo query.
db.getCollection('oplog.rs').find({ "ts" : { "$gt" : Timestamp(1499172935 , 1)} })
How can I get the above query using java?
or
Is there any other way I can query oplog timestamp field using java?
You can use the type 'BsonTimeStamp' to build your filter.
BsonTimestamp lastReadTimestamp = new BsonTimestamp(time, inc);
Bson filter = new Document("$gt", lastReadTimestamp);
dbCollection.find(new Document("ts", filter));

Implementing Mongodb query using $elemMatch in Java

I am using Mongo java driver to retrieve data from mongo collections. I have the following query which I am trying to implement in java:
Json is:
{
"_id" : ObjectId("56cd284767c74d3d4dd3ec80"),
"comments" : "Hello",
"statusLog" : [
{
"status" : "Submitted",
"startDate" : ISODate("2015-01-14T05:00:00.000Z"),
"endDate" : ISODate("2016-02-29T21:24:24.740Z")
},
{
"status" : "Active",
"startDate" : ISODate("2016-02-29T21:24:24.740Z")
}
],
"createdDate" : ISODate("2015-01-14T05:00:00.000Z")
}
Mongo Query:
db.CollectionName.find({},{_id: 0, createdDate:1, "statusLog": {$elemMatch: {"status":"Submitted"}}});
Here is the query in java that I have written (mongo java driver 3.4.2):
BasicDBObject query = new BasicDBObject(new BasicDBObject("statusLog",
new BasicDBObject("$elemMatch", new BasicDBObject("status", "Submitted"))));
Running the java code returns all status logs and not the one that I am looking for.
Any help would be highly appreciated.
elemMatch should be in find method not in projection bson. For example:
collection.find(elemMatch("statusLog", eq("status", "Submitted"))).projection(projection);
You should use newer Document/MongoCollection api and use helper methods to prepare projection.
import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.Projections.*;
MongoClient mongoClient = new MongoClient();
MongoDatabase database = mongoClient.getDatabase("db"); // Get DB
MongoCollection<Document> collection = database.getCollection("collection"); // Get Collection
Bson projection = Projections.fields( excludeId(), include("createdDate"), elemMatch("statusLog", eq("status", "Submitted"))); // Add Projections
FindIterable<Document> iterable = collection.find().projection(projection);
Using old BasicDBObject/DBCollection api
MongoClient mongoClient = new MongoClient();
DB database = mongoClient.getDB("db");
DBCollection collection = database.getCollection("collection");
BasicDBObject projection = new BasicDBObject(new BasicDBObject("statusLog",new BasicDBObject("$elemMatch", new BasicDBObject("status", "Submitted"))));
collection.find(new BasicDBObject(), projection);
To find an item in a list of document with multiple objects, using multiple filtrer criteria:
"array_of_data": {$elemMatch: {"AAA": "xxxx", "BBB": "xxxxx"}}

How to return documents of a collection without objectId in MongoDB?

DB db = mongo.getDB("sample");
DBCollection table = db.getCollection("samplecollection");
DBCursor cursor2 = table.find();
gives the result as:
{ "_id" : { "$oid" : "58bfbcff1d30d8a8c1194328"} , "ID" : 1 , "NAME" : "dgsdg"}
How to get the document without objectid?
You can use projection for that.
Try this:
DBCursor cursor2 = table.find().projection(excludeId())
Read this MongoDB documentation to know more.
I have done this and worked:
MongoDatabase database = mongo.getDatabase("db");
MongoCollection<org.bson.Document> contCol = database.getCollection("test");
FindIterable<org.bson.Document> it = contCol.find().projection(excludeId());
ArrayList<Document> docs = new ArrayList();
for (org.bson.Document its : it) {
System.out.println(its);
}
First you will be import this, import com.mongodb.client.model.Projections;
Then again, u try this one also..
MongoClient client = new MongoClient("hostName");
MongoDatabase db = client.getDatabase("dbName");
MongoCollection<Document> collection = db.getCollection("collectionName");
collection.withWriteConcern(new WriteConcern(1));
/* whatever field you dosn`t need.. you will run this following code,
FindIterable<Document> findDoc = collection.find().projection(new Document().append("_id",0)); //if you need mean, you put _id value is 1.
*/
FindIterable<Document> findDoc = collection.find().projection(Projections.excludeId()) ;
for (Document doc : findDoc) {
System.out.println(doc);
}
You can use the aggregation framework to achieve what you want:
db.getCollection('samplecollection').aggregate([{$project: { field1:1 ,field2: 1.....,'_id': 0} }])
https://docs.mongodb.com/manual/reference/operator/aggregation/project/

Restrict fields in Result

I am working with MongoDB v3.0.1 and the MongoDB Java Driver 3.0.0-RC1.
I have an user collection with fields like "username", "firstname", "lastname", "email", and so on.
Now I want to select all users but only with the fields "username", "firstname" and "lastname".
On the Mongo-Shell it is working with db.user.find({}, { "username" : true , "firstname" : true , "lastname" : true})
But how can I do it in Java? I tried it with
final BasicDBObject query = new BasicDBObject("{}", new BasicDBObject("_id", true));
final MongoCursor<Document> usersCursor = col.find(query)
For this I get an empty result back because it's translated as { "{}" : { "_id" : true , "firstname" : true , "lastname" : true}}.
I also tried it with BasicDBList, but this isn't accepted by col.find()
With the "old" Mongo 2.x driver I would use new BasicDBObject(BasicDBObject(), new BasicDBObject("username", true).append("firstname", true).append("lastname", true)
Is there a possibility to do that or do I have to fetch all fields?
Greetings
Sören
With the new CRUD API in the 3.0.0 Java driver, the proper way to do it is with the projection method that is chained off off MongoCollection.find(). Since the projection method takes an instance of the Bson interface, there are a number of different classes you can use to specify the projection:
// using BasicDBObject
collection.find().projection(new BasicDBObject("username", true)
.append("lastname", true)
.append("firstname", true))
// using the new Document class
collection.find().projection(new Document("username", true)
.append("lastname", true)
.append("firstname", true));
// Using the new Projections builder
collection.find().projection(Projections.include("username", "lastname", "firstname"));
As for the way you say it works in the 2.x driver, that's not possible, as
new BasicDBObject(BasicDBObject(), BasicDBObject("username", true)
.append("firstname", true)
.append("lastname", true)
does not compile. I'm not sure what exactly you were doing with 2.x, but the proper way to accomplish this with the DBCollection class in 2.x (which is still supported in the 3.0 driver), is:
collection.find(new BasicDBObject(), new BasicDBObject("username", true)
.append("lastname", true)
.append("firstname", true));
Have a look at the implementation of DBCollection find(). The following returns the "username", "firstname", "lastname" and "_id" fields for every document in the collection that has an "username", "firstname" and "lastname" fields:
BasicDBObject keys = new BasicDBObject();
keys.put("username", 1);
keys.put("firstname", 1);
keys.put("lastname", 1);
final MongoCursor<Document> usersCursor = col.find(new BasicDBObject(), keys);
collection
.find(new Document(...).append(...))
.projection(new Document(...).append(...))
This will give you a FindIterable and then you can iterate through as you would DBCursor.

Categories