1

基本问题:

以下 2 个查询是否是等效的?

(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()

第一个查询按预期使用索引。第二个没有。

问题总结

  1. 这两个 find() 查询是否等效?
  2. 如果是这样,为什么他们的行为不同?如果不是,它们有何不同?
  3. 如何在没有 $ 和使用 C# 驱动程序的情况下生成 find()?

编辑--------

作为记录,我在 C# 中使用的语法类似于:

coll.find(Query.And([<id query>, <fields query>]));

手动生成 QueryDocument 不起作用,因为它不能包含多个 $or 查询,因为 $or 用作字典的键(我需要多个 $or 在我的实际查询中)。

4

2 回答 2

0

我已经确定,当 mongo 文档声明它在指定逗号分隔的操作列表时提供隐式 AND 时,它有些误导。进行以下查询:

// Returns 19 documents on sample data.
coll.find({{a simple query}, {an $or query}, {another $or query}})

在上述情况下,我发现 $or 查询之一可能会被忽略。也就是说,这 3 个查询没有与 $and 组合。提供明确的 $ 并解决此问题:

// Returns 2 documents on the same sample data.
coll.find({$and: [{a simple query}, {an $or query}, {another $or query}]})
于 2013-11-01T05:13:38.180 回答
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 转换为隐式 AND 的内部能力是不完善的,并且这就是为什么你只想在必要时使用$and

于 2013-11-01T05:17:39.183 回答