MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Mongodb eindeutig in einem Array-Feld mit Regex-Abfrage?

Das Aggregations-Framework und nicht die .distinct() Befehl:

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

Es ist wahrscheinlich besser, einen "Anker" am Anfang der Regex zu verwenden, wenn Sie vom "Anfang" der Zeichenfolge meinen. Und auch dabei $match bevor Sie $unwind verarbeiten auch:

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

Dadurch wird sichergestellt, dass Sie nicht $unwind verarbeiten auf jedes Dokument in der Sammlung und nur auf diejenigen, die möglicherweise Ihren Wert "übereinstimmende Tags" enthalten, bevor Sie "filtern", um sicherzugehen.

Der wirklich "komplexe" Weg, große Arrays mit möglichen Übereinstimmungen etwas abzumildern, erfordert etwas mehr Arbeit und MongoDB 2.6 oder höher:

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

Also $map ist ein netter "Inline"-Prozessor von Arrays, aber er kann nur so weit gehen. Der $setDifference -Operator negiert false Übereinstimmungen, aber letztendlich müssen Sie immer noch $unwind verarbeiten um die restlichen $group zu erledigen Bühne für eindeutige Werte insgesamt.

Der Vorteil dabei ist, dass Arrays jetzt nur noch auf das passende "Tags"-Element "reduziert" werden. Verwenden Sie dies nur nicht, wenn Sie eine "Zählung" der Vorkommen wünschen, wenn es "mehrere unterschiedliche" Werte im selben Dokument gibt. Aber auch hier gibt es andere Möglichkeiten, damit umzugehen.