【问题标题】:MongoDB Java client - why does `sort` seem to break my query?MongoDB Java 客户端 - 为什么“排序”似乎破坏了我的查询?
【发布时间】:2014-04-23 12:43:15
【问题描述】:

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

【问题讨论】:

  • 当您说assertThat( sorted.size(), is( 4 ) ); 语句有效时,我会假设sort 查询的结果按预期工作。可能是List&lt;DBObject&gt; sortedAsList = sorted.toArray(); 的问题?
  • 我也尝试过使用sorted.iterator(),但这也不会返回任何元素。
  • 生成的查询不应该只有$query而不是query吗???

标签: java mongodb mongo-java fongo


【解决方案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(它允许我将元运算符添加到查询中)并尝试“取消”自动生成的(和错误的)查询,如下所示:

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 ) );
...

现在上面的所有测试都通过了!

显然,这是一个可怕的 hack,希望 MongoDB 团队尽快修复 Java 客户端。与此同时,我至少可以让它工作。

我试图在Java Driver JIRA 中发布一个错误,但我不知道如何注册。

编辑 2

其实,刚刚发现我可以注册并创建票:JAVA-1176

** 编辑 3 **

刚刚与 MongoDB 团队一起发现,最新版本的 Fongo(撰写本文时为 1.4.5)和 Java 驱动程序版本 2.11.4 不再存在此问题。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多