Implementing Mongodb query using $elemMatch in Java - 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"}}

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.

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/

How to delete mongodb document with two conditions one with $gt operator?

I would like to retrieve the following information:
delete from database where name = 'AAA' and age>20;
but for MongoDB in Java. Essentially, it should delete the document that contain the word AAA and age greater than 20 in them. I know that there is the $in operator in MongoDB, but how do I do the same in Java, using the Java driver? I've been trying to look for it everywhere but am getting nothing. I've tried:
query = new BasicDBObject("age", new BasicDBObject("$gt", "20"), new BasicDBObject("name", "AAA"));
JSON which i want to delete is like this.
{"school" : "NewSchool" , "name" : "AAA" , "age" : "50"}
What you want is the find-term:
{
"name" : "AAA",
"age" : { $gt : 20 }
}
Construct this as your basic DB object, or simply use the new 3.x Filters to create the Bson for you. (As I personally only use 3.x, here's the appropriate example):
MongoClient client = ...
MongoDatabase db = client.getDatabase(...);
MongoCollection<Document> coll = db.getCollection(...);
coll.deleteMany(Filters.and(Filters.eq("name", "AAA"), Filters.gt("age", 20)));

Updating value of a subfield in MongoDB with Java driver?

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

How to update value of specific embedded document, inside an array, of a specific document in MongoDB?

I have the following structure in my document:
{
_id : ObjectId("43jh4j343j4j"),
array : [
{
_arrayId : ObjectId("dsd87dsa9d87s9d7"),
someField : "something",
someField2 : "something2"
},
{
_arrayId : ObjectId("sds9a0d9da0d9sa0"),
someField : "somethingElse",
someField2 : "somethingElse2"
}
]
}
I want to update someField and someField2 but only for one of the items in the array, the one that matches _arrayId (e.g. _arrayId : ObjectId("dsd87dsa9d87s9d7"); and only for this document (e.g. _id : ObjectId("43jh4j343j4j") ) and no other.
The arrayIds are not unique to the document that's why I need it to be for a specific document. I could use the $ positional operator if I wanted to update that value within the array for every document it exists in, but that's not what I want.
I am trying to accomplish this in java but a command line solution would work as well.
Here is RameshVel's solution translated to java:
DB db = conn.getDB( "yourDB" );
DBCollection coll = db.getCollection( "yourCollection" );
ObjectId _id = new ObjectId("4e71b07ff391f2b283be2f95");
ObjectId arrayId = new ObjectId("4e639a918dca838d4575979c");
BasicDBObject query = new BasicDBObject();
query.put("_id", _id);
query.put("array._arrayId", arrayId);
BasicDBObject data = new BasicDBObject();
data.put("array.$.someField", "updated");
BasicDBObject command = new BasicDBObject();
command.put("$set", data);
coll.update(query, command);
You could still use $ positional operator to accomplish this. But you need to specify the objectid of the parent doc along with the _arrayid filter. The below command line query works fine
db.so.update({_id:ObjectId("4e719eb07f1d878c5cf7333c"),
"array._arrayId":ObjectId("dsd87dsa9d87s9d7")},
{$set:{"array.$.someField":"updated"}})
...and this is how to do it with mongo-driver version >= 3.1 (mine is 3.2.2):
final MongoClient mongoClient = new MongoClient(new MongoClientURI(mongoURIString));
final MongoDatabase blogDatabase = mongoClient.getDatabase("yourDB");
MongoCollection<Document> postsCollection = blogDatabase.getCollection("yourCollection");
ObjectId _id = new ObjectId("4e71b07ff391f2b283be2f95");
ObjectId arrayId = new ObjectId("4e639a918dca838d4575979c");
Bson filter = Filters.and(Filters.eq( "_id", id ), Filters.eq("array._arrayId", arrayId));
Bson setUpdate = Updates.set("array.$.someField", "updated");
postsCollection.updateOne(postFilter, setUpdate);
Seeing as none of the answers actually explain how to do this a) in Java and b) for multiple fields in a nested array item, here is the solution for mongo-java-driver 3.12.3.
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Updates;
import org.bson.Document;
import org.bson.types.ObjectId;
MongoClient mongoClient = MongoClients.create(...);
MongoDatabase db = mongoClient.getDatabase("testDb");
MongoCollection<Document> collection = db.getCollection("testCollection");
collection.updateOne(
Filters.and(
Filters.eq("_id", new ObjectId("43jh4j343j4j")),
Filters.eq("array._arrayId", new ObjectId("dsd87dsa9d87s9d7"))
),
Updates.combine(
Updates.set("array.$.someField", "new value 1"),
Updates.set("array.$.someField2", "new value 2")
)
);
This thread has helped me towards the right solution, but I had to do more research for the full solution, so hoping that someone else will benefit from my answer too.

Categories