how to call count operation after find with mongodb java driver - mongodb

I am using MongoDB 3.0. suppose there is a set of documents named photos, its structure is
{"_id" : 1, photographer: "jack"}
with database.getCollection("photos"), Mongodb will return a MongoCollection object, on which I have the method count() to get the number documents returned.
However, when I make queries with specific conditions. For example find documents with id smaller than 100 :
photosCollections.find(Document.parse("{_id : {$lt : 100}}"))
Above find method will always return a cursor which doesn't provide a count() function. So how can I know how many documents returned ? I know on command line, I can use
db.photos.find({_id : {$lt : 100}}).count()
Of course, I can go through the iterator and count the number of documents myself. However I find it really clumsy. I am wondering does MongoDB java driver provides such functionality to count the number of documents returned by the find() method ? If not, what is the reason behind the decision ?

As you said the MongoCollection has the count() method that will return the number of documents in the collection, but it has also a count(Bson filter) that will return the number of documents in the collection according to the given options.
So you can just use:
long count = photosCollections.count(Document.parse("{_id : {$lt : 100}}"))
or maybe clearer:
Document query = new Document("_id", new Document("$lt", 100));
long count = photosCollections.count(query);
ref: http://api.mongodb.com/java/3.3/com/mongodb/client/MongoCollection.html#count-org.bson.conversions.Bson-

In MongoDB 3.4 you can only use the Iterator of FindIterable to get the count of the documents returned by a filter. e.g.
FindIterable findIterable =
mongoCollection.find(Filters.eq("EVENT_TYPE", "Sport"));
Iterator iterator = findIterable.iterator();
int count = 0;
while (iterator.hasNext()) {
iterator.next();
count++;
}
System.out.println(">>>>> count = " + count);

I had a similar problem. I am using MongoCollection instead of DBCollection, as it is what it is used in MongoDG 3.2 guide. MongoCollection hasn't got count() method, so I think the only option is to use the iterator to count them.
In my case I only needed to know if any document has been returned, I am using this:
if(result.first() != null)

Bson bson = Filters.eq("type", "work");
List<Document> list = collection.find(bson).into(new ArrayList<>());
System.out.println(list.size());
into(A) (A is collection type) method iterates over all the documents and adds each to the given target. Then we can get the count of the returned documents.

The API docs clearly state that DBCursor Object provides a count method:
MongoClient client = new MongoClient(MONGOHOST,MONGOPORT);
DBCollection coll = client.getDB(DBNAME).getCollection(COLLECTION);
DBObject query = new Querybuilder().start()
.put("_id").lessThan(100).get();
DBCursor result = coll.find(query);
System.out.println("Number of pictures found: " + result.count() );

Related

Retrieving a single field from MongoDB using Selenium/Java

I'm just switching from MySQL to MongoDB and it's a little confusing. We have our database stored in MongoDB and using Java-Selenium in the front end. I am trying to retrieve just one single data from the database. The code below retrieves all the data present in the database:
DBCursor cursor = dbCollection.find();
while(cursor.hasNext())
{
int i=1;
System.out.println(cursor.next());
i++;
}
This is my database lets say:
{
"name" : "Su_123",
"email" : "test#gmail.com",
"_id" : ObjectId("12345656565656")
}
I want to retrieve just the email field (test#gmail.com) from the document where _id = ObjectId("12345656565656") and store this in a String field.
How do I go about coding this? find() retrieves the entire row.
For newer drivers, since 3.7.1
To get specific document that matches a filter:
Document doc = collection.find(eq("email", "test#gmail.com")).first();
It can be used to find the first document where the field email has the value test#gmail.com. And pass an eq filter object to specify the equality condition.
By the same logic using id:
Document document = myCollection.find(eq("_id", new ObjectId("12345656565656"))).first();
To get specific value of the field from selected document:
String value = (String) doc.get("email");
For older drivers like 2.14.2 and 2.13.3
To get a single document with a query:
BasicDBObject query = new BasicDBObject("email", "test#gmail.com");
cursor = coll.find(query);
try {
while(cursor.hasNext()) {
//System.out.println(cursor.next());
}
} finally {
cursor.close();
}
To see more details for newer Mongodb Java driver.
To see more details for older Mongodb Java driver.
To see more details from Mongodb Official Docs.

Get the count of Fields in each document through query using MongoDB java driver

Is it possible to get the number of fields in document using a Query From MongoDB java Driver
Example:
Document1 :{_id:1,"type1": 10 "type2":30,"ABC":123,"DEF":345}
Document2 :{_id:2,"type2":30,"ABC":123,"DEF":345}
Note: In second document "type1" key doesnt exist .
When i project
Is it possible to project only "type1" and "type2" and get number of fields existing in that document.
With current code i am getting all the documents and individually searching if there is the key i am looking is present in the whole cursor:
The code snipped is as follows:
MongoClient mcl=new MongoClient();
MongoDatabase mdb=mcl.getDatabase("test");
MongoCollection mcol=mdb.getCollection("testcol");
FindIterable<Document> findIterable = mcol.find();
MongoCursor<Document> cursor = findIterable.iterator();
//Here am having 120 types checking if each type is present..
while(cursor.hasNext())
{
Document doc=cursor.next();
int numberOfTypes=0;
for(int i=1;i<=120;i++)
{
if(doc.containsKey("type"+i))
{
numberOfTypes++;
}
}
System.out.println("*********************************************");
System.out.println("_id"+doc.get("_id"));
System.out.println("Number of Types in this document are "+numberOfTypes);
System.out.println("*********************************************");
}
}
This code is working if the records are less it wont be over load to the application ..Suppose there are 5000000 with each Document containing 120 types , the application is crashing as there would be more garbage collection involved as for every iteration we are creating a document.Is there any other approach through which we can achieve the above stated functionality.
From your java code I read
project only "type1" and "type2" and get number of fields existing in that document.
as
project only type[1..120] fields and number of such fields in the document
With this assumption, you can map-reduce it as following:
db.testcol.mapReduce(
function(){
value = {count:0};
for (i = 1; i <= 120; i++) {
key = "type" + i
if (this.hasOwnProperty(key)) {
value[key] = this[key];
value.count++
}
}
if (value.count > 0) {
emit(this._id, value);
}
},
function(){
//nothing to reduce
},
{
out:{inline:true}
});
out:{inline:true} works for small datasets, when result fits into 16Mb limit. For larger responses you need to output to a collection, which you can query and iterate as usual.

When does MongoDB Fetch results in java driver

MongoClient mc=new MongoClient();
MongoDatabase mdb=mc.getDatabase("testdb");
MongoCollection mcol=mdb.getCollection("testcol");
FindIterable<Document> fi=mcol.find();
MongoCursor<Document> mcur=fi.iterator();
MongoCursor<Document> mcur2=fi.iterator();
will mcur and mcur2 have same results all the time as they are reference of FindIterable fi.
In which step of the above code mongodb will get the results Inside mongoCursor or FindIterable step?
mcol.find() is the point where the results are obtained, the .find() will pull all documents from the collection "testcol".
You don't necessarily need to use a FindIterable object an ordinary List<BasicDBObject> does work.
then you can iterate through using:
for(DBObject obj : objList) {
//perform operations
String name = (String) obj.get("nameOfField");
}
hope this helps.

spring data mongo - mongotemplate count with query hint

The mongo docs specify that you can specify a query hint for count queries using the following syntax:
db.orders.find(
{ ord_dt: { $gt: new Date('01/01/2012') }, status: "D" }
).hint( { status: 1 } ).count()
Can you do this using the mongo template? I have a Query object and am calling the withHint method. I then call mongoTemplate.count(query); However, I'm pretty sure it's not using the hint, though I'm not positive.
Sure, there are a few forms of this including going down to the basic driver, but assuming using your defined classes you can do:
Date date = new DateTime(2012,1,1,0,0).toDate();
Query query = new Query();
query.addCriteria(Criteria.where("ord_dt").gte(date));
query.addCriteria(Criteria.where("status").is("D"));
query.withHint("status_1");
long count = mongoOperation.count(query, Class);
So you basically build up a Query object and use that object passed to your operation, which is .count() in this case.
The "hint" here is the name of the index as a "string" name of the index to use on the collection. Probably something like "status_1" by default, but whatever the actual name is given.

MongoDB: Retrieving the first document in a collection

I'm new to Mongo, and I'm trying to retrieve the first document from a find() query:
> db.scores.save({a: 99});
> var collection = db.scores.find();
[
{ "a" : 99, "_id" : { "$oid" : "51a91ff3cc93742c1607ce28" } }
]
> var document = collection[0];
JS Error: result is undefined
This is a little weird, since a collection looks a lot like an array. I'm aware of retrieving a single document using findOne(), but is it possible to pull one out of a collection?
The find method returns a cursor. This works like an iterator in the result set. If you have too many results and try to display them all in the screen, the shell will display only the first 20 and the cursor will now point to the 20th result of the result set. If you type it the next 20 results will be displayed and so on.
In your example I think that you have hidden from us one line in the shell.
This command
> var collection = db.scores.find();
will just assign the result to the collection variable and will not print anything in the screen. So, that makes me believe that you have also run:
> collection
Now, what is really happening. If you indeed have used the above command to display the content of the collection, then the cursor will have reached the end of the result set (since you have only one document in your collection) and it will automatically close. That's why you get back the error.
There is nothing wrong with your syntax. You can use it any time you want. Just make sure that your cursor is still open and has results. You can use the collection.hasNext() method for that.
Is that the Mongo shell? What version? When I try the commands you type, I don't get any extra output:
MongoDB shell version: 2.4.3
connecting to: test
> db.scores.save({a: 99});
> var collection = db.scores.find();
> var document = collection[0];
In the Mongo shell, find() returns a cursor, not an array. In the docs you can see the methods you can call on a cursor.
findOne() returns a single document and should work for what you're trying to accomplish.
So you can have several options.
Using Java as the language, but one option is to get a db cursor and iterate over the elements that are returned. Or just simply grab the first one and run.
DBCursor cursor = db.getCollection(COLLECTION_NAME).find();
List<DOCUMENT_TYPE> retVal = new ArrayList<DOCUMENT_TYPE>(cursor.count());
while (cursor.hasNext()) {
retVal.add(cursor.next());
}
return retVal;
If you're looking for a particular object within the document, you can write a query and search all the documents for it. You can use the findOne method or simply find and get a list of objects matching your query. See below:
DBObject query = new BasicDBObject();
query.put(SOME_ID, ID);
DBObject result = db.getCollection(COLLECTION_NAME).findOne(query) // for a single object
DBCursor cursor = db.getCollection(COLLECTION_NAME).find(query) // for a cursor of multiple objects