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

Verwendung von $in oder $nin in der Mongo-Aggregation $group $cond

Der Vergleich auf $setIsSubset ist eine kürzere Option als $or Bedingung, die Sie verwenden, obwohl es im Grunde immer noch gültig ist, das zu tun, was Sie tun.

Einziger Haken bei $setIsSubset ist, dass jedes Argument ein Array ist, also müssen Sie das einzelne Element in ein einzelnes Element-Array konvertieren. Dies ist ganz einfach mit $map :

db.collectionName.aggregate([
    { "$group": {
        "_id": "$createdAt",
        "count": { "$sum": 1 },
        "count_failure": {
            "$sum": {
                "$cond": [
                    { "$setIsSubset": [
                        { "$map": {
                            "input": ["A"],
                            "as": "el",
                            "in": "$id"
                        }},
                        [ 0,100,101,102,103,104,105 ],
                    ]},
                    1,
                    0
                ]
            }
        }
    }}    
])

Oder wenn Sie es vorziehen, dann gleichen Sie das Array von Argumenten stattdessen mit dem Singularwert ab, mit $anyElementTrue :

db.collectionName.aggregate([
    { "$group": {
        "_id": "$createdAt",
        "count": { "$sum": 1 },
        "count_failure": {
            "$sum": {
                "$cond": [
                    { "$anyElementTrue": { "$map": {
                        "input": [ 0,100,101,102,103,104,105 ],
                        "as": "el",
                        "in": { "$eq": [ "$$el", "$id" ] }
                    }}},
                    1,
                    0
                ]
            }
        }
    }}
])

Wo die $map ist vielmehr, die Argumente zu durchlaufen, um sie mit dem Singular abzugleichen, anstatt den Singular in ein Array zu zwingen.

Und natürlich liefern beide Formen im Wesentlichen true/false zu $cond dann können Sie die Logik einfach mit $not wo erforderlich:

db.collectionName.aggregate([
    { "$group": {
        "_id": "$createdAt",
        "count": { "$sum": 1 },
        "count_failure": {
            "$sum": {
                "$cond": [
                    { "$not": [{ "$anyElementTrue": { "$map": {
                        "input": [ 0,100,101,102,103,104,105 ],
                        "as": "el",
                        "in": { "$eq": [ "$$el", "$id" ] }
                    }}}]},
                    1,
                    0
                ]
            }
        }
    }}
])

Es hängt wirklich davon ab, wie Sie es betrachten, aber einfach als gelieferte Argumente gewinnen Sie nicht wirklich etwas über die ursprüngliche Form mit $oder . Es mag etwas sauberer und "einfacher zu tippen" aussehen, aber normalerweise würde ich eine solche Logik nicht direkt in die Aggregationspipeline "eingeben", sondern diesen Teil der Struktur zunächst auf der Grundlage einer einfachen Liste generieren:

d.h.

var failList = [ 0,100,101,102,103,104,105 ];

var orCondition = failList.map(function(el) { 
    return { "$eq": [ "$id", el ] }
})

Und dann einfach den neu zugeordneten Array-Inhalt in der Pipeline-Definition verwenden:

    { "$group": {
        "_id": "$createdAt",
        "count": { "$sum": 1 },
        "count_failure": {
            "$sum": {
                "$cond": [
                    { "$or": orCondition },
                    1,
                    0
                ]
            }
        }
    }}
])

Wie auch immer Sie es betrachten, denken Sie daran, dass es alles nur Datenstrukturen sind und Sie grundlegende Prozesse zur Manipulation haben. Sowohl innerhalb der Pipelineverarbeitung als auch im Pipelinebau selbst.