Detta är "by design" av $lookup
genomförande. Vad egentligen händer "under huven" är MongoDB internt konverterar argumenten i $lookup
till den nya expressiva formatera med $expr
och $in
. Även i versioner före när detta expressivt form implementerades, den interna mekaniken för en "array of values" var verkligen likadant.
Lösningen här är att behålla en kopia av den ursprungliga arrayen som referens för att ordna om "joined" föremål:
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"
}}
])
Eller genom den äldre $lookup
användning:
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" }
}}
])
Båda varianterna ger samma utdata:
{
"_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"
}
]
}
Det allmänna konceptet är att använda $indexOfArray
i jämförelse med _id
värde från "joined" innehåll för att hitta det är "index" position i den ursprungliga källarrayen från "$Classes.ID"
. De olika $lookup
syntaxvarianter har olika tillvägagångssätt för hur du kommer åt denna kopia och hur du i princip rekonstruerar.
$sort
anger naturligtvis ordningen för faktiska dokument, antingen inne i pipeline-bearbetningen för den uttrycksfulla formen, eller via de exponerade dokumenten av $unwind
. Där du använde $unwind
du skulle då $group
tillbaka till det ursprungliga dokumentformuläret.
OBS :Användningsexemplen här beror på MongoDB 3.4 för
$indexOfArray
åtminstone och$$REMOVE
anpassar sig till MongoDB 3.6 liksom expressiva$lookup
.Det finns andra tillvägagångssätt för att beställa om arrayen för tidigare utgåvor, men dessa visas mer i detalj på Does MongoDB:s garantiordning för $in-klausulen. Realistiskt sett är det absoluta minimum du för närvarande bör köra som en produktionsversion av MongoDB version 3.4.
Se Supportpolicy under MongoDB Server för fullständig information om utgåvor som stöds och slutdatum.