MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

trier le tableau dans la requête et projeter tous les champs

Puisque vous regroupez sur le document _id vous pouvez simplement placer les champs que vous souhaitez conserver dans le groupement _id . Ensuite, vous pouvez reformer en utilisant $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"
    }}
]);

L'autre "astuce" consiste à utiliser un nom temporaire pour le tableau lors de l'étape de regroupement. C'est le cas lorsque vous $project et modifiez le nom, vous obtenez les champs dans l'ordre spécifié dans l'instruction de projection. Si vous ne l'avez pas fait, le champ "array_to_sort" ne serait pas le dernier champ de l'ordre, car il est copié de l'étape précédente.

C'est une optimisation prévue dans $project , mais si vous voulez la commande, vous pouvez le faire comme ci-dessus.

Pour les structures totalement inconnues, il existe la méthode mapReduce :

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

Bien sûr, cela a un format de sortie spécifique à mapReduce et donc pas exactement le document que vous aviez, mais tous les champs sont contenus sous "values" :

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

Les futures versions (au moment de l'écriture) vous permettent d'utiliser un $$ROOT variable en agrégat pour représenter le document :

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"}
    }}
]);

Il est donc inutile d'utiliser l'étape finale du "projet" car vous ne connaissez pas réellement les autres champs du document. Mais ils seront tous contenus (y compris le tableau et l'ordre d'origine) dans le _id champ du document résultat.