MongoDB Java客户端 - 为什么`sort`似乎打破了我的查询?

时间:2014-04-23 12:43:15

标签: 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

1 个答案:

答案 0 :(得分:1)

好吧,我发现了问题。正如我在对该问题的评论中提到的那样,当您调用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(这允许我在查询中添加元运算符)以及尝试取消&#34;取消&#34;自动生成(和错误)查询,如下所示:

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不再存在此问题。

不幸的是,由于兼容性问题,我们还不能使用Java驱动程序的最新版本(2.12.0),但上述版本不会出现问题!

相关问题