在使用 sort
时,我无法进行查询。我希望查询的结果与我没有使用 sort
时完全相同,当然,结果应该是排序的,但是当使用 sort< 时会发生什么
我什么也没得到。
这是重现问题的完整示例:
DB db = fongo.getDB( "something" );
DBCollection collection = db.getCollection( "what" );
collection.insert( new BasicDBObject( "hello", 4 ) );
collection.insert( new BasicDBObject( "hello", 2 ) );
collection.insert( new BasicDBObject( "hello", 1 ) );
collection.insert( new BasicDBObject( "hello", 3 ) );
final DBCursor sorted = collection
.find( new BasicDBObject( "hello", new BasicDBObject( "$exists", true ) ) )
.sort( new BasicDBObject( "hello", 1 ) )
.limit( 10 );
final DBCursor notSorted = collection
.find( new BasicDBObject( "hello", new BasicDBObject( "$exists", true ) ) )
.limit( 10 );
// both asserts below work!
assertThat( notSorted.size(), is( 4 ) );
assertThat( sorted.size(), is( 4 ) );
List<DBObject> notSortedAsList = notSorted.toArray();
List<DBObject> sortedAsList = sorted.toArray();
assertThat( notSortedAsList.size(), is( 4 ) );
assertThat( sortedAsList.size(), is( 4 ) ); // << BREAKS HERE!!!!
assertThat( sortedAsList.stream().map( obj -> obj.get( "hello" ) )
.collect( Collectors.toList() ), is( Arrays.asList( 1, 2, 3, 4 ) ) );
如您所见,notSortedAsList
列表包含 4 个元素,正如预期的那样,但是 sortedAsList
是空的!!唯一的区别是后者是根据包含 sort
的查询创建的。
除非我做错了什么,这似乎是 MongoDB Java 驱动程序中的错误,尽管它也可能与 Fongo
有关,因为我正在使用它来测试它。
对正在发生的事情有什么想法吗??
编辑
这是上面显示的包含排序的查询生成的内容:
find({ "query" : { "hello" : { "$exists" : true}} , "orderby" : { "hello" : 1}}, null).skip(0).limit(10)
没有sort
,查询看起来像这样:
find({ "hello" : { "$exists" : true}}, null).skip(0).limit(10)
我也试过做以下查询:
final DBCursor sorted = collection
.find( new BasicDBObject( "hello", new BasicDBObject( "$exists", true ) ) )
.addSpecial( "$orderby", new BasicDBObject( "hello", 1 ) )
.limit( 10 );
生成的查询是:
find({ "$orderby" : { "hello" : 1} , "query" : { "hello" : { "$exists" : true}}}, null).skip(0).limit(10)
两者的结果相同,尽管第一个使用 orderby
而第二个使用 $orderby
(如此处建议:http://docs.mongodb.org/manual/reference/operator/meta/orderby/#op._S_orderby)
最佳答案
嗯,我发现了问题。正如我在对该问题的评论中提到的,当您调用 sort
时,MongoDB 驱动程序开始使用 meta-query operators。而不是像通常那样只是一个简单的对象查询。
例如,没有排序的简单查询如下所示:
find({ "hello" : { "$exists" : true}}, null)
上面的代码会找到任何包含名为 "hello"
的字段的文档。
但是,当您使用 sort
时,查询看起来像这样:
find({ "query" : { "hello" : { "$exists" : true}} , "orderby" : { "hello" : 1}}, null)
这是错误的,因为它将匹配包含名为 "query"
的字段和上述值的文档,以及名为 "orderby"
的字段...
正确的查询应该是:
find({ "$orderby" : { "hello" : 1} , "$query" : { "hello" : { "$exists" : true}}}, null)
唯一的区别是使键成为元运算符的 $
。
为了证实这个假设,我修改了我的代码以使用 addSpecial
(它允许我向查询添加元运算符)并尝试“取消”自动生成的(错误的) )查询,如下:
final DBCursor sorted = collection
.find( )
.addSpecial( "$orderby", new BasicDBObject( "hello", 1 ) )
.addSpecial( "$query", new BasicDBObject( "hello", new BasicDBObject( "$exists", true ) ) )
.limit( 10 );
因为这仍然会在查询中保留错误的 "query"
运算符,所以我不得不在我的文档中添加一个 query
字段以使其最终起作用:
collection.insert( new BasicDBObject( "hello", 4 ).append( "query", 1 ) );
...
现在以上所有测试都通过了!
显然,这是一次可怕的黑客攻击,希望 MongoDB 团队尽快修复 Java 客户端。与此同时,我至少可以让它正常工作。
我试图在 Java Driver JIRA 中发布错误但我找不到如何注册。
编辑 2
实际上,刚发现我可以注册并创建了一个工单:JAVA-1176
** 编辑 3 **
刚刚与 MongoDB 团队一起发现这个问题在最新版本的 Fongo(撰写本文时为 1.4.5)和 Java 驱动程序版本 2.11.4 中不再存在。
遗憾的是,由于兼容性问题,目前我们还不能使用最新版本(2.12.0)的Java驱动,但以上版本不会出现该问题!
关于java - MongoDB Java 客户端 - 为什么 `sort` 似乎中断了我的查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23244651/