提问者:小点点

在$cond中访问$map变量


我在MongoDB集合中有一些数据,看起来像这样:

db.test.insertOne(
    { "interactions": [
            {
                data: "keep",
                prompt: "prompt 1"
            },
            {
                other: "keep",
                prompt: "prompt 2"
            },
            {
                field: "no prompt"
            }
        ]}
    )

我想遍历所有交互,并将提示设置为包含提示当前值的数组。类似于这样:

{
  "interactions": [
    {
      "data": "keep",
      "prompt": "prompt 1",
      "prompts": [ "prompt 1" ]
    },
    {
      "other": "keep",
      "prompt": "prompt 2",
      "prompts": [ "prompt 2" ]
    },
    {
      "field": "no prompt"
    }
  ]
}

我一直在尝试使用聚合管道执行update很多(),但收到一个我不明白的错误。这是我的更新:

db.test.updateMany(
    {},
    [{
        $set: {
            interactions: {
                $map: {
                    input: "$interactions",
                    as: "interaction",
                    in: {
                        $mergeObjects: [
                            "$$interaction",
                            {
                                $cond: {
                                    if: { "$$interaction.prompt": { $exists: true } },
                                    then: {
                                        prompts: [ "$$interaction.prompt" ]
                                    },
                                    else: {}
                                }
                            }
                        ]
                    }
                }
            }
        }
    }]
    )

运行这个我得到一个错误:

无法识别的表达式'$$交互.提示符'。

在没有$cond的情况下运行更新:

db.test.updateMany(
    {},
    [{
        $set: {
            interactions: {
                $map: {
                    input: "$interactions",
                    as: "interaction",
                    in: {
                        $mergeObjects: [
                            "$$interaction",
                            {
                                prompts: [ "$$interaction.prompt" ]
                            }
                        ]
                    }
                }
            }
        }
    }]
    )

但是在该操作之后,没有提示的数组元素有一个null值的数组:

{
  "interactions": [
    {
      "data": "keep",
      "prompt": "prompt 1",
      "prompts": ["prompt 1"]
    },
    {
      "other": "keep",
      "prompt": "prompt 2",
      "prompts": ["prompt 2"]
    },
    {
      "field": "no prompt",
      "prompts": [null]
    }
  ]
}

我不希望提示设置在没有提示的元素上。

那么,为什么我不能在$cond中访问$$交互.提示?或者,如果有更好的方法来完成我想做的事情,请告诉我。


共2个答案

匿名用户

在聚合管道中,您不能使用$存在运算符。

并且您必须从$运算符开始,但不能从变量$$开始。

相反,您检查$$交互.提示符是否既不是未定义也不是null

db.collection.updateMany({},
[
  {
    $set: {
      interactions: {
        $map: {
          input: "$interactions",
          as: "interaction",
          in: {
            $mergeObjects: [
              "$$interaction",
              {
                $cond: {
                  if: {
                    $not: {
                      $in: [
                        "$$interaction.prompt",
                        [
                          undefined,
                          null
                        ]
                      ]
                    }
                  },
                  then: {
                    prompts: [
                      "$$interaction.prompt"
                    ]
                  },
                  else: {}
                }
              }
            ]
          }
        }
      }
    }
  }
])

演示@Mongo游乐场

匿名用户

由于某种原因,使用$not$in在我的数据库中不起作用,尽管它在Playground中起作用。在这里找到替代方案后:https://stackoverflow.com/a/25515046/1303158,我的最终解决方案是:

db.collection.update({},
[
  {
    $set: {
      interactions: {
        $map: {
          input: "$interactions",
          as: "interaction",
          in: {
            $mergeObjects: [
              "$$interaction",
              {
                $cond: {
                  if: {
                    $gt: [
                      "$$interaction.prompt",
                      null
                    ]
                  },
                  then: {
                    prompts: [
                      "$$interaction.prompt"
                    ]
                  },
                  else: {}
                }
              }
            ]
          }
        }
      }
    }
  }
],
{
  multi: true
})

演示@Mongo游乐场