为什么这两个 MongoDB 查询不同?

Why are these two MongoDB queries different?

我是 MongoDB 新手。

鉴于此文档:

{ "x" : 5, "y" : 1 }

这个查询匹配它:

{ "$and" : [ {"y" : 1}, {"$or" : [ {"x" : 1}, {"x" : 5} ] } ] }

但这个不是:

{ "y" : 1, "$or" : [ {"x" : 1}, {"x" : 5} ] }

有什么原因吗?

更进一步:

我可以将查询简化为 "degenerate" $ 或 case:

{ "y" : 1, "$or" : [ {"x" : 5} ] }

它仍然不匹配。但是这个确实如此:

{ "y" : 1, "x" : 5 }

这个也是:

{ "$or" : [ { "y" : 1 } ], "$or" : [ { "x" : 5 } ] }

一般来说,当顶级查询文档中有多个谓词时,它们似乎被视为隐式 AND。这似乎与文档一致。

但是如果 "top-level implicit AND" 中的谓词是逻辑 ($and/$or) 与文字比较 (y:1) 的混合,那么它 "fails"。

但是显式 $and 中的同一组谓词将 "succeed"。

我只是想知道这种行为是否是预期的,如果是,为什么。

所有这些查询都有效。

> db.test.drop()
true
> db.test.insert({ "x" : 5, "y" : 1 })
WriteResult({ "nInserted" : 1 })
> db.test.find({ "$and" : [ {"y" : 1}, {"$or" : [ {"x" : 1}, {"x" : 5} ] } ] })
{ "_id" : ObjectId("54f20e0a0d484029bca053c4"), "x" : 5, "y" : 1 }
> db.test.find({ "y" : 1, "$or" : [ {"x" : 1}, {"x" : 5} ] })
{ "_id" : ObjectId("54f20e0a0d484029bca053c4"), "x" : 5, "y" : 1 }
> db.test.find({ "y" : 1, "$or" : [ {"x" : 5} ] })
{ "_id" : ObjectId("54f20e0a0d484029bca053c4"), "x" : 5, "y" : 1 }

万一以后有人看到这个,这里是发生了什么:

简而言之,当使用 mongo C 驱动程序时,"failed" 的查询实际上从未发送到 Mongo 服务器。我从来没有注意到这一点,因为我没有检查错误。

我的代码是这样的:

mongoc_cursor_t *cursor = mongoc_collection_find(whatever);
const bson_t   *doc_mongo = NULL;
while (mongoc_cursor_next(cursor, &doc_mongo))
{
    whatever
}

但在那之后,我需要有类似于以下代码片段的内容才能看到错误消息:

if (mongoc_cursor_error (cursor, &error))
{
    fprintf (stderr, "Failed to iterate all documents: %s\n", error.message);
}

我看到的错误消息看起来像这样:

"Cannot mix top-level query with dollar keys such as..."

修复方法是始终将查询文档包装在关键字“$query”下的另一个文档中。

bson_t* wrap(bson_t* q)
{
    bson_t *b = bson_new ();
    bson_append_document(b, "$query", -1, q);
    return b;
}

在此处找到更多信息:

http://qnalist.com/questions/5650929/mongodb-user-cdriver-cannot-use-or-and-in-find-queries