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

最初のクエリは、期待どおりにインデックスを使用します。2番目はそうではありません。

質問のまとめ

  1. 2 つの find() クエリは同等ですか?
  2. もしそうなら、なぜ彼らの行動は違うのですか?そうでない場合、それらはどのように異なりますか?
  3. $and を使用せずに C# ドライバーを使用して find() を生成するにはどうすればよいですか?

編集--------

記録として、私が C# で使用している構文は次のようなものです。

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

$or は辞書のキーとして使用されるため、複数の $or クエリを含めることはできないため、手動で QueryDocument を生成することはできません (実際のクエリでは複数の $or が必要です)。

4

2 に答える 2

0

はい、2 つのクエリは機能的に同等です。

このクエリの実行について

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 クエリが使用するのに、明示的な AND を暗黙的な AND に変換する Mongo の内部機能が不完全であるように思われます。そのため、必要な場合にのみ使用$andします。

于 2013-11-01T05:17:39.183 に答える