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

Cómo usar $in o $nin en la agregación de mongo $group $cond

La comparación en $setIsSubset es una opción más corta que $or condición que está usando, aunque sigue siendo básicamente válida para hacer lo que está haciendo.

La única pega con $setIsSubset es que cada argumento es una matriz, por lo que debe convertir el elemento único en una matriz de un solo elemento. Esto es bastante fácil usando $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
                ]
            }
        }
    }}    
])

O, si lo prefiere, haga coincidir la matriz de argumentos con el valor singular, con $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
                ]
            }
        }
    }}
])

Donde el $map es más bien atravesar los argumentos para que coincidan con el singular en lugar de forzar el singular en una matriz.

Y, por supuesto, dado que cualquiera de las formas proporciona esencialmente true/false al $cond entonces puede invertir la lógica con $not donde sea necesario:

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

Realmente depende de cómo lo mires, pero simplemente como argumentos proporcionados, entonces realmente no ganas nada sobre el formulario original con $or . Puede parecer un poco más limpio y "más fácil de escribir", pero normalmente no estaría "escribiendo" dicha lógica directamente en la canalización de agregación, sino generando esa parte de la estructura basada en una lista simple en primer lugar:

es decir

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

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

Y luego simplemente usando el contenido de la matriz reasignada en la definición de canalización:

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

Lo mires como lo mires, recuerda que son solo estructuras de datos y tienes procesos básicos para manipular. Tanto dentro del procesamiento de la tubería como también en la construcción de la misma.