Dies ist "gewollt" von $lookup
Implementierung. Was eigentlich passiert "unter der Haube" ist MongoDB intern konvertiert die Argumente in $lookup
zum neuen expressiven mit $expr
formatieren und $in
. Sogar in Versionen vor diesem ausdrucksstarken Form implementiert wurde, die interne Mechanik für ein "Array von Werten" war wirklich ähnlich.
Die Lösung besteht hier darin, eine Kopie des ursprünglichen Arrays als Referenz für die Neuordnung von "joined" beizubehalten Artikel:
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"
}}
])
Oder durch das alte $lookup
Verwendung:
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" }
}}
])
Beide Varianten erzeugen dieselbe Ausgabe:
{
"_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"
}
]
}
Das allgemeine Konzept besteht darin, $indexOfArray
zu verwenden im Vergleich zur _id
Wert aus "joined" Inhalt, um seinen "Index" zu finden Position im ursprünglichen Quellarray von "$Classes.ID"
. Die unterschiedliche $lookup
Syntaxvarianten haben unterschiedliche Ansätze, wie Sie auf diese Kopie zugreifen und wie Sie im Grunde rekonstruieren.
Der $sort
legt natürlich die Reihenfolge der eigentlichen Dokumente fest, entweder innerhalb der Pipeline-Verarbeitung für die ausdrucksstarke Form oder über die exponierten Dokumente von $unwind
. Wo Sie $unwind
verwendet haben Sie würden dann $group
zurück zum ursprünglichen Dokumentformular.
HINWEIS :Die Verwendungsbeispiele hier hängen von MongoDB 3.4 für $indexOfArray
ab mindestens und das $$REMOVE
stimmt mit MongoDB 3.6 überein, ebenso wie expressive $lookup
.
Es gibt andere Ansätze zum Neuordnen des Arrays für frühere Versionen, aber diese werden ausführlicher in der Garantiereihenfolge der $in-Klausel von Does MongoDB demonstriert. Realistisch gesehen ist das absolute Minimum, das Sie derzeit als MongoDB-Produktionsversion ausführen sollten, die Version 3.4.
Siehe Supportrichtlinie unter MongoDB-Server für die vollständigen Details der unterstützten Releases und Enddaten.