1

ich einen Datensatz haben, die etwa wie folgt aussieht:Probleme beim Erstellen Abfrage in MongoDB mit Unterabfrage

{ 
 
    "id": "02741544", 
 
    "items": [{ 
 
    "item": "A" 
 
    }] 
 
}, { 
 
    "id": "02472691", 
 
    "items": [{ 
 
    "item": "A" 
 
    }, { 
 
    "item": "B" 
 
    }, { 
 
    "item": "C" 
 
    }] 
 
}, { 
 

 
    "id": "01316523", 
 
    "items": [{ 
 
    "item": "A" 
 
    }, { 
 
    "item": "B" 
 
    }] 
 
}, { 
 
    "id": "01316526", 
 
    "items": [{ 
 
    "item": "A" 
 
    }, { 
 
    "item": "B" 
 
    }] 
 
}, { 
 
    "id": "01316529", 
 
    "items": [{ 
 
    "item": "A" 
 
    }, { 
 
    "item": "D" 
 
    }] 
 
},

Ich versuche, eine Abfrage zu fertigen, die mir eine Ausgabe geben wird, die aussieht wie dies:

{ 
 
    "item": "A", 
 
    "ids": [{ 
 
    "id": "02741544" 
 

 
    }, { 
 
    "id": "02472691" 
 

 
    }, { 
 
    "id": "01316523" 
 

 
    }, { 
 
    "id": "01316526" 
 

 
    }, { 
 
    "id": "01316529" 
 

 
    }] 
 
}, { 
 
    "item": "B", 
 
    "ids": [{ 
 
    "id": "02472691" 
 

 
    }, { 
 
    "id": "01316523" 
 

 
    }, { 
 
    "id": "01316526" 
 

 
    }] 
 
}, { 
 
    "item": "C", 
 
    "ids": [{ 
 
    "id": "02472691" 
 

 
    }] 
 
}, { 
 
    "item": "D", 
 
    "ids": [{ 
 
    "id": "02472691" 
 

 
    }] 
 
},

Grundsätzlich versuche ich, die eindeutigen Elemente aus dem Elementarray im Objekt zu erhalten und dann ein Array von IDs für jedes Objekt zurückgeben, das dieses Element in seinem Elementarray hat.

Antwort

2

bessere Nutzung der aggregation framework, in dem eine Operation ausgeführt werden müssen, die (in der angegebenen Reihenfolge) der folgenden Pipeline-Stufen besteht:

  1. $unwind - Dieser erste Schritt wird die items Array dh sie abflachen erstellt eine Kopie jedes Dokuments pro Arrayeintrag. Dies ist notwendig, um die Dokumente weiter unten in der Pipeline als "denormalisierte" Dokumente zu verarbeiten, die Sie als Gruppen aggregieren können.
  2. $group - Dies wird Gruppe die abgeflachten Dokumente durch die item Subdokument Schlüssel und erstellen Sie die ids Liste durch den Akkumulator Operator $push verwenden.

- UPDATE -

Wie @AminJ in den Kommentaren darauf hingewiesen, wenn items doppelte Element Werte haben kann, und Sie wollen keine doppelten IDs im Ergebnis können Sie verwenden $addToSet statt $push

Das folgende Beispiel zeigt dies:

Beispielausgabe

{ 
    "_id" : "A", 
    "ids" : [ 
     { "id" : "02741544" }, 
     { "id" : "02472691" }, 
     { "id" : "01316523" }, 
     { "id" : "01316526" }, 
     { "id" : "01316529" } 
    ] 
} 

/* 2 */ 
{ 
    "_id" : "B", 
    "ids" : [ 
     { "id" : "02472691" }, 
     { "id" : "01316523" }, 
     { "id" : "01316526" } 
    ] 
} 

/* 3 */ 
{ 
    "_id" : "C", 
    "ids" : [ 
     { "id" : "02472691" } 
    ] 
} 

/* 4 */ 
{ 
    "_id" : "D", 
    "ids" : [ 
     { "id" : "01316529" } 
    ] 
} 

Das Ergebnis aus einer aggregate() Funktion ist ein Cursor auf die von der letzten Stufe der Aggregation Pipeline-Betrieb erzeugt Dokumenten. Wenn Sie also die Ergebnisse in einem Array haben möchten, können Sie die toArray() Methode des Cursors verwenden, die ein Array zurückgibt, das alle Dokumente enthält.

Zum Beispiel:

var pipeline = [  
     { "$unwind": "$items" }, 
     { 
      "$group": { 
       "_id": "$items.item", 
       "ids": { 
        "$push": { "id": "$id" } /* or use 
        "$addToSet": { "id": "$id" } if you don't want duplicate ids */      
       } 
      } 
     } 
    ], 
    results = db.collection.aggregate(pipeline).toArray(); 

printjson(results); 
+1

Es könnte erwähnenswert sein, wenn 'Elemente' 'doppelte item' Werte haben können und Sie nicht wollen, Duplikate IDs im Ergebnis können Sie 'addToSet' anstelle von' push' verwenden. –

+0

@AminJ Guter Punkt – chridam

+0

Dies gibt die gewünschte Ausgabe so weit wie der Inhalt geht, aber es gibt die Ergebnisse nicht als ein Array von Objekten zurück. Wie wird das erreicht? – TWLATL

0

Hier ist eine Lösung, die eine Aggregation-Pipeline:

db.col.aggregate([ 
     { 
      $unwind: "$items" 
     }, 
     { 
      $project: { 
       id: 1, 
       item: "$items.item" 
      } 
     }, 
     { 
      $group: { 
       _id: "$item", 
       ids: { 
        $push: "$id" 
       } 
      } 
     } 
    ])