MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

MongoDB:Zählen, wie viele Elemente mit einem bestimmten Wert in einem Array vorhanden sind, also in einem Dokument?

Das Aggregation Framework ist dafür ideal. Erwägen Sie, die folgende Pipeline auszuführen, um das gewünschte Ergebnis zu erhalten.

pipeline = [
    {
        "$match": {
            "name": "james",
            "books.year": 1990
        }
    },
    {
        "$project": {
            "numberOfBooks": {
                "$size": {                  
                    "$filter": {
                        "input": "$books",
                        "as": "el",
                        "cond": { "$eq": [ "$$el.year", 1990 ] }
                    }                   
                }
            }
        }
    }
];
db.collection.pipeline(pipeline);

Die obige Pipeline verwendet den neuen $filter Operator, der für MongoDB 3.2 verfügbar ist, um ein Array zu erstellen, das die angegebene Bedingung erfüllt, d. h. er filtert äußere Elemente, die die Kriterien nicht erfüllen. Der anfängliche $match Pipeline ist notwendig, um Dokumente herauszufiltern, die frühzeitig in die Aggregationspipeline gelangen, als Strategie zur Pipeline-Optimierung.

Der $size Operator, der einen einzelnen Ausdruck als Argument akzeptiert, gibt Ihnen dann die Anzahl der Elemente im resultierenden Array, somit haben Sie Ihre gewünschte Buchanzahl.

Für eine alternative Lösung, die $filter Operator, der in früheren Versionen nicht gefunden wurde, betrachten Sie die folgende Pipeline-Operation:

pipeline = [
    {
        "$match": {
            "name": "james",
            "books.year": 1990
        }
    },
    {
        "$project": {
            "numberOfBooks": {
                "$size": {                  
                    "$setDifference": [
                        {
                            "$map": {
                                "input": "$books",
                                "as": "el",
                                "in": {
                                    "$cond": [
                                        { "$eq": [ "$$el.year", 1990 ] },
                                        "$$el",
                                        false
                                    ]
                                }
                            }
                        },
                        [false]
                    ]                   
                }
            }
        }
    }
];
db.collection.pipeline(pipeline);

Der $project In der Pipeline-Phase wird das Bücher-Array so angepasst, dass Sie die Dokumente entfernen, die nicht das Jahr 1990 enthalten. Dies wird durch $setDifference und $map Betreiber.

Der $map Der Operator erstellt im Wesentlichen ein neues Array-Feld, das Werte als Ergebnis der ausgewerteten Logik in einem Unterausdruck für jedes Element eines Arrays enthält. Der $setDifference Der Operator gibt dann eine Menge mit Elementen zurück, die in der ersten Menge, aber nicht in der zweiten Menge vorkommen; d.h. führt eine relative Ergänzung des zweiten Satzes relativ zum ersten durch. In diesem Fall wird das letzte Bücher-Array zurückgegeben, das Elemente mit dem Jahr 1990 enthält, und anschließend den $size berechnet die Anzahl der Elemente im resultierenden Array und gibt Ihnen so die Anzahl der Bücher.

Für eine Lösung, die den $unwind Operator, wobei man bedenken sollte (dank dieser aufschlussreichen Antwort von @BlakesSeven in den Kommentaren):

Führen Sie als letzten Ausweg die folgende Pipeline aus:

pipeline = [
    {
        "$match": {
            "name": "james",
            "books.year": 1990
        }
    },
    { "$unwind": "$books" },
    {
        "$match": { "books.year": 1990 }
    },
    {
        "$group": {
            "_id": null
            "count": { "$sum": 1 }
        }
    }
]
db.collection.pipeline(pipeline)