3

次の構造のドキュメントがあります。

user {id: 123,  tag:"tag1"}
user {id: 123,  tag:"tag2"}
user {id: 123,  tag:"tag3"}
user {id: 456,  tag:"tag1"}

指定されたユーザー ID から、このユーザーに 3 つのタグすべて (AND オペランド) を持つレコードがあるかどうかを調べたいと考えています。ユーザーが「tag1」および「Tag2」および「tag3」のレコードを持っている場合、true を返します

同等の SQL は次のようになります。

SELECT * FROM users WHERE 
  EXISTS (SELECT * FROM tags WHERE user_id = users.id AND name ='tag1') AND
  EXISTS (SELECT * FROM tags WHERE user_id = users.id AND name ='tag2') AND 
  user_id=123

MongoDB で似たようなものを表現するにはどうすればよいですか?

4

1 に答える 1

5

MongoDB には結合の概念がないため、入力を 1 つのドキュメントに減らすことで、結合の概念を超えて作業する必要があります。

次のように、タグの配列を格納するようにドキュメント構造を変更した場合:

{id: 123,  tag:["tag1","tag2","tag3"]}
{id: 456,  tag:["tag1"]}

次のようなクエリを実行できます。

db.user.find({$and:[{tag:"tag1"},{tag:"tag2"},{tag:"tag3"}]})

必要に応じて、map-reduce を記述して、ユーザー ID のタグの配列を発行することができるので、それに対して上記のクエリを実行できます。

編集 - シンプルな map-reduce を含む

find上記のクエリに役立つフォーマットに初期入力を取得するための非常に単純な map-reduce を次に示します。

var map = function() {emit(this.id, {tag:[this.tag]});}
var reduce = function(key, values){
   var result_array=[];
   values.forEach(function(v1){             
       v1.tag.forEach(function(v2){
        result_array.push(v2);
        });
    });
return {"tag":result_array};}

var op = db.user.mapReduce(map, reduce, {out:"mr_results"})

次に、次のように、map-reduce 出力コレクションに対してクエリを実行できます。

db.mr_results.find({$and:[{"value.tag":"tag1"},{"value.tag":"tag2"}, {"value.tag":"tag3"}]})
于 2012-08-10T06:03:31.473 に答える