访问 $map 变量在 $cond 中

huangapple go评论49阅读模式
英文:

Accessing $map variable in $cond

问题

以下是您提供的代码的翻译部分:

我有一些存储在MongoDB集合中的数据看起来像这样

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

我想遍历所有的interactions,并将prompts设置为包含当前prompt值的数组。类似于这样:

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

我一直在尝试使用带有聚合管道的updateMany(),但出现了一个我不理解的错误。这是我的更新操作:

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

运行此操作时,我收到错误消息:

无法识别的表达式'$$interaction.prompt'。

运行不带$cond的更新操作可以正常工作:

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

但在该操作之后,没有prompt的数组元素会具有一个包含null值的数组:

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

我不希望在没有prompt的元素上设置prompts

那么为什么我无法在$cond中访问$$interaction.prompt
或者,如果有更好的方法来实现我想要做的事情,请告诉我。


<details>
<summary>英文:</summary>

I have some data in a MongoDB collection that looks something like this:

```javascript
db.test.insertOne(
    { &quot;interactions&quot;: [
            {
                data: &quot;keep&quot;,
                prompt: &quot;prompt 1&quot;
            },
            {
                other: &quot;keep&quot;,
                prompt: &quot;prompt 2&quot;
            },
            {
                field: &quot;no prompt&quot;
            }
        ]}
    )

I want to iterate over all the interactions, and set prompts to an array containing the current value of prompt. Something like this:

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

I've been trying to do a updateMany() with an aggregation pipeline, but am getting an error that I don't understand. This is my update:

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

Running this I get an error:

> Unrecognized expression '$$interaction.prompt'.

Running the update without the $cond works:

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

but after that operation, the array element that didn't have a prompt has an array with a null value:

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

I don't want prompts set on an element that didn't have prompt.

So why can't I access $$interactions.prompt within the $cond?
Alternatively, if there's a better way to accomplish what I want to do, please let me know.

答案1

得分: 3

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

而且,你必须以$运算符开头,而不是以变量$$开头。

相反,你需要检查$$interaction.prompt是否既不是undefined也不是null

Demo @ Mongo Playground

英文:

In the aggregation pipeline, you can't use the $exists operator.

And you must start with the $ operator but not with variable $$.

Instead, you check whether $$interaction.prompt is neither undefined nor null.

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

Demo @ Mongo Playground

答案2

得分: 0

以下是您要翻译的内容:

For some reason, using $not and $in didn't work in my database, although it did in the Playground. After finding an alternative here: https://stackoverflow.com/a/25515046/1303158, my final solution is:

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

Demo @ Mongo Playground

英文:

For some reason, using $not and $in didn't work in my database, although it did in the Playground. After finding an alternative here: https://stackoverflow.com/a/25515046/1303158, my final solution is:

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

Demo @ Mongo Playground

huangapple
  • 本文由 发表于 2023年2月16日 13:04:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/75468052.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定