[JAVA-1657] Java driver throws error with $query Created: 21/Feb/15  Updated: 11/Mar/15  Resolved: 22/Feb/15

Status: Closed
Project: Java Driver
Component/s: Query Operations
Affects Version/s: 2.12.5
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: sandip Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Hi ,

From the java driver when I run the attached query it throws following error

com.mongodb.MongoException: Can't canonicalize query: BadValue unknown top level operator: $query
at com.mongodb.QueryResultIterator.throwOnQueryFailure(QueryResultIterator.java:214)
at com.mongodb.QueryResultIterator.init(QueryResultIterator.java:198)
at com.mongodb.QueryResultIterator.initFromQueryResponse(QueryResultIterator.java:176)
at com.mongodb.QueryResultIterator.<init>(QueryResultIterator.java:64)
at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:86)
at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:66)
at com.mongodb.DBCursor._check(DBCursor.java:458)
at com.mongodb.DBCursor._hasNext(DBCursor.java:546)
at com.mongodb.DBCursor.hasNext(DBCursor.java:571)
at aap.main(aap.java:57)

The code and mongodb output is here:
mongos> db.test.find({$query:{}},

{"price":10}

)

{ "_id" : 1, "price" : 10 } { "_id" : 2, "price" : 20 } { "_id" : 3, "price" : 5 } { "_id" : ObjectId("54dadd1c63108d63b47e79c3") } { "_id" : ObjectId("54e23eb9e63b0d8071b5b2af") }

{ "_id" : ObjectId("54e23ed3e63b0d8071b5b2b0")

================================================
java Code:
MongoClient mongo = new MongoClient("<Hostname>", 27017);
DB db = mongo.getDB("test");

DBCollection table = db.getCollection("test");
DBObject searchQuery = (DBObject)JSON.parse("{$query:{}},

{'price':10}

");
DBCursor cursor = table.find(searchQuery);

while (cursor.hasNext())

{ System.out.println(cursor.next()); }

 Comments   
Comment by Jeffrey Yemin [ 11/Mar/15 ]

Yes, the recommended way to specify a sort is via the sort method on DBCursor. Whether or not you choose to do that by parsing JSON is up to you.

I did reproduce your results when connected to a mongos, and I don't have a hypothesis as to why it failed.

Comment by sandip [ 11/Mar/15 ]

Thanks . So do you suggest to use "sort" with the way you updated ?
Still the issue remains why the failed query works for when connected to mongo shard , not when connected to mongos

In your case single mongo instance is effectively like a shard . But can you try connecting to shard and check what happens ?

Comment by Jeffrey Yemin [ 11/Mar/15 ]

I can reproduce your results with a modified test program. I had to remove the array from the JSON string, as well as the projection, which was the second element of the array.

        MongoClient mongoClient = new MongoClient();
        DBCollection table = mongoClient.getDB("test").getCollection("JAVA1657");
        DBObject searchQuery = (DBObject) JSON.parse("{$query:{},$orderby:{'stu_id':1}}");
        table.findOne(searchQuery);

However, this works fine:

        MongoClient mongoClient = new MongoClient();
        DBCollection table = mongoClient.getDB("test").getCollection("JAVA1657");
 
        DBCursor cursor = table.find((DBObject) JSON.parse("{}"), (DBObject) JSON.parse("{'_id' : 0}"))
                               .sort((DBObject) JSON.parse("{'stu_id' : 1}"));

Comment by Jeffrey Yemin [ 10/Mar/15 ]

I connected to a standalone mongod, which is effectively like a shard.

Comment by sandip [ 10/Mar/15 ]

Have you tried connecting directly to the shard ? The exception will not be thrown .

Lets assume the shard is running on 27019 , instead of connecting to default 27017 connect to shard to 27019
MongoClient mongo = new MongoClient("myhost.com", 27019);

Comment by Jeffrey Yemin [ 10/Mar/15 ]

I'm not seeing the same results as you. Running this simplified sample program:

        MongoClient mongoClient = new MongoClient();
        DBCollection table = mongoClient.getDB("test").getCollection("JAVA1657");
        DBObject searchQuery = (DBObject) JSON.parse("[{$query:{},$orderby:{'stu_id':1}},{_'id':0}]");
        table.findOne(searchQuery);

I get an exception when connected to a mongod:

Exception in thread "main" com.mongodb.MongoException: Can't canonicalize query: BadValue unknown operator: $query
	at com.mongodb.QueryResultIterator.throwOnQueryFailure(QueryResultIterator.java:214)
	at com.mongodb.QueryResultIterator.init(QueryResultIterator.java:198)
	at com.mongodb.QueryResultIterator.initFromQueryResponse(QueryResultIterator.java:176)
	at com.mongodb.QueryResultIterator.<init>(QueryResultIterator.java:64)
	at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:86)
	at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:66)
	at com.mongodb.DBCollection.findOne(DBCollection.java:869)
	at com.mongodb.DBCollection.findOne(DBCollection.java:843)
	at com.mongodb.DBCollection.findOne(DBCollection.java:789)

Comment by sandip [ 09/Mar/15 ]

I have found something interesting

• Case 1: If we connect to mongos and try to execute the above code , we get an exception ( described in email below)
• Case 2: But if we connect to mongo shard directly , instead of connecting to mongos the query works.

Is this also expected?

Comment by Jeffrey Yemin [ 23/Feb/15 ]

The driver is not built in a way that allows you to do this, nor is the MongoDB wire protocol itself. You will have to pull out the pieces from the user-supplied query and apply them to the DBCursor in your own code.

Comment by sandip [ 23/Feb/15 ]

Hi ,

How can we try the orderby query . The orderby syntax inside java program looks like

DBObject searchQuery = (DBObject)JSON.parse("[{$query:{},$orderby:{'stu_id':1}},{_'id':0}]");
DBCursor cursor = table.find(searchQuery);

Our system is like this . The user provides a query as input and we take the input on send the query to mongodb for return result . So the above one you have mentioned will work . But what for the orderby queries ? Internally we dont change the query , just pass it as the way it is entered as input.

Thanks

Comment by Jeffrey Yemin [ 22/Feb/15 ]

The server generates this error because $query is not a query operator. If you're just trying to search for documents where price is 10, easiest way is:

table.find(QueryBuilder.start("price").is(10).get());
// or
table.find(new BasicDBObject("price", 10));
// or
table.find(JSON.parse("{price : 10}"));

Generated at Thu Feb 08 08:55:10 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.