为什么这两个 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
我是 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