MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Mongodb distinct sur un champ tableau avec requête regex ?

Le framework d'agrégation et non le .distinct() commande :

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"
    }}
])

Vous feriez probablement mieux d'utiliser une "ancre" au début de la regex, c'est-à-dire à partir du "début" de la chaîne. Et aussi en faisant cela $match avant de traiter $unwind aussi :

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"
    }}
])

Cela garantit que vous ne traitez pas $unwind sur chaque document de la collection et uniquement ceux qui contiennent éventuellement votre valeur "balises correspondantes" avant de "filtrer" pour vous en assurer.

La manière vraiment "complexe" d'atténuer quelque peu les grands tableaux avec des correspondances possibles demande un peu plus de travail, et MongoDB 2.6 ou supérieur :

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" }}
])

Donc $map est un bon processeur "en ligne" de tableaux, mais il ne peut pas aller plus loin. Le $setDifference l'opérateur nie le false correspond, mais en fin de compte, vous devez toujours traiter $unwind faire le reste du $group étape pour des valeurs distinctes dans l'ensemble.

L'avantage ici est que les tableaux sont désormais "réduits" au seul élément "tags" qui correspond. Ne l'utilisez pas lorsque vous voulez un "compte" des occurrences lorsqu'il y a "plusieurs valeurs distinctes" dans le même document. Mais encore une fois, il existe d'autres façons de gérer cela.