MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

MongoDB:aggregazione utilizzando $cond con $regex

AGGIORNAMENTO: A partire da MongoDB v4.1.11, sembra finalmente esserci una buona soluzione per il tuo problema che è documentata qui .

Risposta originale:

Come ho scritto nei commenti sopra, $regex non funziona all'interno di $cond al momento. È disponibile un biglietto JIRA per quello ma è, ehm, beh, aperto...

Nel tuo caso specifico, tendo a suggerirti di risolvere quell'argomento sul lato client a meno che tu non abbia a che fare con quantità pazze di dati di input di cui restituirai sempre solo piccoli sottoinsiemi. A giudicare dalla tua query, sembrerebbe che tu recuperi sempre tutti i documenti appena inseriti in due gruppi di risultati ("Sì" e "No").

Se non vuoi o non puoi risolvere questo argomento sul lato client, ecco qualcosa che usa $facet (MongoDB>=v3.4 richiesta) - non è né particolarmente veloce né eccessivamente carino, ma potrebbe aiutarti a iniziare.

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

Come sempre con il framework di aggregazione, può essere utile rimuovere le singole fasi dalla fine della pipeline ed eseguire la query parziale per comprendere cosa fa ogni singola fase.