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

Array in Abfrage sortieren und alle Felder projizieren

Da gruppieren Sie nach dem Dokument _id Sie können die Felder, die Sie behalten möchten, einfach innerhalb der Gruppierung _id platzieren . Dann können Sie mit $project

db.c.aggregate([
    { "$unwind": "$array_to_sort"},
    { "$sort": {"array_to_sort.b":1, "array_to_sort:a": 1}},
    { "$group": { 
        "_id": {
            "_id": "$_id",
            "unknown_field": "$unknown_field"
        },
        "Oarray_to_sort": { "$push":"$array_to_sort"}
    }},
    { "$project": {
        "_id": "$_id._id",
        "unknown_field": "$_id.unknown_field",
        "array_to_sort": "$Oarray_to_sort"
    }}
]);

Der andere "Trick" darin besteht darin, einen temporären Namen für das Array in der Gruppierungsphase zu verwenden. Dies ist der Fall, wenn Sie $project und den Namen ändern, erhalten Sie die Felder in der Reihenfolge, die in der Projektionsanweisung angegeben ist. Andernfalls wäre das Feld "array_to_sort" nicht das letzte Feld in der Reihenfolge, da es aus der vorherigen Stufe kopiert wird.

Das ist eine beabsichtigte Optimierung in $project , aber wenn Sie die Bestellung möchten, können Sie es wie oben tun.

Für völlig unbekannte Strukturen gibt es die mapReduce-Methode:

db.c.mapReduce(
    function () {
        this["array_to_sort"].sort(function(a,b) {
            return a.a - b.a || a.b - b.b;
        });

        emit( this._id, this );
    },
    function(){},
    { "out": { "inline": 1 } }
)

Das hat natürlich ein MapReduce-spezifisches Ausgabeformat und daher nicht genau das Dokument, das Sie hatten, aber alle Felder sind unter "values" enthalten:

{
    "results" : [
            {
                    "_id" : 0,
                    "value" : {
                            "_id" : 0,
                            "some_field" : "a",
                            "array_to_sort" : [
                                    {
                                            "a" : 1,
                                            "b" : 0
                                    },
                                    {
                                            "a" : 3,
                                            "b" : 3
                                    },
                                    {
                                            "a" : 3,
                                            "b" : 4
                                    }
                            ]
                    }
            }
    ],
}

Zukünftige Versionen (zum Zeitpunkt des Schreibens) ermöglichen Ihnen die Verwendung eines $$ROOT Variable insgesamt, um das Dokument darzustellen:

db.c.aggregate([
    { "$project": {
        "_id": "$$ROOT",
        "array_to_sort": "$array_to_sort"
    }},
    { "$unwind": "$array_to_sort"},
    { "$sort": {"array_to_sort.b":1, "array_to_sort:a": 1}},
    { "$group": { 
        "_id": "$_id",
        "array_to_sort": { "$push":"$array_to_sort"}
    }}
]);

Es macht also keinen Sinn, die letzte "Projekt" -Phase zu verwenden, da Sie die anderen Felder im Dokument nicht wirklich kennen. Aber sie werden alle (einschließlich des ursprünglichen Arrays und der Reihenfolge ) in der _id enthalten sein Feld des Ergebnisdokuments.