MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Rails &Mongoid einzigartige Ergebnisse

Sie können das Dokument (oder die Teilmenge) nicht einfach mit dem Distinct zurückgeben. Gemäß der Dokumentation Es gibt nur das eindeutige Array von Werten basierend auf dem angegebenen Schlüssel zurück. Aber Sie können dies erreichen, indem Sie map-reduce

verwenden
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;
}

Der obige Code ist selbsterklärend, in der Kartenfunktion gruppiere ich ihn nach dem Schlüssel hash.call_id und Zurückgeben des gesamten Dokuments, damit es von der Reduce-Funktion verarbeitet werden kann.

Gehen Sie bei der Reduzierungsfunktion einfach durch die gruppierte Ergebnismenge und wählen Sie nur ein Element aus der gruppierten Menge aus (unter den mehreren doppelten Schlüsselwerten - unterschiedliche Simulation).

Erstellen Sie abschließend einige Testdaten

> 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" }

und das Ausführen dieser Karte reduziert

> 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,
}

Sie erhalten das erste Dokument des eindeutigen Satzes. Sie können dasselbe in Mongoid tun, indem Sie zuerst die map/reduce-Funktionen stringifizieren und mapreduce so aufrufen

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

Hoffe es hilft