sql >> Database >  >> NoSQL >> MongoDB

MongoDB:Tellen hoeveel items met een bepaalde waarde er in een array zijn, dat is in een document?

Het aggregatiekader is daar ideaal voor. Overweeg de volgende pijplijn uit te voeren om het gewenste resultaat te krijgen.

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

De bovenstaande pijplijn gebruikt de nieuwe $filter operator beschikbaar voor MongoDB 3.2 om een ​​array te produceren die aan de gespecificeerde voorwaarde voldoet, d.w.z. het filtert externe elementen die niet aan de criteria voldoen. De eerste $match pijplijn is nodig om documenten te filteren die vroeg in de aggregatiepijplijn komen als een strategie voor pijplijnoptimalisatie.

De $size operator die een enkele uitdrukking als argument accepteert, geeft je het aantal elementen in de resulterende array, dus je hebt het gewenste aantal boeken.

Voor een alternatieve oplossing die geen gebruik maakt van de $filter operator niet gevonden in eerdere versies, overweeg de volgende pijplijnbewerking:

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);

De $project pijplijnfase omvat het aanpassen van de boekenarray zodat u de documenten verwijdert die niet het jaar 1990 hebben. Dit wordt mogelijk gemaakt door de $setDifference en $map exploitanten.

De $map operator creëert in wezen een nieuw arrayveld dat waarden bevat als resultaat van de geëvalueerde logica in een subexpressie voor elk element van een array. De $setDifference operator retourneert vervolgens een set met elementen die in de eerste set voorkomen, maar niet in de tweede set; d.w.z. voert een relatieve aanvulling uit van de tweede set ten opzichte van de eerste. In dit geval wordt de laatste boekenreeks geretourneerd die elementen heeft met het jaar 1990 en vervolgens de $size berekent het aantal elementen in de resulterende array, waardoor u het aantal boeken krijgt.

Voor een oplossing die gebruikmaakt van de $unwind operator, rekening houdend met het volgende (dankzij deze inzichtelijke reactie van @BlakesSeven in de opmerkingen):

en als laatste redmiddel, voer de volgende pijplijn uit:

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


  1. MongoDB-verzoeken volgen vanuit een consoletoepassing

  2. Mongoose save() werkt de waarde niet bij in een array in het databasedocument

  3. 10 vragen om te stellen (en te beantwoorden) bij het hosten van MongoDB op AWS

  4. MongoDB Document opnieuw vormgeven