sql >> Databáze >  >> NoSQL >> MongoDB

Jak používat $in nebo $nin v mongo agregaci $group $cond

Srovnání na $setIsSubset je kratší možnost než $or stavu, který používáte, i když v zásadě stále platí to, co děláte.

Jediný úlovek s $setIsSubset je, že každý argument je pole, takže musíte převést jeden prvek na pole jednoho prvku. To je dostatečně snadné pomocí $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
                ]
            }
        }
    }}    
])

Nebo chcete-li, porovnejte pole argumentů se singulární hodnotou místo toho pomocí $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
                ]
            }
        }
    }}
])

Kde je $map je spíše procházení argumentů tak, aby odpovídaly jednotnému, než aby singulár vnucoval do pole.

A samozřejmě, protože oba formuláře v podstatě poskytují true/false do $cond pak stačí obrátit logiku pomocí $not v případě potřeby:

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

Opravdu záleží na tom, jak se na to díváte, ale jednoduše jako dodané argumenty pak ve skutečnosti nezískáte nic oproti původnímu tvaru s $or . Může to vypadat trochu čistěji a „snáze se to píše“, ale obvykle bych takovou logiku „nezadával“ přímo do agregačního kanálu, ale spíše bych generoval tuto část struktury na základě prostého seznamu:

tj.

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

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

A pak stačí použít přemapovaný obsah pole v definici kanálu:

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

Ať už se na to díváte z jakéhokoli úhlu, pamatujte, že jsou to všechno jen datové struktury a máte základní procesy pro manipulaci. A to jak při zpracování potrubí, tak i při samotné výstavbě potrubí.



  1. A operátor mongoosastic (filtr)

  2. Použijte bluebird pro mongoose, got .bind není funkce

  3. Rychlost MongoDB {aggregation $match} vs {find}

  4. mongod shell se nespustí, data/db neexistuje