sql >> Base de Datos >  >> NoSQL >> MongoDB

Mongodb distinto en un campo de matriz con consulta de expresiones regulares?

El marco de agregación y no el .distinct() comando:

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

Probablemente sea mejor usar un "anclaje" al comienzo de la expresión regular si quiere decir desde el "inicio" de la cadena. Y también haciendo esto $match antes de procesar $unwind también:

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

Eso asegura que no esté procesando $unwind en todos los documentos de la colección y solo en aquellos que posiblemente contengan su valor de "etiquetas coincidentes" antes de "filtrar" para asegurarse.

La forma realmente "compleja" de mitigar un poco las matrices grandes con posibles coincidencias requiere un poco más de trabajo y MongoDB 2.6 o superior:

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

Entonces $map es un buen procesador de arreglos "en línea" pero solo puede llegar hasta cierto punto. El $setDifference operador niega el false coincide, pero en última instancia aún necesita procesar $unwind para hacer el $group restante escenario para distintos valores en general.

La ventaja aquí es que las matrices ahora se "reducen" solo al elemento "etiquetas" que coincide. Simplemente no use esto cuando desee un "recuento" de las ocurrencias cuando hay valores "múltiples distintos" en el mismo documento. Pero nuevamente, hay otras formas de manejar eso.