MongoDB agregación se presenta de manera exponencial complicado por minuto!

Estoy tan lejos como para $unwind una matriz anidada y, a continuación, realizar una $lookup por el _id de cada objeto de la unwinded matriz anidada. Mi último intento para revertir la corrección con $group. Sin embargo, soy incapaz de reconstruir el original incrustado matriz, con su original nombre de la propiedad, junto con el resto de la original inmediata de las propiedades de cada documento.

Aquí está mi intento hasta ahora:

db.users.aggregate([
    {
        $unwind: "$profile",
        $unwind: {
            path: "$profile.universities",
            preserveNullAndEmptyArrays: true
        }
    },
    {
        $lookup: {
            from: "universities",
            localField: "profile.universities._id",
            foreignField: "_id",
            as: "profile.universities"
        }
    },
    {
        $group: {
            _id: "$_id",
            emails: { "$first": "$emails" },
            profile: { "$first": "$profile" },
            universities: { "$push": "$profile.universities" }
        }
    }
]).pretty()

Lo que me pasa es algo como esto:

{
    "_id" : "A_USER_ID",
    "emails" : [
        {
            "address" : "AN_EMAIL_ADDRESS",
            "verified" : false
        }
    ],
    "profile" : {
        "name" : "NAME",
        "company" : "A COMPANY",
        "title" : "A TITLE",
        "phone" : "123-123-1234",
        "disabled" : false,
        "universities" : [
            {
                "_id" : "ID_1",
                "name" : "UNIVERSITY_NAME_1",
                "code" : "CODE_1",
                "styles" : {AN_OBJECT}
            }
        ]
    },
    "universities" : [
        [
            {
                "_id" : "ID_1",
                "name" : "UNIVERSITY_NAME_1",
                "code" : "CODE_1",
                "styles" : {AN_OBJECT}
            }
        ],
        [
            {
                "_id" : "ID_2",
                "name" : "UNIVERSITY_NAME_2",
                "code" : "CODE_2",
                "styles" : {AN_OBJECT}
            }
        ]
    ]
}

Hay 2 problemas con este resultado:

  1. El resultado universities es un array de arrays de un objeto de cada uno, ya que la $lookup devuelve un único elemento de la matriz para el original $profile.universities matriz anidada. Debería ser sólo un array de objetos.
  2. El resultado universities debe tomar su lugar original anidados bajo profiles. Soy consciente de por qué el original profile.universities es la manera que es, porque estoy utilizando el $first operador. Mi intención detrás de esto es para conservar todas las propiedades originales de profile, en el cruce con la retención de la original anidada universities matriz.

En última instancia, lo que necesito es algo como esto:

{
    "_id" : "A_USER_ID",
    "emails" : [
        {
            "address" : "AN_EMAIL_ADDRESS",
            "verified" : false
        }
    ],
    "profile" : {
        "name" : "NAME",
        "company" : "A COMPANY",
        "title" : "A TITLE",
        "phone" : "123-123-1234",
        "disabled" : false,
        "universities" : [
            {
                "_id" : "ID_1",
                "name" : "UNIVERSITY_NAME_1",
                "code" : "CODE_1",
                "styles" : {AN_OBJECT}
            },
            {
                "_id" : "ID_2",
                "name" : "UNIVERSITY_NAME_2",
                "code" : "CODE_2",
                "styles" : {AN_OBJECT}
            }
        ]
    }
}

Hay otro operador que puedo usar en lugar de $group para lograr esto? O soy yo el entendimiento de la finalidad de $group incorrectamente?

Edición: Este es el post original, para el contexto:
Si Mongo $la búsqueda de una combinación externa izquierda, entonces ¿cómo es que excluye a los no-coincidencia de los documentos?

InformationsquelleAutor Sun Lee | 2016-09-14

1 Comentario

  1. 19

    Porque el $de búsqueda operador produce una matriz campo, debe $relajarse el nuevo campo antes de que el $group tubería para obtener el resultado deseado:

    db.users.aggregate([
        { "$unwind": "$profile" },
        { "$unwind": {
            "path": "$profile.universities",
             "preserveNullAndEmptyArrays": true
        } }, 
        { "$lookup": {
            "from": "universities",
            "localField": "profile.universities._id",
            "foreignField": "_id",
            "as": "universities"
        } },    
        { "$unwind": "$universities" },
        { "$group": {
            "_id": "$_id",
            "emails": { "$first": "$emails" },
            "profile": { "$first": "$profile" },
            "universities": { "$push": "$universities" }
        } },
        { "$project": {
            "emails": 1,  
            "profile.name" : 1,
            "profile.company": 1,
            "profile.title" : 1,
            "profile.phone" : 1,
            "profile.disabled": 1,          
            "profile.universities": "$universities"
        } }
    ]).pretty()
    • Gracias @chridam, la segunda $unwind y $project hizo el truco! He tenido que modificar dos partes: 1. cambio de la segunda a relajarse, hasta "$unwind": {"path": "$profile.universities", "preserveNullAndEmptyArrays": true}, y 2. cambiar el $group «universidades» para "universities": { "$push": "$profile.universities" } y yo era capaz de conseguir mis resultados.

Dejar respuesta

Please enter your comment!
Please enter your name here