MONGODB - find on "_id" with JAVA - java

I am trying to do this query :
db.indexInverse.find({_id:ObjectId("5a153409b9c52933c8aab068")}).pretty()
with Java ...
actually i try many things ... but that don't find my document ...
Document vraiDoc = collectionIndexInverse.find(Filters.eq("_id", new ObjectId("\"" + idDoc + "\""))).first();
OR
Bson query = (Bson) new BsonString("{ _id:ObjectId(\"" + idDoc + "\")}");
Document vraiDoc = collectionIndexInverse.find(query).first();
OR
Bson query = (Bson) new BsonString("{ _id:ObjectId(idDoc)}");
Document vraiDoc = collectionIndexInverse.find(query).first();

In your first attempt to are double quoting the ObjectId value.
This will work:
Document vraiDoc = collectionIndexInverse.find(
Filters.eq("_id", new ObjectId("5a153409b9c52933c8aab068"))
).first();
More generally, given these documents:
{
"_id" : ObjectId("59b86ff639f9ba0f9c0dccf6"),
...
},
{
"_id" : ObjectId("59c0e662ac11a822d4e5da27"),
...
}
The following command will return the first document ...
find(Filters.eq("_id", new ObjectId("59b86ff639f9ba0f9c0dccf6"))).first();
... and the following command will return the second document:
find(Filters.eq("_id", new ObjectId("59c0e662ac11a822d4e5da27"))).first();

Related

Parse Mongodb json query in java with multiple criteria

I want to parse a java string to mongo DBObject or BasicDBObject as below.
List<DBObject> query = new ArrayList<DBObject>();
String allQry = "{ \"$match\" : { \"CUSTOMERID\" : { \"$gt\" : 10}}}, { \"$project\" : { \"CUSTOMERNAME\" : 1 , \"COUNTRY\" : 1 , \"CUSTOMERID\" : 1}},{ \"$sort\" : { \"COUNTRY\" : 1}}";
BasicDBObject dbobj = BasicDBObject.parse(allQry);
query.add(dbobj);
System.out.println("qqqquery : "+query);
Cursor aggCur = collection.aggregate(query, aggOpt);
After run above example codes, it outputs qqqquery : [{ "$match" : { "CUSTOMERID" : { "$gt" : 10}}}]. There are $match , $project and $sort in allQry. Why do not it includes $project and $sort in this query? It only includes $match, who can help to check this reason? Thanks.
Following this tutorial:
http://pingax.com/trick-convert-mongo-shell-query-equivalent-java-objects/
you could add all parts of your query like this:
MongoClient mongo = new MongoClient();
DB db = mongo.getDB("pingax");
DBCollection coll = db.getCollection("aggregationExample");
/*
MONGO SHELL : db.aggregationExample.aggregate(
{$match : {type : "local"}} ,
{$project : { department : 1 , amount : 1 }}
);
*/
DBObject match = new BasicDBObject("$match", new BasicDBObject("type", "local"));
DBObject project = new BasicDBObject("$project", new BasicDBObject("department", 1).append("amount", 1));
AggregationOutput output = coll.aggregate(match,project,group,sort);
Related:
How to find documents matching multiple criteria
Executing Mongo like Query (JSON)through Java

How to fetch the particular data from Mongo subdocument in java?

I have tried to fetch data for the particular column value in the mongo document but its displaying whole data.
Following is the mongo document:
{
"_id" : ObjectId("59db2321811a592384865711"),
"User_ID" : "demo",
"Project_ID" : "demo-1",
"Project_Information" : {
"Project_Description" : "Sample",
"Primary_Building_Type" : "Office",
"State" : "AR",
"Analysis_Type" : "1",
"Project_Billing_Number" : "WY",
"Country" : "USA",
"Climate_Zone" : "3A",
"Zip_Code" : "71611"
"City" : "WA",
"Units" : "IP"
}
}
I want to fetch the following output:
[
{
"User_ID": "demo",
"Project_Description": "Sample"
}]
I have tried using dot: Project_Information.Project_Description.The code is as below:
public Object[] addDemo1(String User_ID) throws Exception {
DB db = ConnectToDB.getConnection();
Properties prop = new Properties();
InputStream input = null;
input = GetProjectStatus.class.getClassLoader().getResourceAsStream("config.properties");
prop.load(input);
String col = prop.getProperty("COLLECTION_PI");
System.out.println("data is.." + col);
DBCollection collection = db.getCollection(col);
BasicDBObject obj = new BasicDBObject();
BasicDBObject fields = new BasicDBObject();
BasicDBObject fields2 = new BasicDBObject();
List<DBObject> obj1 = null;
if (User_ID != null && !User_ID.equals("") && User_ID.length() > 0) {
obj.put("User_ID", User_ID);
fields.put("_id", 0);
fields.put("User_ID", 1);
fields.put("Project_ID", 1);
fields.append("Project_Information.Project_Description", "Project_Description");
BasicDBObject fields1 = new BasicDBObject();
fields1.put("User_ID", User_ID);
}
DBCursor cursor = collection.find(obj, fields);
System.out.println("count is:" + cursor.count());
obj1 = cursor.toArray();
System.out.println("" + obj1);
cursor.close();
db.getMongo().close();
return obj1.toArray();
}
But it displays the whole structure of Project_Information.
Please specify how to achieve this. Thanks for help.
Using a 2.x MongoDB Java Driver
Here's an example using the MongoDB 2.x Java driver:
DBCollection collection = mongoClient.getDB("stackoverflow").getCollection("demo");
BasicDBObject filter = new BasicDBObject();
BasicDBObject projection = new BasicDBObject();
// project on "Project_Information.Project_Description"
projection.put("Project_Information.Project_Description", 1);
DBCursor documents = collection.find(filter, projection);
for (DBObject document : documents) {
// the response contains a sub document under the key: "Project_Information"
DBObject projectInformation = (DBObject) document.get("Project_Information");
// the "Project_Description" is in this sub document
String projectDescription = (String) projectInformation.get("Project_Description");
// prints "Sample"
System.out.println(projectDescription);
// to return this single String value in an Object[] (as implied by your OP) just do create the Object[] like this and then return it ...
Object[] r = new Object[] {projectDescription};
// prints the entire projected document e.g.
// { "_id" : { "$oid" : "59db2321811a592384865711" }, "Project_Information" : { "Project_Description" : "Sample" } }
System.out.println(document.toString());
}
Using a 3.x MongoDB Java Driver
Here's an example using the MongoDB 3.x Java driver:
// this finds all documents in a given collection (note: no parameter supplied to the find() call)
// and for each document it projects on Project_Information.Project_Description
FindIterable<Document> documents =
mongoClient.getDatabase("...").getCollection("...")
.find()
// for each attrbute you want to project you must include its dot notation path and the value 1 ...
// this is the equivalent of specifying {'Project_Information.Project_Description': 1} in the MongoDB shell
.projection(new Document("Project_Information.Project_Description", 1));
for (Document document : documents) {
// the response contains a sub document under the key: "Project_Information"
Document projectInformation = (Document) document.get("Project_Information");
// the "Project_Description" is in this sub document
String projectDescription = projectInformation.getString("Project_Description");
// prints "Sample"
System.out.println(projectDescription);
// to return this single String value in an Object[] (as implied by your OP) just do create the Object[] like this and then return it ...
Object[] r = new Object[] {projectDescription};
// prints the entire projected document e.g. { "_id" : { "$oid" : "59db2321811a592384865711" }, "Project_Information" : { "Project_Description" : "Sample" } }
System.out.println(document.toJson());
}
Java libraries won't let you directly access using dot.
They have build in getter and setter methods.
You have not mentioned which package you are using.
Here's the query that you need:
db.mycol.find({},{User_ID:1,"Project_Information.Project_Description":1})
It will give:
{ "_id" : ObjectId("59db2321811a592384865711"),
"User_ID" : "demo",
"Project_Information" : { "Project_Description" : "Sample" }
}
You will have to convert the query in whatever format your package accepts.
Here's a tutorial:
https://www.mongodb.com/blog/post/getting-started-with-mongodb-and-java-part-i

Mongo Java Driver - How to update a subdocument into an array element

How could I update a specific field in subdocument of array element ?
My question is similar to the following below, but in my case I need to update just a subdocument value.
MongoDB: How do I update a single subelement in an array, referenced by the index within the array?
I have the following documento model :
{
_id : "xpto",
other_stuff ... ,
templates : [
{
templateId:"template-a"
body: {
en_US:"<p>Hello World!</p>"
}
},
{
templateId:"template-b"
body: {
es_ES:"<p>Holla !</p>"
}
}
]
}
So, In mongodb shell the following statement works perfectly for me:
db.apiClient.update({"_id":"xpto","templates.templateId":"template-b"}, {$set:{"templates.$.body.es_ES":"<h1>Gracias !</h1>"}})
However , when i try to do it with Mongo Java Driver , I get an IllegalArgumentException.
BasicDBObject selectQuery = new BasicDBObject("_id", "xpto");
selectQuery.put("templates.templateId", "template-b");
BasicDBObject updateQuery = new BasicDBObject();
for(String locale : template.getBody().keySet()) {
String updateBodyLocaleExpression = new StringBuilder()
.append("templates.$.body.").append(locale).toString();
String updateBodyLocaleValue = template.getBody().get(locale);
updateQuery.put(updateBodyLocaleExpression, updateBodyLocaleValue);
}
updateQuery.put("$set", updateQuery);
getCollection(COLLECTION_NAME).update(selectQuery, updateQuery, true, true);
It throws the following exception :
Caused by: java.lang.IllegalArgumentException: Invalid BSON field name templates.$.body.es_ES
at org.bson.AbstractBsonWriter.writeName(AbstractBsonWriter.java:494)
at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:127)
at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:61)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
at com.mongodb.connection.RequestMessage.addDocument(RequestMessage.java:253)
at com.mongodb.connection.RequestMessage.addCollectibleDocument(RequestMessage.java:219)
at com.mongodb.connection.UpdateMessage.encodeMessageBodyWithMetadata(UpdateMessage.java:77)
at com.mongodb.connection.RequestMessage.encodeWithMetadata(RequestMessage.java:160)
at com.mongodb.connection.WriteProtocol.execute(WriteProtocol.java:85)
Is something wrong with my code ?
Thanks.
Yes. You construct wrong updateQuery. You put fields templates.$.body... in the BasicDbObject and then add same document into $set field into itself. MongoDB tries to update field templates.$.body. and here $ is the part of the field name instead of operator.
Here is working example:
//List is for testing purposes only
List<String> locales = Arrays.asList("en_US", "en_UK");
Document query = new Document("_id", "xpto")
.append("templates.templateId", "template-b");
Document updateQuery = new Document();
for (String locale : locales) {
updateQuery.put("templates.$.body." + locale, "<pre>Updated " + locale + "</pre>");
}
collection.updateOne(query, new Document("$set", updateQuery));
Document is almost the same as BasicDbObject but more general.

Java/Groovy monogodb nested query with both AND and OR

I am having hard time converting the below nested mongodb query with $and and $or to java/groovy
db.personSync.find({
$and:[
{$or:[
{ "name" : { "$regex" : "(?i)^test1" , "$options" : "i"}},
{ "name" : { "$regex" : "(?i)^dev" , "$options" : "i"}}
]},
{ "email" : { "$regex" : "(?i)^test" , "$options" : "i"}}
]}
);
]}
);
I was able to write code for $or part as below
def mongoCritera = new ArrayList<BasicDBObject>();
mongoCritera.add('name', java.util.regex.Pattern.compile('(?i)^test1`'))
mongoCritera.add('name', java.util.regex.Pattern.compile('(?i)^dev`'))
def query = new BasicDBObject("\$or", mongoCritera);
collection.find(query);
But I couldn't accommodate $and logic, can someone please help me with this?
def andCritera = new ArrayList<BasicDBObject>();
def orCritera1= new ArrayList<BasicDBObject>();
orCritera1.add('name', java.util.regex.Pattern.compile('(?i)^test1`'))
orCritera1.add('name', java.util.regex.Pattern.compile('(?i)^dev`'))
def orQuery1 = new BasicDBObject("\$or", orCritera1);
andCritera.add(orQuery1)
def orCritera2= new ArrayList<BasicDBObject>();
orCritera1.add('email', java.util.regex.Pattern.compile('(?i)^test`'))
def orQuery2 = new BasicDBObject("\$or", orCritera2);
andCritera.add(orQuery2)
def query = new BasicDBObject("\$and", andCritera);
def cursor = collection.find(query)
while (cursor.hasNext()) {
println 'person '+ cursor.next();
}
As per my understanding you wants to write a query fetch
name should be start from (test1 or dev) case insensitive and email start with test (also case insensitive) ? if yes try this
db.personSync.find({$and:[{name:{"$regex":"^[test|dev]","$options":"i"}},{email:{"$regex":"^test1","$options":"i"}}]})
public static void main(String[] args) {
MongoClient c = new MongoClient();
MongoDatabase db = c.getDatabase("test");
MongoCollection<Document> collection = db.getCollection("so3");
ArrayList<Document> andCritera = new ArrayList<Document>();
ArrayList<Document> orCritera1= new ArrayList<Document>();
orCritera1.add(new Document("name", java.util.regex.Pattern.compile("(?i)^[test1|dev]")));
Document orQuery1 = new Document("$or", orCritera1);
andCritera.add(orQuery1);
andCritera.add(new Document("email", java.util.regex.Pattern.compile("(?i)^test")));
Document query = new Document("$and", andCritera);
ArrayList<Document> docList = new ArrayList<Document>();
collection.find(query).into(docList);
for(Document doc:docList){
System.out.println(doc);
}
}
I validated this is working fine :)

How to $and two documents in mongodb and Java?

I am using mongodb with Java 3.0 driver. I have a scenario where I have to perform logical and i.e, $and on my queries. For example, I have two documents already created and I am trying to do something like this:
iterable = mongoDatabase.getCollection("restaurants").find(
new Document("$and", asList(abc,
updatedDocumentTypeOne)));
where abc is one document and updatedDocumentTypeOne is another document. I found this in mongodb manual but I am getting error as first create asList Method.
Or how to replicate the following in Java:
db.inventory.find( {
$and : [
{ $or : [ { price : 0.99 }, { price : 1.99 } ] },
{ $or : [ { sale : true }, { qty : { $lt : 20 } } ] }
]
} )`
You can also try the code below that adds a filter for query replication in Java:
// Where db is the object reference of "inventory" collection's database
MongoCollection<Document> inventory = db.getCollection("inventory");
//List for result return
List<Document> result = new ArrayList<Document>();
//Query replication in Java and return result into the list
inventory.find(Filters.and(
Filters.or(Filters.eq("price", 0.99),Filters.eq("price", "1.99")),
Filters.or(Filters.eq("sale", true),Filters.lt("qty", 20))
)).into(result);
Change from asList() to Arrays.asList()
Instead of writing Arrays.asList(), you have specified as asList(). So compiler is searching for the method asList(), which is NOT available.
Check the below code :
iterable = mongoDatabase.getCollection("restaurants").find(
new Document("$and", Arrays.asList(abc,
updatedDocumentTypeOne)));
For your above query, You can code as below :
/* First OR condition */
Document price1 = new BasicDBObject("price",0.99);
Document price2 = new BasicDBObject("price",1.99);
BasicDBList or_first = new BasicDBList();
or_first.add(price1);
or_first.add(price2);
DBObject query = new BasicDBObject("$or", or_first);
/* Second OR condition */
boolean val = true;
Document sale = new BasicDBObject("sale",val);
Document qty = new BasicDBObject("qty", new BasicDocument("$lt",20));
BasicDBList or_second = new BasicDBList();
or_second.add(sale);
or_second.add(qty);
DBObject query = new BasicDBObject("$or", or_second);
/* AND condition logic */
BasicDBList and_op = new BasicDBList();
and_op.add(or_first);
and_op.add(or_second);
iterable = mongoDatabase.getCollection("restaurants").find( new Document("$and", and_op ));

Categories