Java MongoDB access object children nodes - java

I pull the following document from MongoDB into Java:
{
"_id": {
"$oid": "5076371389d22e8906000000"
},
"item": {
"values": [
{
"value1": [
4958,
3787,
344
],
"value2": [
4,
13,
23
]
}
],
"name": "item1"
}
}
Using
M mongo = new M("database", "collection");
String query = "{\"item.name\":\"item1\"}";
DBCursor cur = mongo.collection.find(mongo.query(query));
while(cur.hasNext()) {
System.out.println(cur.next().toString());
// I need to access value1 array.
}
I need to access value1 array, I also need to pull the whole document, so I cannot just ask Mongo to return this for me. Its like I am pulling this document, need to do a calculation and use the document again.
I understand this result can be converted to a map. But how would I be able to navigate through it since it is a multidimentional object. Thanks

Try this:
//try catch omitted
Mongo mongo = new Mongo("localhost", 27017);
DB db = mongo.getDB("db");
BasicDBObject query = new BasicDBObject("item.name","item1");
DBCursor cur = db.getCollection("items").find(query);
while(cur.hasNext()) {
BasicDBObject object = (BasicDBObject) cur.next();
BasicDBObject item = (BasicDBObject) object.get("item");
BasicDBList valueslist = (BasicDBList) item.get("values");
BasicDBObject values = (BasicDBObject) valueslist.get(0);
BasicDBList value1 = (BasicDBList) values.get("value1");
System.out.println(value1);
}
You can optimise it, but I hope you get the point and it helps.
cheers

Related

MongoDB java Driver query on nested object using objectID is not working

I have following mongodb document structure
{
"_id": ObjectId("571530da41995a703faaf55b"),
"project_name": "abc",
"status": "new",
"cluster": "",
"sku": {
"_id": "57152f7941995a703faaf559",
"name": "temp",
"distribution": "apache",
"creation_date": "2016-04-18T19:02:46.595Z",
"user_id": "570784b1682d25f45b64ed51",
"__v": 0,
"services": []
}
}
I want to find project info given a sku._id. I am using following piece of code for this purpose.
String getProjectIDforSku(String skuID ) {
ObjectId id = new ObjectId(skuID);
BasicDBObject query = new BasicDBObject("sku", new BasicDBObject("_id", skuID));
DBObject obj = getCollection("deployment", "projects").findOne(query);
if (obj != null) {
var jsonString = Json.parse(obj.toString());
return jsonString;
} else
return null;
}
When I call this function, I receive null instead of valid json string.
Can anyone guide me where i am wrong?
Thanks
Change
BasicDBObject query = new BasicDBObject("sku", new BasicDBObject("_id", skuID));
to
BasicDBObject query = new BasicDBObject("sku._id",skuID);
The reason being that in the first one you are comparing sku to an object with only one field _id (which is not the case, the object has other fields), while the second one only matches the _id field within the sku object.

Return nested elements in Json that equal search string - mongodb

I has the following json document in Mongo db. The show element will have several season elements which will also have several episodes elements that in turn have multiple questionEntry elements.
I want to return multiple questionElements where the questionElements metaTag entry equals my search. E.G. if a metaTag element equals my string the return it's parent questionEntry element and search across all elements nested in show.
{
"show":[
{
"season":[
{
"episodes":[
{
"questionEntry":{
"id":1,
"info":{
"seasonNumber":1,
"episodeNumber":5,
"episodeName":"A Hero Sits Next Door"
},
"questionItem":{
"theQuestion":"What is the name of the ringer hired by Mr. Weed?",
"attachedElement":{
"type":1,
"value":""
}
},
"options":[
{
"type":1,
"value":"Johnson"
},
{
"type":1,
"value":"Hideo"
},
{
"type":1,
"value":"Guillermo"
}
],
"answer":{
"questionId":1,
"answer":3
},
"metaTags":[
"Season 1",
"Episode 5",
"Trivia",
"Arya Stark",
"House Stark"
]
}
}
]
}
]
}
]
}
I'm usingthe latest Java Mongo driver in Windows 8.1 and using Mongodb 2.4.4. So my question is what is the best method to return a single or multiple qestionEntry element(s) over this entire show collection that match my search string?
Hopefully somebody here can help me with this.
EDIT:
private DB mongoDatabase;
private DBCollection mongoColl;
private DBObject dbObject;
// Singleton class
// Create client (server address(host,port), credential, options)
mongoClient = new MongoClient(new ServerAddress(host, port),
Collections.singletonList(credential),
options);
mongoDatabase = ClientSingleton.getInstance().getClient().getDB("MyDB");
Please try the below :
db.exp.aggregate([{"$redact":{"$cond": { if: {$gt:[ {"$size": {
$setIntersection : [ { "$ifNull": [ "$metaTags", []]},
["House Stark"]]} } , 0 ]} , then:"$$PRUNE",
else:"$$DESCEND" }}}]).pretty();
[OR]
EDIT :
db.exp.aggregate([{"$unwind":"$show"},
{"$unwind":"$show.season"},
{"$unwind":"$show.season.episodes"},
{"$match" : {"show.season.episodes.questionEntry.metaTags":{"$in":
["Trivia"]}}},
{"$group":{"_id":"$_id","episodes":{"$push":"$show.season.episodes"}
]);
JAVA CODE :
MongoClient client = new MongoClient();
List<String> continentList = Arrays.asList(new String[]{"Trivia"});
DB db = client.getDB("example");
DBCollection coll = db.getCollection("exp");
DBObject matchFields = new
BasicDBObject("show.season.episodes.questionEntry.metaTags",
new BasicDBObject("$in", continentList));
DBObject groupFields = new BasicDBObject( "_id",
"$_id").append("episodes",
new BasicDBObject("$push","$show.season.episodes"));
DBObject unwindshow = new BasicDBObject("$unwind","$show");
DBObject unwindsea = new BasicDBObject("$unwind", "$show.season");
DBObject unwindepi = new BasicDBObject("$unwind",
"$show.season.episodes");
DBObject match = new BasicDBObject("$match", matchFields);
DBObject group = new BasicDBObject("$group", groupFields);
AggregationOutput output =
coll.aggregate(unwindshow,unwindsea,unwindepi,match,group);
for (DBObject result : output.results()) {
System.out.println(result);
}

Java API to insert a document with array of elements in mongodb collection

I want to insert the following JSON into the Mongodb collection using java API . Here bookmarks is an arrayList of bookmarks POJO .
{
"_id": 5,
"email": "xxx#gmail.com",
"bookmarks": [
{
"name": "chipotle",
"category": "restaurant",
"stats": "203 likes",
"tried": true
},
{
"name": "olivegarden",
"category": "restaurant",
"stats": "203 likes",
"tried": true
}
]
}
I used the following API . but it doesn't seem to work
BasicDBObject document = new BasicDBObject();
document.append("email", userList.get(i).getEmail());
document.append("bookmarks", userList.get(i).getBookmarksList() ) ;
WriteResult result = collection.insert(document);
This is the error I got when I ran the unit test .
java.lang.IllegalArgumentException: can't serialize class com.xxx.pojo.Bookmark
at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:272)
at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:173)
at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:119)
at com.mongodb.DefaultDBEncoder.writeObject(DefaultDBEncoder.java:27)
at com.mongodb.OutMessage.putObject(OutMessage.java:289)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:239)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:204)
at com.mongodb.DBCollection.insert(DBCollection.java:76)
at com.mongodb.DBCollection.insert(DBCollection.java:60)
at com.mongodb.DBCollection.insert(DBCollection.java:105)
Even after making the Bookmark POJO serializable I got the same error again .So I guess am using the Java API for insert in a wrong way . How to map the POJO directly into the mongodb element ?
As the error suggests can't serialize class com.xxx.pojo.Bookmark , which means that the List containing Bookmark.class can't be directly inserted in BasicDBObject document.
You need to use : BasicDBList as follows:
BasicDBList bookmark_list = new BasicDBList();
List<Bookmark> bmk_list = userList.get(i).getBookmarksList();
for(int i=0;i<bmk_list.size();i++)
{
String name = bmk_list.get(i).getName();
String category = bmk_list.get(i).getCategory();
String stats = bmk_list.get(i).getStats();
boolean tried = bmk_list.get(i).getTried();
DBObject db_obj = new BasicDBObject();
db_obj.put("name",name);
db_obj.put("category",category);
db_obj.put("stats",stats);
db_obj.put("tried",tried);
bookmark_list.add(db_obj);
}
Now add this bookmark_list in your document as follows:
BasicDBObject document = new BasicDBObject();
document.append("email", userList.get(i).getEmail());
document.append("bookmarks", bookmark_list ) ;
WriteResult result = collection.insert(document);

MongoDB/Java SDK: Query elements with a value in array

I am very new to MongoDB and its Java... SDK? Api? I have a very simple question, but I haven't been able to find a satisfactory answer.
Let's say I have a collection of instances that are like:
{
"_id": {
"$oid": "5156171e5d451c136236e738"
},
"_types": [
"Sample"
],
"last_z": {
"$date": "2012-12-30T09:12:12.250Z"
},
"last": {
"$date": "2012-12-30T04:12:12.250Z"
},
"section": "5156171e5d451c136236e70f",
"s_mac": "AA:AA:AA:AA:AA:AA",
"_cls": "Sample",
}
And I have a hard-coded Java list:
static List<String> MAC_LIST = Arrays.asList("90:27:E4:0E:3D:D2", "A8:26:D9:E6:1D:8B");
What I would like to know is how to query the MongoDB so it will give me all the objects whose s_mac field has a value that appears in the MAC_LIST List.
I'm guessing I should use the $in operator, but I don't know how to translate it to Java code.
Any hint or link to pages with explanations of the use of the $in operator through the Java SDK would be appreciated!
Here is a contrived example that works for me (driver version 2.10.1) - you can adjust the IP address and run it as is to check if you get the same outcome:
public void gss() throws Exception{
MongoClient mongo = new MongoClient("192.168.1.1");
DB db = mongo.getDB("test");
DBCollection collection = db.getCollection("stackoverflow");
DBObject o1 = new BasicDBObject();
o1.put("s_mac", "AA:AA:AA:AA:AA:AA");
o1.put("_cls", "Sample1");
DBObject o2 = new BasicDBObject();
o2.put("s_mac", "90:27:E4:0E:3D:D2");
o2.put("_cls", "Sample2");
DBObject o3 = new BasicDBObject();
o3.put("s_mac", "A8:26:D9:E6:1D:8B");
o3.put("_cls", "Sample3");
collection.insert(o1, o2, o3);
System.out.println(collection.find().count());
List<String> MAC_LIST = Arrays.asList("90:27:E4:0E:3D:D2", "A8:26:D9:E6:1D:8B");
System.out.println(collection.find(new BasicDBObject("s_mac", new BasicDBObject("$in", MAC_LIST))).count());
}
It inserts the following documents:
{ "_id" : ObjectId("5159ff98567e143bff0668e9"),
"s_mac" : "AA:AA:AA:AA:AA:AA",
"_cls" : "Sample1"
}
{ "_id" : ObjectId("5159ff98567e143bff0668ea"),
"s_mac" : "90:27:E4:0E:3D:D2",
"_cls" : "Sample2"
}
{ "_id" : ObjectId("5159ff98567e143bff0668eb"),
"s_mac" : "A8:26:D9:E6:1D:8B",
"_cls" : "Sample3"
}
A call to collection.find().count() returns 3 and a call to collection.find(new BasicDBObject("s_mac", new BasicDBObject("$in", MAC_LIST))).count() returns 2 which I think is what you expected.

Insert Array inside an object in MongoDB

I am new at MongoDB and I want to insert to mongodb data like this but I couldn't figure out how
{
image = "cab"
tags = [
[ "NNP", 0 ],
[ "NN", 1 ]
]
},
{
image = "castle"
tags = [
[ "NNP", 2 ],
[ "NN", 1 ],
]
}
my code is
BasicDBObject obj = new BasicDBObject();
obj.put("images", ....);
for(Tag tag:tags){
BasicDBObject tagsObj = new BasicDBObject();
tagsObj.put("NNP",tag.getNNP());
tagsObj.put("NN",tag.getNN());
obj.put("tags",tagsObj);
}
UPDATE:
using this code
Mongo m = new Mongo();
DB db = m.getDB("test");
DBCollection coll = db.getCollection("tags");
for(Tag tag:tags){
BasicDBList dbl = new BasicDBList();
dbl.add(new BasicDBObject("NNP",tag.getNNP()));
dbl.add(new BasicDBObject("NN", tag.getNNP()));
BasicDBObject outer=new BasicDBObject("images", currentImageName).append("tags", dbl);
coll.insert(outer);
}
I store every image alone cause the tags might be like this for the same image
{
image = "cab",
tags = [
{ "NNP", 0 },
{ "NN", 1 }
],
[ {"NNP", 4 },
{ "NN", 5 }
],
[
{"NNP", 0 },
{ "NN", 4 }
]
},
Thanks
Basically you use BasicDBObject for key-value mappings and BasicDBList for array objects. For the object in your question, you'd do this:
BasicDBList dbl = new BasicDBList();
dbl.add(new BasicDBObject("NNP",0));
dbl.add(new BasicDBObject("NN", 1));
BasicDBOBject outer=new BasicDBObject("image", "cab").append("tags", dbl);
There's some convenience methods in the api to make this a bit less verbose.
The mapping works like this:
for: {"A":1} use: new BasicDBObject("A",1)
for: {"A":1, "B":2} use: new BasicDBObject("A",1).append("B",2)
for: {"A":{"B":2}} use: new BasicDBObject("A",new BasicDBObject("B",2))
for: {"A":["B","C"]} use:
BasicDBList dbl = new BasicDBList();
dbl.add("B");
dbl.add("C");
-> new BasicDBObject("A",dbl);
Did you mean like this?
BasicDBObject obj = new BasicDBObject();
obj.put("image", ....);
for(Tag tag:tags){
BasicDBObject tagsObj = new BasicDBObject();
tagsObj.put("NNP",tag.getNNP());
tagsObj.put("NN",tag.getNN());
obj.put("tags",tagsObj);
}
Here is how i use it when using mongo3.x:
suppose you want the result to be like this: {"data": [{"key":"v1"}, {"key":"v1"}, {"key":"v1"}] }
[step1]: use Java Map to create json object which maps to the elements inside the array; that is, the {} inside []
[step1 Ans]: Map m1,m2,m3 = new HashMap(); m1.put("key", "v1"); m2.put("key", "v1"); m3.put("key", "v1");
[step2]: use Java List to add all Java Map into one element.
[step2 Ans]: List list = new ArrayList(); list.add(m1); list.add(m2); list.add(m3);
[step3]: add Java list into mongo
[step3 Ans]: Document dc = new Document("key", list);

Categories