sql >> Database teknologi >  >> NoSQL >> MongoDB

Aggregate $lookup returnerer ikke elementernes oprindelige array-rækkefølge

Dette er "by design" af $lookup implementering. Hvad faktisk sker "under emhætten" er MongoDB intern konverterer argumenterne i $lookup til det nye ekspressive formatere ved hjælp af $expr og $in . Selv i versioner før, da dette ekspressive form blev implementeret, den interne mekanik for en "matrix af værdier" var egentlig meget det samme.

Løsningen her er at vedligeholde en kopi af det originale array som reference til omarrangering af "joined" elementer:

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 ved den gamle $lookup brug:

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" }
  }}
])

Begge varianter producerer det samme 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"
                }
        ]
}

Det generelle koncept er at bruge $indexOfArray sammenlignet med _id værdi fra "tilsluttet" indhold for at finde det "indeks" position i det originale kildearray fra "$Classes.ID" . De forskellige $lookup syntaksvarianter har forskellige tilgange til, hvordan du får adgang til denne kopi og hvordan du grundlæggende rekonstruerer.

$sort angiver selvfølgelig rækkefølgen af ​​faktiske dokumenter, enten inde i pipeline-behandlingen for den ekspressive form eller via de synlige dokumenter fra $unwind . Hvor du brugte $unwind du ville derefter $group tilbage til den originale dokumentformular.

BEMÆRK :Brugseksemplerne her afhænger af MongoDB 3.4 for $indexOfArray i det mindste og $$REMOVE justeres med MongoDB 3.6, ligesom ekspressive $lookup .

Der er andre metoder til at genbestille arrayet til tidligere udgivelser, men disse er demonstreret mere detaljeret på Does MongoDB's $in-klausul-garantiordre. Realistisk set er det absolut minimum, du i øjeblikket bør køre som en produktionsversion af MongoDB, 3.4-udgivelsen.

Se Supportpolitik under MongoDB Server for alle detaljer om understøttede udgivelser og slutdatoer.




  1. MongoDB - Opret en sikkerhedskopi

  2. Sådan genereres unikt objekt-id i mongodb

  3. Hvordan får man adgang til en allerede eksisterende samling med Mongoose?

  4. Hvordan gemmer man et binært objekt i redis ved hjælp af node?