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

$ buscar en ObjectId en una matriz

Actualización de 2017

$lookup ahora puede usar directamente una matriz como campo local. $unwind ya no es necesario.

Respuesta antigua

El $lookup la etapa de canalización de agregación no funcionará directamente con una matriz. La intención principal del diseño es una "unión izquierda" como un tipo de unión de "uno a muchos" (o realmente una "búsqueda") en los posibles datos relacionados. Pero se pretende que el valor sea singular y no una matriz.

Por lo tanto, primero debe "desnormalizar" el contenido antes de realizar $lookup operación para que esto funcione. Y eso significa usar $unwind :

db.orders.aggregate([
    // Unwind the source
    { "$unwind": "$products" },
    // Do the lookup matching
    { "$lookup": {
       "from": "products",
       "localField": "products",
       "foreignField": "_id",
       "as": "productObjects"
    }},
    // Unwind the result arrays ( likely one or none )
    { "$unwind": "$productObjects" },
    // Group back to arrays
    { "$group": {
        "_id": "$_id",
        "products": { "$push": "$products" },
        "productObjects": { "$push": "$productObjects" }
    }}
])

Después de $lookup coincide con cada miembro de la matriz, el resultado es una matriz en sí misma, por lo que $unwind de nuevo y $group para $push nuevas matrices para el resultado final.

Tenga en cuenta que cualquier coincidencia de "unión izquierda" que no se encuentre creará una matriz vacía para los "productObjects" en el producto dado y, por lo tanto, negará el documento para el elemento "producto" cuando el segundo $unwind se llama.

Aunque una aplicación directa a una matriz estaría bien, así es como funciona actualmente al hacer coincidir un valor singular con muchos posibles.

Como $lookup es básicamente muy nuevo, actualmente funciona como sería familiar para aquellos que están familiarizados con la mangosta como una "versión para hombres pobres" de .populate() método ofrecido allí. La diferencia es que $lookup ofrece el procesamiento del "lado del servidor" de la "unión" en lugar del cliente y que parte de la "madurez" en $lookup actualmente falta lo que .populate() ofertas (como interpolar la búsqueda directamente en una matriz).

En realidad, este es un problema asignado para la mejora SERVER-22881, por lo que, con un poco de suerte, llegará a la próxima versión o poco después.

Como principio de diseño, su estructura actual no es ni buena ni mala, sino que está sujeta a gastos generales al crear cualquier "unión". Como tal, se aplica el principio básico de MongoDB en el inicio, donde si "puede" vivir con los datos "pre-unidos" en la colección, entonces es mejor hacerlo.

La otra cosa que se puede decir de $lookup como principio general, es que la intención de la "unión" aquí es que funcione al revés de lo que se muestra aquí. Entonces, en lugar de mantener los "identificadores relacionados" de los otros documentos dentro del documento "principal", el principio general que funciona mejor es que los "documentos relacionados" contengan una referencia al "principal".

Entonces $lookup se puede decir que "funciona mejor" con un "diseño de relación" que es el reverso de algo como mangosta .populate() realiza sus uniones del lado del cliente. Al identificar el "uno" dentro de cada "muchos", simplemente extrae los elementos relacionados sin necesidad de $unwind la matriz primero.