在聚合时 MongoDB 中是否有其他的东西到 $cond

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27479347/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:14:12  来源:igfitidea点击:

Is there an elseif thing in MongoDB to $cond while aggregating

mongodbmongodb-queryaggregation-framework

提问by humblerookie

So I need a custom field calculated in MongoDB as follows

所以我需要一个在MongoDB中计算的自定义字段如下

if( field1 =="A")  ->customfield=10
else if(field1 =="B"  )->customfield=20
else (field1 =="C" ) ->customfield=15

I'm using aggregation along with the $project statement. But the $cond operator doesn't allow elseif (subbranching the else) and merely allows two static branches if and else. Using a nested elseif causes

我将聚合与 $project 语句一起使用。但是 $cond 操作符不允许 elseif (子分支 else)并且只允许两个静态分支 if 和 else。使用嵌套的 elseif 导致

"exception: field inclusion is not allowed inside of $expressions"

"exception: field inclusion is not allowed inside of $expressions"

Heres my query(which gives me the error)

这是我的查询(这给了我错误)

db.items.aggregate([ { $project :
{
     name: 1,
     customfield:
     {
         $cond: { if: { $eq: [ "$field1", "4" ] }, then: 30,
                else: {
                    if: 
                    { $eq: ["$field1","8"]}, 
                    then: 25, else: 10}}
               }
           }},{ $sort: { customfield: 1 }},{$limit:12}]);

Is there a method or workaround to this. My apologies if this is a repeated question but I wasn't able to find a similar one.

有没有方法或解决方法。如果这是一个重复的问题,我很抱歉,但我找不到类似的问题。

回答by Neil Lunn

With modern releases ( since MongoDB 3.4 ) you would use $switch, which is basically the counterpart to switchor casekeywords in other language implementations:

对于现代版本(自 MongoDB 3.4 起),您将使用$switch,它基本上是其他语言实现中的switchorcase关键字的对应物:

db.items.aggregate([
  { "$project": {
    "name": 1,
    "customfield": {
      "$switch": {
        "branches": [
          { "case": { "$eq": [ "$field1", "4" ] }, "then": 30 },
          { "case": { "$eq": [ "$field1", "8" ] }, "then": 25 }
        ],
        "default": 10
      }
    }
  }},
  { "$sort": { customfield: 1 }},
  { "$limit":12 }
])

This avoids nestingthe if..then..elseconditions as can be done using $condand shown below. But the below still shows as an example that this could always be done, even before the new operator of even the explicit if..then..elsekeywords since the original array notation always maintained that syntax.

这避免嵌套if..then..else作为是可以做到用条件$cond和如下所示。但下面仍然作为一个例子表明,即使在显式if..then..else关键字的 new 运算符之前,也可以始终这样做,因为原始数组表示法始终保持该语法。

Noting also that an arrayof conditions here is typically also a lot easier to construct programatically than creating a nesteddata structure for the statement as was needed with $cond.

还注意到,一个阵列的条件下在这里通常也比创建一个更容易编程构造嵌套的语句的数据结构与需要$cond



The if..then..elsekeywords to the $condoperator are only a recent addition as of recent versions of MongoDB at the time of writing ( MongoDB 2.6 was the introduction of the keywords. The actual operator was available with release of the aggregation framework in MongoDB 2.2 ). The intention was for clarity but in this case it seems to has caused some confusion.

运算符的if..then..else关键字$cond只是在撰写本文时最近版本的 MongoDB 中最近添加的(MongoDB 2.6 是关键字的引入。实际的运算符在 MongoDB 2.2 中的聚合框架发布时可用)。目的是为了清楚起见,但在这种情况下,它似乎引起了一些混乱。

As an if..then.elseoperator $condis indeed a ternaryoperator, just as would be implemented in many programming languages. This means as an "inline" conditional, rather than creating "blocks" of logic to the conditions, anything that does not meet the first condition belongs under else.

由于if..then.else运算符$cond确实是三元运算符,就像在许多编程语言中实现的一样。这意味着作为“内联”条件,而不是为条件创建逻辑“块”,任何不满足第一个条件的都属于else.

Therefore you "nest" the statements rather than follow blocks:

因此,您“嵌套”语句而不是遵循块:

db.items.aggregate([
  { "$project": {
    "name": 1,
    "customfield": {
      "$cond": { 
        "if": { "$eq": [ "$field1", "4" ] }, 
        "then": 30,
        "else": {
          "$cond": {
            "if": { "$eq": ["$field1","8"]}, 
            "then": 25, 
            "else": 10
          }
        }
      }
    }
  }},
  { "$sort": { customfield: 1 }},
  { "$limit":12 }
]);

Or even with the original arraynotation, which some might prefer if building the statement programatically:

或者甚至使用原始数组表示法,如果以编程方式构建语句,有些人可能更喜欢:

db.items.aggregate([
  { "$project": {
    "name": 1,
    "customfield": {
      "$cond": [
         { "$eq": [ "$field1", "4" ] }, 
         30,
         { "$cond": [
           { "$eq": ["$field1","8"] },
           25, 
           10
         ]}
      ]
    }
  }},
  { "$sort": { customfield: 1 }},
  { "$limit":12 }
]);

Ternary means three conditions, no more no less. So all if..then..elselogic must be nested.

三元意味着三个条件,不多不少。所以所有的if..then..else逻辑都必须嵌套。

回答by nort

MongoDB 3.4 has a new thing called $switchfor this exact thing!

MongoDB 3.4 有一个新东西叫做$switch这个确切的东西!

$switch: {
   branches: [
      { case: <expression>, then: <expression> },
      { case: <expression>, then: <expression> },
      ...
   ],
   default: <expression>
}

https://docs.mongodb.com/manual/reference/operator/aggregation/switch/

https://docs.mongodb.com/manual/reference/operator/aggregation/switch/

回答by KARNAV PARGI

if you are using only object then

如果您只使用对象,那么

{
    $cond: {
        $and: [
            { if: { $eq: ["$$field1", 'A'] }, then: '10', else: 15 },
            { if: { $eq: ["$$field1", 'B'] }, then: '20', else: 15 },
            { if: { $eq: ["$$field1", 'C'] }, then: '10', else: 15 },
        ]
    }
}

And if you are Using Array find Data

如果您使用数组查找数据

{
    $map: {
        input: "$fields", as: "field1", in: {
            $cond: {
                $and: [
                    { if: { $eq: ["$$field1", 'A'] }, then: '10', else: 15 },
                    { if: { $eq: ["$$field1", 'B'] }, then: '20', else: 15 },
                    { if: { $eq: ["$$field1", 'C'] }, then: '10', else: 15 },
                ]
            }
        }
    }
}