MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Agregacja $ lookup nie zwraca elementów oryginalnej kolejności tablicy

Jest to "zgodnie z projektem" $lookup realizacja. Co faktycznie dzieje się „pod maską” czy MongoDB jest wewnętrzny konwertuje argumenty w $lookup do nowej ekspresji sformatuj za pomocą $expr i $in . Nawet w wersjach wcześniejszych niż to ekspresyjne zaimplementowano formularz, wewnętrzna mechanika "tablicy wartości" był naprawdę taki sam.

Rozwiązaniem tutaj jest zachowanie kopii oryginalnej tablicy jako odniesienia do zmiany kolejności "dołączonych" przedmioty:

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

Lub starszego $lookup użycie:

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

Oba warianty dają ten sam wynik:

{
        "_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"
                }
        ]
}

Ogólna koncepcja polega na użyciu $indexOfArray w porównaniu z _id wartość z „dołączonych” zawartość, aby znaleźć to jest "indeks" pozycja w oryginalnej tablicy źródłowej z "$Classes.ID" . Różne $lookup warianty składni mają różne podejścia do uzyskiwania dostępu do tej kopii i jak w zasadzie rekonstruujesz.

$sort oczywiście ustala kolejność rzeczywistych dokumentów, które są w ramach przetwarzania potoku dla formy ekspresyjnej lub poprzez ujawnione dokumenty $unwind . Gdzie użyłeś $unwind wtedy $group z powrotem do oryginalnego formularza dokumentu.

UWAGA :Przykłady użycia tutaj zależą od MongoDB 3.4 dla $indexOfArray przynajmniej i $$REMOVE jest zgodny z MongoDB 3.6, podobnie jak ekspresyjny $lookup .

Istnieją inne podejścia do zmiany kolejności tablicy we wcześniejszych wydaniach, ale są one przedstawione bardziej szczegółowo w kolejności gwarancji klauzuli $in w Czy MongoDB. Realistycznie absolutnym minimum, które powinieneś obecnie używać jako produkcyjnej wersji MongoDB, jest wydanie 3.4.

Zobacz Zasady pomocy technicznej pod Serwerem MongoDB aby uzyskać szczegółowe informacje o obsługiwanych wydaniach i datach zakończenia.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Mongoose - Zapisz tablicę ciągów

  2. Różnice MongoDB między NumberLong a prostą Integer?

  3. Dlaczego błąd mongod jest martwy, ale podsys jest zablokowany i nie ma wystarczającej ilości wolnego miejsca na pliki dziennika w systemie Linux?

  4. Wstaw Pandas Dataframe do mongodb za pomocą PyMongo

  5. Mongo:policz liczbę wystąpień słów w zestawie dokumentów