java - MongoDB Java 客户端 - 为什么 `sort` 似乎中断了我的查询?

标签 java mongodb mongo-java fongo

在使用 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/

相关文章:

java - 随机无法识别 Maven 依赖项

java - Android 使用 SMS 网关

mongodb - 使用 ssl 身份验证在 scala 中连接 mongo 服务器

java - mongo + java + 打开的文件太多

java - 如何使用 java 驱动程序更新 mongo db 中的文档字段?

java - 使用java对mongodb中的子文档数组进行排序

Java 邮件 TLS 身份验证

java - Mongodb 查询通过其值查找所有键

python - Pymongo 查找和修改

java - 严格替代 Spring @Transactional 注释