How to execute full text search command in MongoDB with Java Driver ? - java

Mongo and Java gurus. Our team decided to use full text search API, introduced recently in MongoDB. However, we found some difficulties executing the command using the Java MongoDB driver.
here is my code I am using :
public BasicDBObject find(String search) {
BasicDBObject searchCommand = new BasicDBObject();
searchCommand.put("text", new BasicDBObject().append("search", search));
CommandResult commandResult = db.command(searchCommand);
}
This is what I get when I print
System.out.println(commandResult)
{ "serverUsed" : "/127.0.0.1:27017" , "errmsg" : "exception: wrong type for field (text) 3 != 2" , "code" : 13111 , "ok" : 0.0 }

Taken from a post on the Google group ( https://groups.google.com/forum/?fromgroups#!topic/mongodb-user/7jWUbunUcFQ ):
final DBObject textSearchCommand = new BasicDBObject();
textSearchCommand.put("text", collectionName);
textSearchCommand.put("search", textToSearchFor);
final CommandResult commandResult = db.command(textSearchCommand);
Shows exactly how to format the command.

Related

Why the aggregate function does not give the desired result?

Was trying to change the data type of all values in a specific field, without use of iterators.
Here tid is the field name
I tried running the code in Mongo using
var ch ={"$addFields" : { "tid" : { "$convert":{"input":"$tid" , "to" : 2}}}}
db.test.aggregate(ch);
Where test is my collection
Java Code :
BasicDBObject fieldObject = new BasicDBObject();
fieldObject.put("$convert",new BasicDBObject().append("input",
"$tid").append("to", 2));
BasicDBObject addField = new BasicDBObject("$addFields",new
BasicDBObject("tid",fieldObject));
System.out.println(addField);
List<BasicDBObject> options = new ArrayList<>();
options.add(addField);
details.aggregate(options);
When I ran the code in mongo command line, the data types are changing from Integer to String.
But no change when I run the same through java code. Is there any issue with my Java Code.

Querying timestamp field of mongo oplog using java

I am trying to query timestamp field of mongo oplog collection using java.
Below is the code.
BSONTimestamp timestamp1 = new BSONTimestamp(1499172935, 1);
BasicDBObject query1 = new BasicDBObject("ts", new BasicDBObject("$gt", timestamp1) );
DBCursor cursor = dbCollection.find(query1);
When I run above piece of code, it returns nothing.
Below is the converted query.
{ "ts" : { "$gt" : { "$ts" : 1499172935 , "$inc" : 1}} }
I executed the same query using robomongo and it also returns nothing.
db.getCollection('oplog.rs').find({ "ts" : { "$gt" : { "$ts" : 1499172935 , "$inc" : 1}} })
But when I changed the query to use Timestamp and executed it, it returns list of oplog records. Below is the working mongo query.
db.getCollection('oplog.rs').find({ "ts" : { "$gt" : Timestamp(1499172935 , 1)} })
How can I get the above query using java?
or
Is there any other way I can query oplog timestamp field using java?
You can use the type 'BsonTimeStamp' to build your filter.
BsonTimestamp lastReadTimestamp = new BsonTimestamp(time, inc);
Bson filter = new Document("$gt", lastReadTimestamp);
dbCollection.find(new Document("ts", filter));

How to convert mongo shell code to java code using document and mongo aggregation

How can I convert this code to java? How to use aggregation framework in java ? Can anyone please help me out...
My java code:
Document update = new Document("$project",new Document("TOTAL_EMPLOYEE_SALARY",new Document("$sum","$employees.EMP_SALARY")));
AggregationOutput output = coll.aggregate(update); // throwing some error in eclipse
My mongo shell code :
db.collection.aggregate([
{ "$project": {
"TOTAL_EMPLOYEE_SALARY": {
"$sum": "$employees.EMP_SALARY"
}
}}
])
So use a List:
List<Document> pipeline = Arrays.<Document>asList(
new Document("$project",
new Document("TOTAL_EMPLOYEE_SALARY",new Document("$sum","$employees.EMP_SALARY"))
)
);
AggregationOutput output = coll.aggregate(pipeline);

MongoDB querying with Java API

Here is the sample document of my MongoDB:
user:{
_id:1,
name:'xyz',
age:12,
mobile:21321312,
transaction:[{
trans_id:1,
prod:'a',
purchasedAt:ISODate("2015-02-01"),
},
{
trans_id:2,
prod:'b',
purchasedAt:ISODate("2015-02-01")
},
{
trans_id:3,
prod:'c',
purchasedAt:ISODate("2014-11-24")
}]
,...
}
My query looks like:
db.user.find({transaction:{$elemMatch:{prod:'a', purchasedAt:ISODate("2015-02-01")}}, transaction:{$elemMatch:{prod:{$nin:['b','c']}, purchasedAt:ISODate("2015-02-01")}}}).count()
I am trying to get the user count who have purchased product 'a' on date "2015-02-01" but not have purchased product b & c on same day.
So while trying to do this in Java with the query:
coll.find(new BasicDBObject().append("transaction", new BasicDBObject("$elemMatch", new BasicDBObject("prod", 'a').append("purchasedAt", Date))).append("transaction", new BasicDBObject("$elemMatch", new BasicDBObject("prod", new BasicDBObject("$nin",['b','c'])).append("purchasedAt", Date)));
I have also tried:
coll.find(new BasicDBObject("transaction", new BasicDBObject("$elemMatch", new BasicDBObject("prod", 'a').append("purchasedAt", Date))).append("transaction", new BasicDBObject("$elemMatch", new BasicDBObject("prod", new BasicDBObject("$nin",['b','c'])).append("purchasedAt", Date)));
where Date is "2015-02-01" in util.Date object.
I found out that Java ignores the $in part of the query, i.e. it ignores {transaction:{$elemMatch:{prod:'a', purchasedAt:ISODate("2015-02-01")}} & performs only $nin part.
I found out it by DBCursor object.
Here's the output of the cursor:
Cursor: Cursor id=0, ns=mydb.user, query={ "transaction" : { "$elemMatch" : { "prod" : { "$nin" : [ "b" , "c"]} , "purchasedAt" : { "$date" : "2015-02-01T00:00:00.000Z"}}}}, numIterated=0, readPreference=primary
Because of this my result is inaccurate. I wonder why the exact same query works well in Mongo shell but doesn't with Java API. Is there anything wrong with my query structure?
My guess is that this question is now moot, but, if you still do not consider it answered, are you looking for the "$not" operator, which can check for non-existance sort of.

Mongo DB Aggregate Query returns in Batches

I have the following code, :
CommandResult cr = db.doEval("db." + collectionName + ".aggregate("
+ query + ")");
Command result is giving in batches, where I need to get in single value.
Batch Result:{ "serverUsed" : "/servername" , "retval" : { **"_firstBatch**" : [ { "visitor_localdate" : 1367260200} , { "visitor_localdate"
Expected Result:
{ "serverUsed" : "/servername" , "retval" : { "**result**" : [ { "visitor_localdate" : 1367260200} , { "visitor_localdate"
The Mongo DB we are using is 2.6.4 with 64 bit.
Can any one help with this?. I am guessing there is some Configuration issue.
Your doing this all wrong. You don't need to jump through hoops like this just to get a dynamic collection name. Just use this syntax instead:
var collectionName = "collection";
var cursor = db[collectionName].aggregate( pipeline )
Where pipeline also is just the array of pipeline stage documents, ie:
var pipeline = [{ "$match": { } }, { "$group": { "_id": "$field" } }];
At any rate the .aggregate() method returns a cursor, you can iterate the results with standard methods:
while ( cursor.hasNext() ) {
var doc = cursor.next();
// do something with doc
}
But you are actually doing this in Java and not JavaScript, so from the base driver with a connection on object db you just do this:
DBObject match = new BasicDBObject("$match", new BasicDBObject());
DBObject group = new BasicDBObject("$group", new BasicDBObject());
List pipeline = new ArrayList();
pipeline.add(match);
pipeline.add(group);
AggregationOutput output = db.getCollection("collectionName").aggregate(pipeline);
The pipeline is basically a list interface of DBObject information where you construct the BSON documents representing the operations required.
The result here is of AggregationOutput, but cursor like results are obtainable by additionally supplying AggregationOptions as an additional option to pipeline
There was something related to bacth added in mongodb 2.6, more details here: http://docs.mongodb.org/manual/reference/method/db.collection.aggregate/#example-aggregate-method-initial-batch-size
From the link
db.orders.aggregate(
[
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } },
{ $limit: 2 }
],
{
cursor: { batchSize: 0 }
}
)
You might be having a cursor batch in your aggregate query
The answer from Neil Lunn is not wrong but I want to add that the result you were expecting is a result for mongodb versions earlier than v2.6.
Before v2.6, the aggregate function returned just one document containing a result field, which holds an array of documents returned by the pipeline, and an ok field, which holds the value 1, indicating success.
However, from mongodb v2.6 on, the aggregate function returns a cursor (if $out option was not used).
See examples in mongodb v2.6 documentation and compare how it worked before v2.6 (i.e. in v2.4):

Categories