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.
Related
I want to select a specific field of a document in Mongodb collection and convert it to java object.
My document is like this:
{
"Name":"Ben",
"template":"A fingerprint template which I extracted"
}
So I wish select this "template field"
My sample code is below:
List<Document> documents = (List<Document>) collection.find().into(new ArrayList<Document>());
for (Document document : documents) {
Document doc = documents.get(document);
FingerprintTemplate template = (FingerprintTemplate) doc.get("template");
And the error is:
java: incompatible types: org.bson.Document cannot be converted to int
Any idea or any suggestions please!!
You can query if the field exists:
collection.find("template": { $exists: true, $ne: null } });
For the mapping part, you can have a look at objectMapper to map directly to a java object: https://www.baeldung.com/jackson-object-mapper-tutorial
Your error is still that you have a Document and Java is expecting an int.
Try this :
BasicDBObject query = new BasicDBObject();
BasicDBObject whereQuery = new BasicDBObject();
basicDBObject.put("template",1);
DBCursor cursor = collection.find(query,whereQuery);
while(cursor.hasNext()) {
System.out.println(cursor.next());
}
This would print the documents that have template but to convert to Object you would need some JSON Object mapper maybe jackson
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"}}
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/
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
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.