How to custom search for text query in mongodb? - java

I'm new in mongodb. I have following data as a JSON format in mongodb. I need to search the bookLabel or the shortLabel for the book and it should show me all the information about the book. For example: if I query for 'Cosmos' it'll show all the description about the book, like: bookLabel, writer, yearPublish, url. How can I do that in java? Need query, please help.
"Class":"Science",
"Description":[
{
"bookLabel":"Cosmos (Mass Market Paperback)",
"shortLabel":"Cosmos",
"writer":"Carl Sagan",
"yearPublish":[
"2002"
],
"url":"https://www.goodreads.com/book/show/55030.Cosmos"
},
{
"bookLabel":"The Immortal Life of Henrietta Lacks",
"shortLabel":"Immortal Life",
"writer":"Rebecca Skloot",
"yearPublish":[
"2010, 2011"
],
"url":"https://www.goodreads.com/book/show/6493208-the-immortal-life-of-henrietta-lacks"
}
],
"Class":"History",
"Description":[
{
"bookLabel":"The Rise and Fall of the Third Reich",
"shortLabel":"Rise and Fall",
"writer":"William L. Shirer",
"yearPublish":[
"1960"
],
"url":"https://www"
}
]
}

With MongoDB Java Driver v3.2.2 you can do something like this:
FindIterable<Document> iterable = collection.find(Document.parse("{\"Description.shortLabel\": {$regex: \"Cosmos\"}"));
This returns all documents containing Cosmos in the Description.shortLabel nested field. For an exact match, try this {"Description.shortLabel": "Cosmos"}. Replace shortLabel with bookLabelto search the bookLabel field. Then you can do iterable.forEach(new Block<Document>()) on the returned documents. To search both bookLabel and shortLabel, you can do a $or{}. My syntax could be wrong so check the MongoDB manual. But this is the general idea.

For this, you can use MongoDB's Text Search Capabilities. You'll have to create a text index on your collection for that.
First of all create a text index on your collection on fields bookLabel and shortLabel.
db.books.createIndex({ "Description.bookLabel" : "text", "Description.shortLabel" : "text" })
Note that this is done in the Mongo shell
Then
DBObject command = BasicDBObjectBuilder
.start("text", "books")
.append("search", "Cosmos")
.get();
CommandResult result = db.command(command);
BasicDBList results = (BasicDBList) result.get("results");
for(Object o : results) {
DBObject dbo = (DBObject) ((DBObject) o).get("obj");
String id = (String) dbo.get("_ID");
System.out.println(id);
}
Haven't really tested this. But just give it a try. Should work.

Related

How to save a searchable and queryable json document in Postgres?

Receiving a Person's profile as JSON. How can I model it in a way it every value of this JSON document is searchable?
Not only json document needs to be searchable. It should also be queryable like "find all the persons who like Tarantino movies".
I can define this document in a relational model with one to many relationships. But this approach wouldn't allow free text search from the client side.Is there a better way to handle such scenarios? Document look like this:
{
"name":"FirstN LastN",
"photo":nicephoto.jpg,
"location":"Boston, MA",
"contacts":[
{
"type":"phone",
"value":"701290012734"
},
{
"type":"email",
"value":"test#test.com"
}
],
"movies":[
{
"name":"The Godfather",
"director":"Francis Ford Coppola",
"releaseYear":"1972",
"favQuote":"I'm gonna make him an offer he can't refuse. Okay?"
},
{
"name":"Pulp Fiction",
"director":"Quentin Tarantino",
"releaseYear":"1994",
"favQuote":"Just because you are a character doesn't mean that you have character."
}
],
"school":null,
}
"find all the persons who like Tarantino movies" needs to be written or converted in SQL like:
select persons->>'name' from jdoc,json_array_elements(jdoc.persons->'movies') movies where movies->>'director' ~ 'Tarantino';
other selection criteria can be modeled in similar way.
Requires Postgres 9.3 or later
http://sqlfiddle.com/#!15/652eb/10
to the question "how to save":
create table jdoc (persons json);
insert into jdoc values ('{
"name":"FirstN LastN",
"photo":"nicephoto.jpg",
"location":"Boston, MA",
"contacts":[
{
"type":"phone",
"value":"701290012734"
},
{
"type":"email",
"value":"test#test.com"
}
],
"movies":[
{
"name":"The Godfather",
"director":"Francis Ford Coppola",
"releaseYear":"1972",
"favQuote":"Im gonna make him an offer he cant refuse. Okay?"
},
{
"name":"Pulp Fiction",
"director":"Quentin Tarantino",
"releaseYear":"1994",
"favQuote":"Just because you are a character doesnt mean that you have character."
}
],
"school":null
}')
;
You might be looking for FLWOR:
for $d in doc("depts.xml")//deptno
let $e := doc("emps.xml")//employee[deptno = $d]
where count($e) >= 10
order by avg($e/salary) descending
return
<big-dept>
{ $d,
<headcount>{count($e)}</headcount>,
<avgsal>{avg($e/salary)}</avgsal>
}
</big-dept>
although it doesn't look like Postgres has plans to support Xquery.

MongoDB - How to find and append / find and upsert both document and fields

In Mongo, is there a built-in way to update a document and instead of replacing all contents of the query document, to update those nodes which are the same and append those which do not exist in the original document.
For example, imagine I insert the following document into my collection:
{
"name" : "Goku",
"level" : 9000
}
Now, at some later point, I wish to update my existing document with the following document I received:
{
"name" : "Goku",
"son" : "Gohan"
}
Ideally, I would like a way to perform an update and produce the following document:
{
"name" : "Goku",
"level" : 9000,
"son" : "Gohan"
}
The standard case is to overwrite the existing document with the new document (as it should be). However, is there a built-in or clever way to achieve the result above without first finding the first document, appending onto it, and then performing an update?
Thanks.
-- EDIT --
#pennstatephil has the correct answer below. Just in case anyone's is helped by this, here's an implementation of this example in Java as of driver version 2.12.0:
String json = "{'name' : 'Goku', 'level' : 9000 }";
DBObject document = (DBObject) JSON.parse(json);
BasicDBObject update = new BasicDBObject("$set", document);
BasicDBObject query = new BasicDBObject().append("name", document.get("name"));
collection.findAndModify(query, null, null, false, update, false, true);
json = "{'name' : 'Goku', 'son' : 'Gohan'}";
document = (DBObject) JSON.parse(json);
update = new BasicDBObject("$set", document);
query = new BasicDBObject().append("name", document.get("name"));
collection.findAndModify(query, null, null, false, update, false, true);
I believe findAndModify and $set (on the update clause) is what you're looking for.

MongoDB find query

I use mongoDB to collect comments inside a collection comments
I use this java programme to create them
...
BasicDBObject comment=new BasicDBObject();
BasicDBObject auteur=new BasicDBObject();
auteur.put("id", id);
auteur.put("login", login);
auteur.put("contact",false);
comment.put("auteur",auteur);
comment.put("texte",texte);
...
When i try to find the comment using the field texte it works:
db.comments.find({"texte":"my name is user1"})
{
"_id" : ObjectId("5341395ae4b082f5895d5967"),
"auteur" : { "id" : 1, "login" : "user1", "contact" : false },
"texte" : "my name is user1"
}
However my aim is to find them by using the the field id of auteur.
I tried
db.comments.find({"auteur":{"id":1}})
but it returns nothing...
I'm really lost. Thanks!!
You would use the Dot Notation to access the id of the sub document auteur:
db.comments.find({"auteur.id": 1});
The dot notation can also be used to access an element of an array by the zero-based index position:
db.things.find({"an_array_name.15": "a text to search..."});
Regards.
Mohamed.

Remove and Add new array into the JSON object using MongoDB

I have JSON object :
{ "_id" : "1", "_class" : "com.model.Test", "projectList" : [ {
"projectID" : "Spring", "resourceIDList" : [ "Mark","David" ] },
{ "projectID" : "MongoDB", "resourceIDList" : [ "Nosa ] }
I need to be able to remove the resourceIDList for Project "Spring" and assign a new ResourceIDList.
The ResourceIDList is just List
Whenever I try to use the following,nothing is updated at DB:
Query query = new Query(where("_id").is("1").and("projectID").is("Spring"));
mongoOperations.updateMulti( query,new Update().set("ressourceIDList", populateResources()), Test.class);
Replacing the resourceIDList in the embedded document matching {"projectList.projectID":"Spring"} may be accomplished in the JavaScript shell like so:
(I like to start with the JS shell, because it is less verbose than Java and the syntax is relatively straightforward. Examples with JS can then be applied to any of the language drivers.)
> db.collection.update({_id:"1", "projectList.projectID":"Spring"}, {$set:{"projectList.$.resourceIDList":["Something", "new"]}})
The documentation on using the "$" operator to modify embedded documents may be found in the "The $ positional operator" section of the "Updating" documentation:
http://www.mongodb.org/display/DOCS/Updating#Updating-The%24positionaloperator
There is more information on embedded documents in the "Dot Notation (Reaching into Objects)" Documentation:
http://www.mongodb.org/display/DOCS/Dot+Notation+%28Reaching+into+Objects%29
The above may be done in the Java Driver like so:
Mongo m = new Mongo("localhost", 27017);
DB db = m.getDB("test");
DBCollection myColl = db.getCollection("collection");
ArrayList<String> newResourceIDList = new ArrayList<String>();
newResourceIDList.add("Something");
newResourceIDList.add("new");
BasicDBObject myQuery = new BasicDBObject("_id", "1");
myQuery.put("projectList.projectID", "Spring");
BasicDBObject myUpdate = new BasicDBObject("$set", new BasicDBObject("projectList.$.resourceIDList", newResourceIDList));
myColl.update(myQuery, myUpdate);
System.out.println(myColl.findOne().toString());
If you have multiple documents that match {"projectList.projectID" : "Spring"} you can update them at once using the multi = true option. With the Java driver it would look like this:
myColl.update(myQuery, myUpdate, false, true);
In the above, "false" represents "upsert = false", and "true" represents "multi = true". This is explained in the documentation on the "Update" command:
http://www.mongodb.org/display/DOCS/Updating#Updating-update%28%29
Unfortunately, I am not familiar with the Spring framework, so I am unable to tell you how to do this with the "mongoOperations" class. Hopefully, the above will improve your understanding on how embedded documents may be updated in Mongo, and you will be able to accomplish what you need to do with Spring.

MongoDB and Java: Query doesn't return results

I'm using the MongoDB Java driver, and can't seem to get a query to work. I have a collection named "Questions", which has entries that look like:
{
"question" : "how are you",
"category" : "personal",
"processed" : false,
"training" : true
}
When running the Mongo command line client, the query
db.questions.find()
or
db.questions.find({"processed" : false, "training" : true})
results are returned as expected; however, my java code does the following:
DBObject queryObj = new BasicDBObject();
queryObj.put("processed", false);
queryObj.put("training", isTrain);
DBObject updateObj = new BasicDBObject();
queryObj.put("processed", true);
DBCursor cursor = mongoCollection.find(queryObj).limit(NUM_TO_LOAD);
mongoCollection.update(queryObj, updateObj);
and the cursor that is returned to me is empty/the update doesn't make any changes. If I remove the queryObj argument from the call to find, results are once again returned as expected. Am I doing something wrong here?
Thanks,
Chris Covert
looks like, you used the wrong variable on line 6. Shouldn't it be updateObj, instead of queryObj?
Hope isTrain is a boolean, and got correctly initiated with a value (true/false).

Categories

Resources