sql >> Databasteknik >  >> NoSQL >> MongoDB

Rails &Mongoid unika resultat

Du kan inte bara returnera dokumentet (eller delmängden) genom att använda distinkt. Enligt dokumentationen den returnerar bara den distinkta uppsättningen av värden baserat på den givna nyckeln. Men du kan uppnå detta genom att använda map-reduce

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

Ovanstående kod är självförklarande, på kartfunktionen grupperar jag den efter hash.call_id och returnera hela dokumentet så att det kan bearbetas med reducerad funktion.

På reduceringsfunktionen går du bara igenom den grupperade resultatuppsättningen och väljer endast ett objekt från den grupperade uppsättningen (bland de multipla dubblettnyckelvärdena - distinkt simulering).

Skapa äntligen lite testdata

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

och kör den här kartan minska

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

Du får det första dokumentet av den distinkta uppsättningen. Du kan göra samma sak i mongoid genom att först strängsätta map/reduce-funktionerna och anropa mapreduce så här

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

Hoppas det hjälper




  1. NodeJS + Mongo native – kontrollera om samlingen finns före fråga

  2. Spark HBase Connector – ett år i översyn

  3. MongoDB returnerar True om dokumentet finns

  4. Hur kan jag ta bort äldre poster från en samling i MongoDB?