0

この2つのバイナリ文字列10110と01111のようなMongoDBコレクションがあります

 { element_id:a, field_1:1, field_2:0, field_3:1, field_4:1, field_5:0} #binary string: 10110
 { element_id:b, field_1:0, field_2:1, field_3:1, field_4:1, field_5:1} #binary string: 01111

候補のバイナリ文字列「11111」をMongoDBに照会したいのですが、最小のmatch(AND)値は4です(5つすべてではありません)。つまり、DBからそのドキュメントを選択するために必要なのは、1つの位置に一致する4つだけです。

したがって、期待される出力は--element_id:bになります。

MongoDBサイトまたはGoogleで何も見つかりませんでした。誰か助けてもらえますか?

4

3 に答える 3

2

MapReduceは、Chien-Weiからの以前の回答によると良いアプローチです。MongoDB 2.2では、AggregationFrameworkの使用を検討することもできます。

たとえば、常に11111と一致している場合は、対象$addのフィールドの値を指定$matchしてから、少なくとも4のフィールドの値のみを一致させることができます。

db.element.aggregate(
    // Could use an initial $match here to find candidate documents (using indexed query)

    // Use $project to add calculated total
    { $project: {
        _id: 0,
        element_id: 1,
        // Assume we are matching 11111 and field values are always 0 or 1
        total: { $add: [ "$field_1", "$field_2", "$field_3", "$field_4", "$field_5" ] }
    }},

    // Filter to interesting results (at least 4 fields with '1')
    { $match: {
        total : { $gte : 4 }
    }}
)

サンプル出力:

{ "result" : [ { "element_id" : "b", "total" : 4 } ], "ok" : 1 }

より一般的な比較が必要な場合は$cond、ターゲット配列と条件付きで照合するために使用できます。例:

var targetArray = [1,1,1,1,1];
db.element.aggregate(
    // Could use an initial $match here to find candidate documents (using indexed query)

    // Use $project to add calculated total
    { $project: {
        _id: 0,
        element_id: 1,
        total: { $add: [
            { $cond:[{$eq:["$field_1", targetArray[0]]}, 1, 0 ]},
            { $cond:[{$eq:["$field_2", targetArray[1]]}, 1, 0 ]},
            { $cond:[{$eq:["$field_3", targetArray[2]]}, 1, 0 ]},
            { $cond:[{$eq:["$field_4", targetArray[3]]}, 1, 0 ]},
            { $cond:[{$eq:["$field_5", targetArray[4]]}, 1, 0 ]}
        ]}
    }},

    // Filter to interesting results (at least 4 fields with a match)
    { $match: {
        total : { $gte : 4 }
    }}
)

集計オプションと現在の制限の一般的な比較については、関連するStackOverflowの質問:MongoDB集計の比較:group()、$ group、およびMapReduceを参照してください。

于 2012-11-28T13:13:02.397 に答える
1

これは私の方法ですが、少し醜いです...

私はmap/reduceを使用します:(f入力です。関数で配列を設定する必要があります)

m = function() { 
    c=0; 
    f = [1,1,1,1,1]; 
    if(f[0]==this.field_1){c++;} 
    if(f[1]==this.field_2){c++;} 
    if(f[2]==this.field_3){c++;} 
    if(f[3]==this.field_4){c++;} 
    if(f[4]==this.field_5){c++;} 
    if(c>=4){
        emit(this.element_id, c)
    }
};

r = function(key, values) { return {key:values}; };

db.test.mapReduce(m, r, {out:{inline:1}})['results']

そして結果:

[ { "_id" : "b", "value" : 4 } ]
于 2012-11-28T09:49:00.673 に答える
1

$or要求された要素のすべての可能な組み合わせに一致する修飾子を使用して、プログラムで複雑なクエリを作成できます。

buildQuery = function(arr){
  var N, i, j, query, subquery;
  N = arr.length;
  query = {$or: []};
  for (i = 1; i <= N; ++i) {
    subquery = {};
    for (j = 1; j <= N; ++j) {
      if (i === j) continue;
      subquery['field_' + j] = arr[j-1];
    }
    query.$or.push(subquery);
  }
  return query;
}

query = buildQuery([1,1,1,1,1]);
db.collection.find(query)

buildQuery出力は次のようになります。

{ '$or': 
   [ { field_2: 1, field_3: 1, field_4: 1, field_5: 1 },
     { field_1: 1, field_3: 1, field_4: 1, field_5: 1 },
     { field_1: 1, field_2: 1, field_4: 1, field_5: 1 },
     { field_1: 1, field_2: 1, field_3: 1, field_5: 1 },
     { field_1: 1, field_2: 1, field_3: 1, field_4: 1 } ] }
于 2012-11-28T13:33:31.297 に答える