sql >> Databáze >  >> NoSQL >> MongoDB

Aggregate $lookup nevrací prvky původní pořadí pole

Toto je "by design" $lookup implementace. Co ve skutečnosti se děje "pod pokličkou" je MongoDB interní převede argumenty v $lookup na nový expresivní formát pomocí $expr a $in . I ve verzích před tímto expresivním byla implementována forma, vnitřní mechanika pro "pole hodnot" byl opravdu hodně stejný.

Řešením je zachovat kopii původního pole jako referenci pro změnu pořadí "připojeno" položky:

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

Nebo podle starší verze $lookup použití:

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

Obě varianty produkují stejný výstup:

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

Obecným konceptem je použití $indexOfArray ve srovnání s _id hodnotu z "připojeno" obsah najít jeho "index" pozici v původním zdrojovém poli z "$Classes.ID" . Různé $lookup varianty syntaxe mají různé přístupy k přístupu k této kopii a jak v podstatě rekonstruujete.

$sort samozřejmě nastavuje pořadí skutečných dokumentů, buď jsou v procesu zpracování pro expresivní formu nebo prostřednictvím vystavených dokumentů $unwind . Kde jste použili $unwind pak byste $group zpět na původní formulář dokumentu.

POZNÁMKA :Zde uvedené příklady použití závisí na MongoDB 3.4 pro $indexOfArray alespoň a $$REMOVE odpovídá MongoDB 3.6 stejně jako expresivní $lookup .

Existují i ​​jiné přístupy k přeskupení pole pro předchozí verze, ale ty jsou podrobněji demonstrovány v objednávce klauzule $in společnosti Does MongoDB. Realisticky naprosté minimum, které byste v současnosti měli provozovat jako produkční MongoDB verze, je vydání 3.4.

Viz Zásady podpory pod Server MongoDB pro úplné podrobnosti o podporovaných vydáních a datech ukončení.




  1. Nahrazení vloženého dokumentu v poli v MongoDB

  2. Automatizace kontroly konfigurace databáze

  3. Funkce MongoDB v ClusterControl 1.4

  4. Jak vytvořím pracovníka resque automaticky při spuštění?