基本问题:
以下两个查询是否相同?
(A) coll.find(k1:v1, k2:v2) // List of fields
(B) coll.find($and: [{k1:v1}, {k2:v2}]) // $and the list of fields
如果是这样,为什么他们表现出不同的行为? (见下文)。如果没有,我怎样才能在C#中生成前者?
进一步讨论
我正在索引子文档中的字段。查询(A)正确使用索引但查询(B)没有。
以下是一些示例代码(它将直接在mongo控制台中运行):
{
_id : Guid
..other stuff..
Fields: { K1: V1, K2: V2 ...}
}
// Populate
db.test.insert({_id:1,Fields:{K1:123,K2:456}})
db.test.insert({_id:2,Fields:{K1:456,K2:123}})
// Index on fields of subdocument
db.test.ensureIndex({"Fields.K1": 1})
db.test.ensureIndex({"Fields.K2": 1})...
// Execute some queries
db.test.find({_id: {$lt: 20}, "$or": [{"Fields.K1": 123}, {"Fields.K2": 123}]}).explain()
db.test.find({$and: [{_id: {$lt: 20}}, {"$or": [{"Fields.K1": 123}, {"Fields.K2": 123}]}]}).explain()
第一个查询按预期使用索引。第二个没有。
问题摘要
修改 --------
对于记录,我在C#中使用的语法类似于:
coll.find(Query.And([<id query>, <fields query>]));
手动生成QueryDocument不起作用,因为它不能包含多个$或查询作为$或用作字典的键(我需要多个$或在我的实际查询中)。
答案 0 :(得分:0)
我已经确定mongo文档在指出以逗号分隔的操作列表时提供隐式AND时有些误导。请进行以下查询:
// Returns 19 documents on sample data.
coll.find({{a simple query}, {an $or query}, {another $or query}})
在上面的例子中,我发现可以忽略其中一个$或查询。也就是说,3个查询没有与$和组合。提供明确的$并修复此问题:
// Returns 2 documents on the same sample data.
coll.find({$and: [{a simple query}, {an $or query}, {another $or query}]})
答案 1 :(得分:0)
是的,这两个查询功能相同。
关于执行此查询
db.test.find({
_id: {$lt: 20},
"$or": [{"Fields.K1": 123}, {"Fields.K2": 123}]
})
使用C#驱动程序,您可以使用:
var query = Query.And(Query.LT("_id", 20),
Query.Or(Query.EQ("Fields.K1", 123),
Query.EQ("Fields.K2", 123)));
var docs = test.Find(query);
即使使用Query.And
,也会生成隐式AND查询,因为您可以看到是否检查了调用query.ToJson()
的输出:
{ "_id" : { "$lt" : 20 }, "$or" : [{ "Fields.K1" : 123 }, { "Fields.K2" : 123 }] }
与原始查询匹配。
至于为什么一些显式的$and
查询不使用等价的隐式AND查询所做的索引(或使用不同的索引,如本例所示),看起来Mongo的内部转换显式的能力并且隐含的是不完美的,这就是为什么你只想要使用$and
的原因。