sql >> Base de Datos >  >> NoSQL >> MongoDB

ordenar matriz en consulta y proyectar todos los campos

Dado que está agrupando en el documento _id simplemente puede colocar los campos que desea mantener dentro de la agrupación _id . Luego puede volver a formar 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"
    }}
]);

El otro "truco" es usar un nombre temporal para la matriz en la etapa de agrupación. Esto es así cuando $project y cambia el nombre, obtiene los campos en el orden especificado en la instrucción de proyección. Si no lo hiciera, entonces el campo "array_to_sort" no sería el último campo en el pedido, ya que se copia de la etapa anterior.

Esa es una optimización prevista en $project , pero si desea el pedido, puede hacerlo como se indicó anteriormente.

Para estructuras completamente desconocidas existe la forma mapReduce de hacer las cosas:

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

Por supuesto, tiene un formato de salida que es específico de mapReduce y, por lo tanto, no es exactamente el documento que tenía, pero todos los campos están contenidos en "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
                                    }
                            ]
                    }
            }
    ],
}

Las versiones futuras (a partir de la escritura) le permiten usar un $$ROOT variable en conjunto para representar el 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"}
    }}
]);

Por lo tanto, no tiene sentido usar la etapa final del "proyecto" ya que en realidad no conoce los otros campos del documento. Pero todos estarán contenidos (incluido el arreglo original y el orden) dentro del _id campo del documento de resultados.