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

MongoDB:Agregace pomocí $cond s $regex

AKTUALIZACE: Počínaje MongoDB v4.1.11 se konečně zdá, že existuje pěkné řešení vašeho problému, které je zdokumentováno zde .

Původní odpověď:

Jak jsem psal v komentářích výše, $regex nefunguje uvnitř $cond od teď. Je otevřená vstupenka JIRA za to, ale je to, ehm, no, otevřené...

Ve vašem konkrétním případě bych měl tendenci navrhovat, abyste toto téma řešili na straně klienta, pokud nemáte co do činění se šíleným množstvím vstupních dat, ze kterých budete vždy vracet jen malé podmnožiny. Soudě podle vašeho dotazu by to vypadalo, jako byste vždy načetli všechny dokumenty právě rozdělené do dvou skupin výsledků ("Ano" a "Ne").

Pokud toto téma nechcete nebo nemůžete vyřešit na straně klienta, pak zde je něco, co používá $facet (Požaduje se MongoDB>=v3.4) – není ani zvlášť rychlý, ani přehnaně pěkný, ale může vám pomoci začít.

db.captions.aggregate([{
    $facet: { // create two stages that will be processed using the full input data set from the "captions" collection
        "CallToActionYes": [{ // the first stage will...
            $match: { // only contain documents...
                "plainText": /leave\sa\scomment/i // that are allowed by the $regex filter (which could be extended with multiple $or expressions or changed to $in/$nin which accept regular expressions, too)
            }
        }, {
            $addFields: { // for all matching documents...
                "CallToAction": "Yes" // we create a new field called "CallsToAction" which will be set to "Yes"
            }
        }],
        "CallToActionNo": [{ // similar as above except we're doing the inverse filter using $not
            $match: {
                "plainText": { $not: /leave\sa\scomment/i }
            }
        }, {
            $addFields: {
                "CallToAction": "No" // and, of course, we set the field to "No"
            }
        }]
    }
}, {
    $project: { // we got two arrays of result documents out of the previous stage
        "allDocuments" : { $setUnion: [ "$CallToActionYes", "$CallToActionNo" ] } // so let's merge them into a single one called "allDocuments"
    }
}, {
    $unwind: "$allDocuments" // flatten the "allDocuments" result array
}, {
    $replaceRoot: { // restore the original document structure by moving everything inside "allDocuments" up to the top
        newRoot: "$allDocuments"
    }
}, {
    $project: { // include only the two relevant fields in the output (and the _id)
        "videoId": 1,
        "CallToAction": 1
    }
}])

Jako vždy u agregačního rámce může pomoci odstranit jednotlivé fáze z konce kanálu a spustit dílčí dotaz, abyste pochopili, co každá jednotlivá fáze dělá.




  1. Mongoose vyberte pole pro návrat z findOneAndUpdate

  2. Jak sečíst pole z různých dokumentů v agregaci MongoDB?

  3. Stemming nefunguje správně pro textový index MongoDB

  4. MongoDB $set neaktualizuje záznam