Dit is "door het ontwerp" van de $lookup
implementatie. Wat eigenlijk gebeurt "onder de motorkap" is MongoDB intern converteert de argumenten in de $lookup
naar de nieuwe expressieve formaat met behulp van $expr
en $in
. Zelfs in eerdere versies dan wanneer dit expressief vorm is geïmplementeerd, de interne mechanica voor een "array van waarden" was eigenlijk hetzelfde.
De oplossing hier is om een kopie van de originele array te behouden als referentie voor het opnieuw ordenen van de "joined" artikelen:
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"
}}
])
Of door de legacy $lookup
gebruik:
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 produceren dezelfde output:
{
"_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"
}
]
}
Het algemene concept is om $indexOfArray
. te gebruiken in vergelijking met de _id
waarde van de "joined" inhoud om zijn "index" te vinden positie in de originele bronarray van "$Classes.ID"
. De verschillende $lookup
syntaxisvarianten hebben verschillende manieren om toegang te krijgen tot deze kopie en hoe je in principe reconstrueert.
De $sort
bepaalt natuurlijk de volgorde van daadwerkelijke documenten, ofwel binnen de pijplijnverwerking voor de expressieve vorm, of via de blootgestelde documenten van $unwind
. Waar je $unwind
hebt gebruikt je zou dan $group
terug naar het originele documentformulier.
OPMERKING :De gebruiksvoorbeelden hier zijn afhankelijk van MongoDB 3.4 voor de $indexOfArray
tenminste en de $$REMOVE
komt overeen met MongoDB 3.6 zoals de expressieve $lookup
.
Er zijn andere benaderingen om de array opnieuw te ordenen voor eerdere releases, maar deze worden in meer detail gedemonstreerd op de garantievolgorde $in-clausule van Does MongoDB. Realistisch gezien is het absolute minimum dat u momenteel zou moeten gebruiken als een productie MongoDB-versie de 3.4-release.
Zie Ondersteuningsbeleid onder MongoDB-server voor de volledige details van ondersteunde releases en einddatums.