Toto je "by design" $lookup
implementace. Co ve skutečnosti se děje "pod pokličkou" je MongoDB interní převede argumenty v $lookup
na nový expresivní formát pomocí $expr
a $in
. I ve verzích před tímto expresivním byla implementována forma, vnitřní mechanika pro "pole hodnot" byl opravdu hodně stejný.
Řešením je zachovat kopii původního pole jako referenci pro změnu pořadí "připojeno" položky:
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"
}}
])
Nebo podle starší verze $lookup
použití:
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" }
}}
])
Obě varianty produkují stejný výstup:
{
"_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"
}
]
}
Obecným konceptem je použití $indexOfArray
ve srovnání s _id
hodnotu z "připojeno" obsah najít jeho "index" pozici v původním zdrojovém poli z "$Classes.ID"
. Různé $lookup
varianty syntaxe mají různé přístupy k přístupu k této kopii a jak v podstatě rekonstruujete.
$sort
samozřejmě nastavuje pořadí skutečných dokumentů, buď jsou v procesu zpracování pro expresivní formu nebo prostřednictvím vystavených dokumentů $unwind
. Kde jste použili $unwind
pak byste $group
zpět na původní formulář dokumentu.
POZNÁMKA :Zde uvedené příklady použití závisí na MongoDB 3.4 pro
$indexOfArray
alespoň a$$REMOVE
odpovídá MongoDB 3.6 stejně jako expresivní$lookup
.Existují i jiné přístupy k přeskupení pole pro předchozí verze, ale ty jsou podrobněji demonstrovány v objednávce klauzule $in společnosti Does MongoDB. Realisticky naprosté minimum, které byste v současnosti měli provozovat jako produkční MongoDB verze, je vydání 3.4.
Viz Zásady podpory pod Server MongoDB pro úplné podrobnosti o podporovaných vydáních a datech ukončení.