sql >> Database >  >> NoSQL >> MongoDB

MongoDB elemmatch meerdere elementen in array

U kunt niet meerdere elementen van een array retourneren die aan uw criteria voldoen in enige vorm van een standaard .find() vraag. Om meer dan één element te matchen, moet je de .aggregate() . gebruiken methode in plaats daarvan.

Het belangrijkste verschil hier is dat de "query" precies doet waarvoor hij bedoeld is en overeenkomt met "documenten" die aan uw voorwaarden voldoen. U kunt proberen de positionele $ . te gebruiken operator binnen een projectie-argument, maar de regels daar zijn dat het alleen overeenkomt met het "eerste" array-element dat overeenkomt met de queryvoorwaarden.

Ga als volgt te werk om op meerdere array-elementen te "filteren":

db.sample.aggregate([
    // Filter possible documents
    { "$match": { "filtermetric.class": "s2" } },

    // Unwind the array to denormalize
    { "$unwind": "$filtermetric" },

    // Match specific array elements
    { "$match": { "filtermetric.class": "s2" } },

    // Group back to array form
    { "$group": {
        "_id": "$_id",
        "filtermetric": { "$push": "$filtermetric" }
    }}
])

In moderne versies van MongoDB die versie 2.6 of hoger zijn, kunt u dit doen met $redact :

db.sample.aggregate([
    // Filter possible documents
    { "$match": { "filtermetric.class": "s2" } },

    // Redact the entries that do not match
    { "$redact": {
        "$cond": [
            { "$eq": [ { "$ifNull": [ "$class", "s2" ] }, "s2" ] },
            "$$DESCEND",
            "$$PRUNE"
        ]
    }}
])

Dat is waarschijnlijk uw meest efficiënte optie, maar het is recursief, dus houd eerst rekening met uw documentstructuur, aangezien hetzelfde benoemde veld niet kan bestaan ​​met een andere voorwaarde op welk niveau dan ook.

Mogelijk veiliger maar alleen nuttig wanneer de resultaten in de array "echt uniek" zijn, is deze techniek met $map en $setDifference :

db.sample.aggregate([
    { "$project": {
        "filtermetric": { "$setDifference": [
            { "$map": [
                "input": "$filtermetric",
                "as": "el",
                "in": {"$cond": [
                    { "$eq": [ "$$el.class", "s2" ] },
                    "$$el",
                    false
                ]}
            ]},
            [false]
        ]}
    }}
])

Merk ook op dat in zowel de $group en $project operationele pijplijnfasen die u nodig hebt om alle velden te specificeren die u van plan bent te retourneren in uw resultaatdocumenten van die fase.

De laatste opmerking is dat $elemMatch is niet vereist wanneer u alleen de waarde van een enkele sleutel binnen een array opvraagt. "Dot-notatie" heeft de voorkeur en wordt aanbevolen wanneer u slechts toegang hebt tot een enkele sleutel van de array. $elemMatch zou alleen nodig moeten zijn wanneer "meerdere" sleutels in het document binnen de array "element" moeten overeenkomen met een vraagvoorwaarde.




  1. Globale initialisatie mislukt:BadValue Ongeldige of geen gebruikerslandinstelling ingesteld. Zorg ervoor dat de omgevingsvariabelen LANG en/of LC_* correct zijn ingesteld

  2. Ingesloten document zonder Array?

  3. Is er een goede manier om popleden van de Redis Sorted Set te steunen?

  4. Misbruik cURL om te communiceren met Redis