MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

classificar array na consulta e projetar todos os campos


Como você está agrupando no documento _id você pode simplesmente colocar os campos que deseja manter dentro do agrupamento _id . Em seguida, você pode reformar usando $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"
    }}
]);

O outro "truque" é usar um nome temporário para o array no estágio de agrupamento. Isso acontece quando você $project e alterar o nome, você obtém os campos na ordem especificada na instrução de projeção. Caso contrário, o campo "array_to_sort" não seria o último campo do pedido, pois é copiado do estágio anterior.

Essa é uma otimização pretendida em $project , mas se você quiser o pedido, poderá fazê-lo como acima.

Para estruturas completamente desconhecidas existe a maneira mapReduce de fazer as coisas:
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 } }
)

Claro que tem um formato de saída específico para mapReduce e, portanto, não é exatamente o documento que você tinha, mas todos os campos estão contidos em "valores":
{
    "results" : [
            {
                    "_id" : 0,
                    "value" : {
                            "_id" : 0,
                            "some_field" : "a",
                            "array_to_sort" : [
                                    {
                                            "a" : 1,
                                            "b" : 0
                                    },
                                    {
                                            "a" : 3,
                                            "b" : 3
                                    },
                                    {
                                            "a" : 3,
                                            "b" : 4
                                    }
                            ]
                    }
            }
    ],
}

Versões futuras (no momento da escrita) permitem que você use um $$ROOT variável agregada para representar o documento:
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"}
    }}
]);

Portanto, não faz sentido usar o estágio final de "projeto", pois você não conhece os outros campos do documento. Mas todos eles estarão contidos (incluindo o array original e o pedido ) dentro do _id campo do documento de resultado.