C'est "de par la conception" du $lookup
la mise en oeuvre. Qu'est-ce en fait se passe "sous le capot" est MongoDB interne convertit les arguments dans le $lookup
au nouveau expressif formater en utilisant $expr
et $in
. Même dans les versions antérieures à ce moment expressif form a été implémenté, la mécanique interne pour un "tableau de valeurs" était vraiment la même chose.
La solution ici est de conserver une copie du tableau d'origine comme référence pour réorganiser les "joints" articles :
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 par l'ancien $lookup
utilisation :
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" }
}}
])
Les deux variantes produisent le même résultat :
{
"_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"
}
]
}
Le concept général étant d'utiliser $indexOfArray
en comparaison avec le _id
valeur du "joint" contenu pour trouver son "index" position dans le tableau source d'origine à partir de "$Classes.ID"
. Les différents $lookup
les variantes de syntaxe ont des approches différentes pour accéder à cette copie et comment vous reconstruisez fondamentalement.
Le $sort
définit bien sûr l'ordre des documents réels, soit à l'intérieur du pipeline de traitement pour la forme expressive, ou via les documents exposés de $unwind
. Où vous avez utilisé $unwind
vous feriez alors $group
retour au formulaire de document d'origine.
REMARQUE :Les exemples d'utilisation ici dépendent de MongoDB 3.4 pour le
$indexOfArray
au moins et le$$REMOVE
s'aligne sur MongoDB 3.6 comme le ferait le expressif$lookup
.Il existe d'autres approches pour réorganiser le tableau pour les versions précédentes, mais celles-ci sont présentées plus en détail dans l'ordre de garantie de la clause $in de Does MongoDB. De manière réaliste, le strict minimum que vous devriez actuellement exécuter en tant que version de production de MongoDB est la version 3.4.
Voir Politique d'assistance sous Serveur MongoDB pour plus de détails sur les versions prises en charge et les dates de fin.