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

MongoDB:Aggregation mit $cond mit $regex

AKTUALISIERUNG: Beginnend mit MongoDB v4.1.11 scheint es endlich eine nette Lösung für Ihr Problem zu geben, die dokumentiert ist hier .

Ursprüngliche Antwort:

Wie ich oben in den Kommentaren geschrieben habe, $regex funktioniert nicht innerhalb von $cond ab sofort. Es gibt ein offenes JIRA-Ticket dafür ist es aber, ähm, naja, offen...

In Ihrem speziellen Fall würde ich eher vorschlagen, dass Sie dieses Thema auf der Clientseite lösen, es sei denn, Sie haben es mit verrückten Mengen an Eingabedaten zu tun, von denen Sie immer nur kleine Teilmengen zurückgeben. Nach Ihrer Abfrage zu urteilen, scheint es, als würden Sie immer alle Dokumente abrufen, die gerade in zwei Ergebnisgruppen ("Ja" und "Nein") zusammengefasst wurden.

Wenn Sie dieses Thema nicht auf der Client-Seite lösen wollen oder können, dann ist hier etwas, das $facet (MongoDB>=v3.4 erforderlich) - es ist weder besonders schnell noch übermäßig hübsch, aber es könnte Ihnen beim Einstieg helfen.

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

Wie immer beim Aggregations-Framework kann es hilfreich sein, einzelne Phasen vom Ende der Pipeline zu entfernen und die Teilabfrage auszuführen, um zu verstehen, was jede einzelne Phase tut.