MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Mongodb distinto su un campo array con query regex?

Il framework di aggregazione e non il .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"
    }}
])

Probabilmente è meglio usare un "ancoraggio" all'inizio dell'espressione regolare se intendi dall '"inizio" della stringa. E anche facendo questo $match prima di elaborare $unwind anche:

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

Ciò assicura che tu non stia elaborando $unwind su ogni documento della raccolta e solo su quelli che eventualmente contengono il tuo valore "tag abbinati" prima di "filtrare" per essere sicuro.

Il modo davvero "complesso" per mitigare in qualche modo grandi array con possibili corrispondenze richiede un po' più di lavoro e MongoDB 2.6 o versioni successive:

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

Quindi $map è un bel processore di array "in-line" ma può arrivare solo fino a questo punto. Il $setDifference l'operatore nega il false corrispondenze, ma alla fine devi ancora elaborare $unwind per fare il restante $group palcoscenico per valori distinti nel complesso.

Il vantaggio qui è che gli array ora sono "ridotti" solo all'elemento "tag" che corrisponde. Basta non usarlo quando vuoi un "conteggio" delle occorrenze quando ci sono valori "più distinti" nello stesso documento. Ma ancora una volta, ci sono altri modi per gestirlo.