Isso é "por design" do
$lookup
implementação. O que na verdade acontece "sob o capô" é MongoDB interno converte os argumentos no $lookup
para o novo expressivo formato usando $expr
e $in
. Mesmo em versões anteriores a quando este expressivo formulário foi implementado, a mecânica interna para uma "matriz de valores" realmente era muito o mesmo. A solução aqui é manter uma cópia do array original como referência para reordenar o "joined" Unid:
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"
}}
])
Ou pelo legado
$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 as variantes produzem a mesma saída:
{
"_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"
}
]
}
O conceito geral é usar
$indexOfArray
em comparação com o _id
valor do "unido" conteúdo para encontrar seu "índice" posição na matriz de origem original de "$Classes.ID"
. Os diferentes $lookup
as variantes de sintaxe têm abordagens diferentes de como você acessa esta cópia e como você basicamente reconstrói. O
$sort
é claro que define a ordem dos documentos reais, seja dentro do processamento do pipeline para a forma expressiva, ou através dos documentos expostos de $unwind
. Onde você usou $unwind
você então $group
de volta ao formulário do documento original.
OBSERVAÇÃO :Os exemplos de uso aqui dependem do MongoDB 3.4 para o$indexOfArray
pelo menos e o$$REMOVE
se alinha com o MongoDB 3.6 como faria o expressivo$lookup
.
Existem outras abordagens para reordenar o array para versões anteriores, mas elas são demonstradas com mais detalhes na ordem de garantia da cláusula $in do MongoDB. Realisticamente, o mínimo que você deve estar executando atualmente como uma versão de produção do MongoDB é a versão 3.4.
Consulte a Política de suporte em Servidor MongoDB para obter os detalhes completos das versões com suporte e datas de término.