Esto es "por diseño" de $lookup
implementación. ¿Qué realmente sucede "bajo el capó" es MongoDB interno convierte los argumentos en el $lookup
al nuevo expresivo formatear usando $expr
y $in
. Incluso en versiones anteriores a cuando esta expresiva se implementó el formulario, la mecánica interna para una "matriz de valores" era realmente lo mismo.
La solución aquí es mantener una copia de la matriz original como referencia para reordenar los "unidos" artículos:
collection.aggregate([
{"$match": {"_id": ObjectId("5c781752176c512f180048e3") }},
{"$lookup": {
"from": "collection2",
"let": { "classIds": "$Classes.ID" },
"pipeline": [
{ "$match": {
"$expr": { "$in": [ "$_id", "$$classIds" ] }
}},
{ "$addFields": {
"sort": {
"$indexOfArray": [ "$$classIds", "$_id" ]
}
}},
{ "$sort": { "sort": 1 } },
{ "$addFields": { "sort": "$$REMOVE" }}
],
"as": "results"
}}
])
O por el heredado $lookup
uso:
collection.aggregate([
{"$match": {"_id": ObjectId("5c781752176c512f180048e3") }},
{"$lookup": {
"from": "collection2",
"localField": "Classes.ID",
"foreignField": "_id",
"as": "results"
}},
{ "$unwind": "$results" },
{ "$addFields": {
"sort": {
"$indexOfArray": [ "$Classes.ID", "$results._id" ]
}
}},
{ "$sort": { "_id": 1, "sort": 1 } },
{ "$group": {
"_id": "$_id",
"Name": { "$first": "$Name" },
"Classes": { "$first": "$Classes" },
"results": { "$push": "$results" }
}}
])
Ambas variantes producen el mismo resultado:
{
"_id" : ObjectId("5c781752176c512f180048e3"),
"Name" : "Pedro",
"Classes" : [
{
"ID" : ObjectId("5c7af2b2f6f6e47c9060d7ce")
},
{
"ID" : ObjectId("5c7af2bcf6f6e47c9060d7cf")
},
{
"ID" : ObjectId("5c7af2aaf6f6e47c9060d7cd")
}
],
"results" : [
{
"_id" : ObjectId("5c7af2b2f6f6e47c9060d7ce"),
"variable1" : "B"
},
{
"_id" : ObjectId("5c7af2bcf6f6e47c9060d7cf"),
"variable1" : "C"
},
{
"_id" : ObjectId("5c7af2aaf6f6e47c9060d7cd"),
"variable1" : "A"
}
]
}
El concepto general es usar $indexOfArray
en comparación con el _id
valor de "joined" content para encontrar su "index" posición en la matriz fuente original de "$Classes.ID"
. Los diferentes $lookup
las variantes de sintaxis tienen diferentes enfoques sobre cómo acceder a esta copia y cómo reconstruyes básicamente.
El $sort
por supuesto, establece el orden de los documentos reales, ya sea estando dentro del proceso de canalización por la forma expresiva, o a través de los documentos expuestos de $unwind
. Donde usaste $unwind
entonces $group
volver al formulario del documento original.
NOTA :Los ejemplos de uso aquí dependen de MongoDB 3.4 para el $indexOfArray
al menos y el $$REMOVE
se alinea con MongoDB 3.6 como lo haría el expresivo $lookup
.
Hay otros enfoques para reordenar la matriz para versiones anteriores, pero estos se muestran con más detalle en el orden de garantía de la cláusula $in de Does MongoDB. Siendo realistas, lo mínimo que debería ejecutar actualmente como una versión de producción de MongoDB es la versión 3.4.
Ver Política de soporte en Servidor MongoDB para obtener los detalles completos de las versiones admitidas y las fechas de finalización.