sql >> Databasteknik >  >> NoSQL >> MongoDB

Mongodb distinkt på ett arrayfält med regex-fråga?

aggregationsramverket och inte .distinct() kommando:

db.event.aggregate([
    // De-normalize the array content to separate documents
    { "$unwind": "$tags" },

    // Filter the de-normalized content to remove non-matches
    { "$match": { "tags": /foo/ } },

    // Group the "like" terms as the "key"
    { "$group": {
        "_id": "$tags"
    }}
])

Du är förmodligen bättre av att använda ett "ankare" till början av regexet, om du menar från "starten" av strängen. Och gör även detta $match innan du bearbetar $unwind likaså:

db.event.aggregate([
    // Match the possible documents. Always the best approach
    { "$match": { "tags": /^foo/ } },

    // De-normalize the array content to separate documents
    { "$unwind": "$tags" },

    // Now "filter" the content to actual matches
    { "$match": { "tags": /^foo/ } },

    // Group the "like" terms as the "key"
    { "$group": {
        "_id": "$tags"
    }}
])

Det säkerställer att du inte bearbetar $unwind på varje dokument i samlingen och bara de som eventuellt innehåller ditt "matchade taggar"-värde innan du "filtrerar" för att vara säker.

Det riktigt "komplexa" sättet att något minska stora arrayer med möjliga matchningar kräver lite mer arbete, och MongoDB 2.6 eller senare:

db.event.aggregate([
    { "$match": { "tags": /^foo/ } },
    { "$project": {
        "tags": { "$setDifference": [
            { "$map": {
                "input": "$tags",
                "as": "el",
                "in": { "$cond": [
                    { "$eq": [ 
                        { "$substr": [ "$$el", 0, 3 ] },
                        "foo"
                    ]},
                    "$$el",
                    false
                ]}
            }},
            [false]
        ]}
    }},
    { "$unwind": "$tags" },
    { "$group": { "_id": "$tags" }}
])

$map är en trevlig "in-line" processor av arrayer men det kan bara gå så långt. $setDifference operatorn negerar false matchningar, men i slutändan behöver du fortfarande bearbeta $unwind för att göra den återstående $group steg för distinkta värden totalt sett.

Fördelen här är att arrayer nu "reduceras" till endast "taggar"-elementet som matchar. Använd bara inte detta när du vill ha ett "antal" av förekomsterna när det finns "flera distinkta" värden i samma dokument. Men återigen, det finns andra sätt att hantera det på.




  1. Returnera endast specifika fält för en fråga i Spring Data MongoDB

  2. MongoDB synkroniserar utvecklings- och produktionsdatabaser

  3. De tre A:en för MongoDB Security – Autentisering, auktorisering och revision

  4. MongoDB startar inte efter serverkrasch