2012-02-07 10 views
3

はMongoのコレクションの次の例を考えてみましょう:レール&Mongoidユニークな結果

{"_id" : ObjectId("4f304818884672067f000001"), "hash" : {"call_id" : "1234"}, "something" : "AAA"} 
{"_id" : ObjectId("4f304818884672067f000002"), "hash" : {"call_id" : "1234"}, "something" : "BBB"} 
{"_id" : ObjectId("4f304818884672067f000003"), "hash" : {"call_id" : "1234"}, "something" : "CCC"} 
{"_id" : ObjectId("4f304818884672067f000004"), "hash" : {"call_id" : "5555"}, "something" : "DDD"} 
{"_id" : ObjectId("4f304818884672067f000005"), "hash" : {"call_id" : "5555"}, "something" : "CCC"} 

私はこのコレクションを照会し、それぞれ「CALL_ID」のための最初のエントリだけを取得したいと思い、他の言葉で私がしようとしています"call_id"に基づいてユニークな結果を得る。 私は方法.distinct使用しようとした:

@result = Myobject.all.distinct('hash.call_id') 

をしかし、結果の配列は、唯一のユニークなCALL_IDフィールドが含まれます:

["1234", "5555"] 

と私はあまりにも他のすべてのフィールドを必要としています。 は、このようなクエリを作成することが可能です?:

@result = Myobject.where('hash.call_id' => Myobject.all.distinct('hash.call_id')) 

あなたは単に明確なを使用して文書(またはサブセット)を返すことはできませんおかげ

答えて

7

documentationによれば、指定されたキーに基づいて異なる値の配列のみを返します。しかし、あなたは上記のコードは、マップ機能で、私は自明キーhash.call_idことによってそれをグループ化し、それがfuncitionを減らすことで処理できるように、全体のドキュメントを返していますされ

var _map = function() { 
    emit(this.hash.call_id, {doc:this}); 
} 

var _reduce = function (key, values) { 
    var ret = {doc:[]}; 
    var doc = {}; 
    values.forEach(function (value) { 
    if (!doc[value.doc.hash.call_id]) { 
      ret.doc.push(value.doc); 
      doc[value.doc.hash.call_id] = true; //make the doc seen, so it will be picked only once 
     } 
    }); 
    return ret; 
} 

-減らすマップを使用することによって、これを達成することができます。

オンセットにグループ化結果を通じて機能、単にループを低減し、(複数の重複するキー値のうち - 異なるシミュレーション)グループ化された組から一つの項目を選択します。

は、最後にあなたが明確なセットの最初の文書を入手

> db.disTest.insert({hash:{call_id:"1234"},something:"AAA"}) 
> db.disTest.insert({hash:{call_id:"1234"},something:"BBB"}) 
> db.disTest.insert({hash:{call_id:"1234"},something:"CCC"}) 
> db.disTest.insert({hash:{call_id:"5555"},something:"DDD"}) 
> db.disTest.insert({hash:{call_id:"5555"},something:"EEE"}) 
> db.disTest.find() 
{ "_id" : ObjectId("4f30a27c4d203c27d8f4c584"), "hash" : { "call_id" : "1234" }, "something" : "AAA" } 
{ "_id" : ObjectId("4f30a2844d203c27d8f4c585"), "hash" : { "call_id" : "1234" }, "something" : "BBB" } 
{ "_id" : ObjectId("4f30a2894d203c27d8f4c586"), "hash" : { "call_id" : "1234" }, "something" : "CCC" } 
{ "_id" : ObjectId("4f30a2944d203c27d8f4c587"), "hash" : { "call_id" : "5555" }, "something" : "DDD" } 
{ "_id" : ObjectId("4f30a2994d203c27d8f4c588"), "hash" : { "call_id" : "5555" }, "something" : "EEE" } 

、このマップは

> db.disTest.mapReduce(_map,_reduce, {out: { inline : 1}}) 
{ 
    "results" : [ 
     { 
      "_id" : "1234", 
      "value" : { 
       "doc" : [ 
        { 
         "_id" : ObjectId("4f30a27c4d203c27d8f4c584"), 
         "hash" : { 
          "call_id" : "1234" 
         }, 
         "something" : "AAA" 
        } 
       ] 
      } 
     }, 
     { 
      "_id" : "5555", 
      "value" : { 
       "doc" : [ 
        { 
         "_id" : ObjectId("4f30a2944d203c27d8f4c587"), 
         "hash" : { 
          "call_id" : "5555" 
         }, 
         "something" : "DDD" 
        } 
       ] 
      } 
     } 
    ], 
    "timeMillis" : 2, 
    "counts" : { 
     "input" : 5, 
     "emit" : 5, 
     "reduce" : 2, 
     "output" : 2 
    }, 
    "ok" : 1, 
} 

を減らす実行しているいくつかのテストデータを作成します。あなたは、まず/マップを文字列化機能を削減し、それが

を役に立てば幸いこの

MyObject.collection.mapreduce(_map,_reduce,{:out => {:inline => 1},:raw=>true }) 

のようなMapReduceの呼び出しによってmongoidで同じことを行うことができます