【问题标题】:"dotted field names are only allowed at the top level" when doing $cond执行 $cond 时,“点字段名称只允许在顶层”
【发布时间】:2015-10-29 11:22:59
【问题描述】:

我正在使用 aggregationprojectcond。像这样的...

假定文件为:

{outter:{
    inner1:"blah",
    innerOther:"somethingelse"
}}

聚合:

db.collection.aggregate([{
   $project : {
       "outter.inner1":1,
       "outter.inner2":{
          $cond : if:{"outter.innerOther":{$exists:true}},
                  then:{"blah":"blah"},
                  else:{"blah":"blah"}
       }
   }
}])

当我运行它时,我收到一个错误:exception: dotted field names are only allowed at the top level on the if 条件语句(我尝试将 if 替换为 if:true 并且聚合有效)。

这是一个错误吗?是否有一种解决方法,无需执行整个其他项目来简单地获得没有点的字段?

编辑

所以我找到了一种解决方法,但仍然想看看这是否是预期的行为。解决方法是通过$let 在投影中使用变量。此外,$exists 似乎不是有效的expression,因此还必须进行以下更改。

db.collection.aggregate([{
   $project : {
       "outter.inner1":1,
       "outter.inner2":{
          $let :{
              vars:{innerOther:{$ifNull:["$outter.innerOther", "absent"]}},
          }
          $cond : if:{$eq:["$$innerOther","absent"]},
                  then:{"blah":"blah"},
                  else:{"blah":"blah"}
       }
   }
}])

【问题讨论】:

  • “外部”是一个数组吗?请问你能出示你的文件吗?
  • 外部是子文档。

标签: mongodb mongodb-query aggregation-framework projection


【解决方案1】:

首先,您不能使用$exists,因为它仅在使用$match 运算符或.find() 方法的表达式中有效。话虽如此,您可以在if 条件中使用"dot notation",但您需要在第一个查询中缺少prefix it with the $ sign。此外,您不能将文字对象键/值对作为值或表达式返回,因为它不是有效的 aggregation expressions,您需要改用 "dot notation"

现在您提到的一种方法是使用$let 操作和$projection。当然,$ifNull 条件运算符返回字段的当前值(如果存在)或替换表达式。

db.collection.aggregate([
    { $project: { 
        "outter.inner1": 1,
        "outter.inner2.blah": { 
            $let: { 
                vars: { 
                    "outterinner2": { 
                        $ifNull: [ "$outter.innerOther", "absent" ]
                    }
                }, 
                in: { 
                    $cond: [ 
                        { $eq: [ "$$outterinner2", "absent" ] }, 
                        "blah", 
                        "blah"
                    ]
                }
            }
        }
    }}
])

另一种方法是使用两个$projection 阶段。

db.collection.aggregate([
    { $project: { 
        "inner1": "$outter.inner1", 
        "inner2": {
            $ifNull: [ "$outter.innerOther", "absent" ] 
        }
    }}, 
    { $project: { 
        "outter.inner1": "$inner1", 
        "outter.inner2.blah": { 
            $cond: [ 
                { $eq: ["$inner2", "absent"] }, 
                "blah", 
                "blah" 
            ]
        }
    }}
])

这两个查询都会产生如下结果:

{
        "_id" : ObjectId("5632713c8b13e9fb9cc474f2"),
        "outter" : {
                "inner1" : "blah",
                "inner2" : {
                        "blah" : "blah"
                }
        }
}

编辑:

$cond 运算符中允许使用“点表示法”。例如以下查询使用“点表示法”。

db.collection.aggregate([
    { $project: { 
        "outter.inner1": 1, 
        "outter.inner2.blah": { 
            $cond: [ 
                { $eq: [ "$outter.innerOther", "somethingelse" ] }, 
                "anotherThing", 
                "nothing" 
            ] 
        } 
    }}
])

和产量:

{
    "_id" : ObjectId("56379b020d97b83cd1506650"),
    "outter" : {
            "inner1" : "blah",
            "inner2" : {
                    "blah" : "anotherThing"
            }

    }
}

【讨论】:

    【解决方案2】:

    嗯.... 通过这个:

    Model.aggregate([
                        {
                            $project: {
                                name: 1,
                                "indexes.name":{
                                    $cond: {
                                        if: {$eq:["$indexes.name",'стафилококки']},
                                        then: "$indexes.name",
                                        else: null
                                    }
                                },
                                "indexes.units":1
                            }
                        }
                    ], callback)
    

    对于 name.indexes 始终返回“null”

    [ 
       { _id: 564c6a5991b08dd017c2bd23,
         name: ' воздух ',
         indexes: [ [Object] ] },
       { _id: 564c6cf091b08dd017c2bd24,
         name: 'repa ',
         indexes: [ [Object] ] },
    ]
    

    索引在哪里:

    [ { units: 'fvf', name: null } ]
    [ { units: 'КОЕ', name: null } ]
    

    【讨论】:

    • 我已经研究了我上面的案例。它令人难以置信,** 但是 $cond 中的 "$indexes.name" 转换为数组 ["стафилококки"] !?虽然实际上它是一个类似于 "units" 的字符串!** 所以.. 不存在相等性 (["стафилококки"] !="стафилококки"),并且 $cond 总是返回 false,例如空
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多