2016-09-05 11 views
1

MongoDBクエリ言語を使用すると、$exists演算子を使用して特定のフィールドの有無に基づいてドキュメントをフィルタリングできます。MongoDBクエリは、定義済みセット内のキーのみを持つドキュメントを返します。

は、方法は、MongoDBの構文で、そこにされており、許可されたフィールドのセットKを与え、その結果からKのフィールドを持っていない文書を除外するために、しかし:

  • た余分な事前に知っていませんフィールド(K外)に遭遇する可能性があります
  • JavaScriptを使用していない、つまり$where演算子ですか?

例:セットK = [ "Some field" ]

{ 
    "Some field" : "foo" 
} 
{ 
    "Some field" : "bar", 
    "Some other field" : "foobar" 
} 

、唯一の最初の文書が返されます。

これは、両方のドキュメントを返すが余分なフィールドを削除する投影とどのように混同しないように注意してください。既知のフィールドKのセットが与えられると

答えて

1

MongoDBがsuをサポートするかどうかわかりませんあなたはmapReduceの助けを借りて達成することができます。

サンプルデータセットを想定します。

// Variable for map 
var map = function() { 
    var isAcceptable = true; 
    Object.keys(this).forEach(function (key) { 
     if (key != "_id" && white_list.indexOf(key) == -1) { 
      isAcceptable = false; 
     } 
    }); 

    if (isAcceptable == true) { 
     emit(1, this); 
    } 
}; 

// Variable for reduce 
var reduce = function (key, values) { 
    return values; 
}; 

db.collection.mapReduce(
    map, 
    reduce, 
    { 
     scope: {"white_list": ["Some field"]}, 
     out: {"inline": 1} 
    } 
); 

が返されます:

{ 
    "results" : [ 
     { 
      "_id" : 1, 
      "value" : { 
       "_id" : ObjectId("57cd7503e55de957c62fb9c8"), 
       "Some field" : "foo" 
      } 
     } 
    ], 
    "timeMillis" : 13, 
    "counts" : { 
     "input" : 2, 
     "emit" : 1, 
     "reduce" : 0, 
     "output" : 1 
    }, 
    "ok" : 1 
} 

所望の結果が返される文書のresults.valuesになります。しかし、MongoDB mapReduceの制限とBSON文書の最大サイズを覚えておいてください。

0

は、入力としてのセットを取り、対応するフィールドの投影とともに$existsオペレータとクエリを与えるクエリを構築することができます。

var K = [ "fieldX", "fieldZ" ]; 

var or = K.map(function(field) { 
    var obj = {}; 
    obj[field] = { "$exists": true }; 
    return obj; 
}); 

var P = K.reduce(function(doc, field) { 
    doc[field] = 1; 
    return doc; 
}, {}); 

var Q = { "$or": or }; 

db.test.find(Q, P); 

サンプル出力を:例を使用すると、あなたが次に

db.test.insert({ "fieldX": "foo", "fieldY": "bar", "fieldZ": 1 }) 
db.test.insert({ "fieldX": "123", "fieldY": "bar", "fieldZ": 2 }) 
db.test.insert({ "fieldY": "abc", "fieldZ": 3 }) 
db.test.insert({ "fieldX": "xyz", "fieldZ": 4 }) 
db.test.insert({ "fieldZ": 5 }) 

クエリQと投影を構築することができますP次のように入力Kセットからテストコレクションの次のドキュメントがあるとし:

/* 1 */ 
{ 
    "_id" : ObjectId("57cd78322c241f5870c82b7d"), 
    "fieldX" : "foo", 
    "fieldZ" : 1 
} 

/* 2 */ 
{ 
    "_id" : ObjectId("57cd78332c241f5870c82b7e"), 
    "fieldX" : "123", 
    "fieldZ" : 2 
} 

/* 3 */ 
{ 
    "_id" : ObjectId("57cd78332c241f5870c82b7f"), 
    "fieldZ" : 3 
} 

/* 4 */ 
{ 
    "_id" : ObjectId("57cd78332c241f5870c82b80"), 
    "fieldX" : "xyz", 
    "fieldZ" : 4 
} 

/* 5 */ 
{ 
    "_id" : ObjectId("57cd78332c241f5870c82b81"), 
    "fieldZ" : 5 
} 
+1

ありがとうございます。しかし、あなたの例では、文書4と5だけが返されると思います。 1,2,3は 'fieldX'と' fieldZ'だけが存在することが許されているという要求に合致しません。言い換えれば、 'Object.keys(doc)'が 'K'のサブセットであるような文書' doc'だけが返されます。 –

関連する問題