Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is it possible to write regular expression in $cond in MongoDB

I need to use $cond to combine differenet column, and one $cond I need to write is as following:

create_widget: {
        $sum:{
          $cond:[{$and: [ {$eq: ['$Method', 'POST']},
                {Url:{$regex: /.*\/widgets$/}} ]}, 1, 0]
        }
    }

and this code is not right, it seems, regular expression can not be put here.Is there any other way to do this? I want to match Url and regular expression and put the code under $cond.

A sample data looks as

{"BrandId":"a","SessionId":"a1","Method":"POST","Url":"/sample/widgets"}
{"BrandId":"a","SessionId":"a2","Method":"POST","Url":"/sample/blog"}
{"BrandId":"b","SessionId":"b1","Method":"PUT","Url":"/sample/widgets"}

The whole code I wrote is as following:

db.tmpAll.aggregate([
    {$group: {
        _id: {BrandId:'$BrandId'},
        SessionId: {$addToSet: '$SessionId'},
        create_widget: {
            $sum:{
              $cond:[{$and: [ {$eq: ['$Method', 'POST']},
                    {} ]}, 1, 0]
            }
        }
    }},
    {$group: {
        _id: '$_id.BrandId',
        distinct_session: {$sum: {$size: '$SessionId'}},
        create_widget: {$sum: '$create_widget'}
    }}
]);

The expected result of sample code is

{ "_id" : "a", "distinct_session" : 2, "create_widget" : 1 }
{ "_id" : "b", "distinct_session" : 1, "create_widget" : 0 }
like image 679
erkpwejropi Avatar asked May 13 '15 16:05

erkpwejropi


People also ask

Can I use regex in MongoDB query?

MongoDB provides the functionality to search a pattern in a string during a query by writing a regular expression. A regular expression is a generalized way to match patterns with sequences of characters. MongoDB uses Perl compatible regular expressions(PCRE) version 8.42 along with UTF-8 support.

Which operator is used in MongoDB to find a pattern or word in any string?

MongoDB regex operator is used to search for strings in collection. Now we will take an example to understand about regex operator: We will take an example table with two fields as “Employee_id” and “Employee_name”. Now we will write the code to find “Employee_name” with initials as “ab”.

What is $EXPR in MongoDB?

$expr can build query expressions that compare fields from the same document in a $match stage. If the $match stage is part of a $lookup stage, $expr can compare fields using let variables. See Perform Multiple Joins and a Correlated Subquery with $lookup for an example.


1 Answers

For MongoDB 4.2 and newer production releases, and in the 4.1.11 and newer development versions, use $regexMatch which is a syntactic sugar on top of $regexFind which can be used for regex matching and capturing.

db.tmpAll.aggregate([
    { "$group": {
        "_id": {
            "BrandId": "$BrandId",
            "SessionId": "$SessionId"
        },
        "widget_count": {
            "$sum": { 
                "$cond": [
                    {
                        "$and": [ 
                            { "$eq": ["$Method", "POST"] },
                            { "$regexMatch": { 
                                "input": "$Url",
                                "regex": /widget/
                            } } 
                        ]
                    }, 1, 0
                ]                     
            }
        },
        "session_count": { "$sum": 1 }
    } },
    { "$group": {
        "_id": "$_id.BrandId",
        "create_widget": { "$sum": "$widget_count" },
        "distinct_session": { "$sum": "$session_count" }
    } }
]);

There is an open JIRA issue for this SERVER-8892 - Use $regex as the expression in a $cond. However, as a workaround, For older MongoDB versions which do not have the above features, use the following workaround in your aggregation pipeline.

It uses the $substr operator in the $project operator stage to extract the part of the URL and acts as a workaround for the regex. :

db.tmpAll.aggregate([
    { "$group": {
        "_id": {
            "BrandId": "$BrandId",
            "SessionId": "$SessionId"
        },
        "widget_count": {
            "$sum": { 
                "$cond": [
                   {
                       "$and": [ 
                           { "$eq": ["$Method", "POST"] },
                           { "$eq": [ { "$substr": [ "$Url", 8, -1 ] }, "widget"] } 
                       ]
                   }, 1, 0
                ]                     
           }
        },
        "session_count": { "$sum": 1 }
    } },
    { "$group": {
        "_id": "$_id.BrandId",
        "create_widget": { "$sum": "$widget_count" },
        "distinct_session": { "$sum": "$session_count" }
    } }
]);

Output

/* 1 */
{
    "result" : [ 
        {
            "_id" : "a",
            "create_widget" : 1,
            "distinct_session" : 2
        }, 
        {
            "_id" : "b",
            "create_widget" : 0,
            "distinct_session" : 1
        }
    ],
    "ok" : 1
}
like image 119
chridam Avatar answered Nov 03 '22 02:11

chridam