MongoDB:为什么需要使用$literal?在哪里可以使用它?

3
我已经学习了MongoDB聚合框架中的$literal,但我不明白它在哪里可以使用?更重要的是,为什么需要使用它?

来自MongoDB官方文档的示例:

db.records.aggregate( [
   { $project: { costsOneDollar: { $eq: [ "$price", { $literal: "$1" } ] } } }
])

为什么我不能像下面这样使用,而不是使用$literal的示例?

db.records.aggregate( [
   { $project: { costsOneDollar: { $eq: [ "$price", "$1" ] } } }
] )

同时提供一些其他示例,展示$literal的最佳(或有效)用法。
2个回答

5
对于基本情况,我认为文档已经相当自解释了:
在表达式中,美元符号$评估为字段路径;即提供对字段的访问。例如,$eq表达式$eq:["$price","$1"]在文档中执行一个等式检查,其中"$price"表示名为price的字段中的值,"$1"表示名为1的字段中的值。
因此,由于$保留用于文档内字段路径值的评估,那么这将被视为实际上正在查找文档中名为"1"的"字段"。因此,实际比较可能是在名为"price"的字段和因为没有名为"1"的字段而被视为null的情况下进行的,因此对于每个文档都是false。
另一方面,如果字段"price"实际上具有等于"$1"的值,则使用$literal允许考虑该"值"(而不是字段路径引用)。因此是"literal"。
运算符实际上已经存在了一段时间(自MongoDB 2.2以来),但是在$const的伪装下,尽管未记录,但仍然是基本运算符,而$literal实际上只是其“别名”。
主要用法始终是在需要将表达式指定为管道中的某个“特定值”的情况下使用。看看这个简单的语句:
{ "$project": { "myField": "one" } }

因为各种原因,您可能想这样做,并在此类语句中返回“字面”值。但是,如果您尝试这样做,它将导致错误,因为它本质上不会解析为“字段路径”或布尔条件以进行字段选择,这是此处所需的。因此,如果您改用:

{ "$project": { "myField": { "$literal": "one" } } }

那么你就拥有了值为"one"的"myField",就像你要求的一样。

其他用法更具历史意义,例如:

{ "$project": { "array": { "$literal": ["A","B","C" ] } } },
{ "$unwind": "$array" },
{ "$group": {
    "_id": "$_id",
    "trans": { "$push": {
        "$cond": [
            { "$eq": [ "$array", "A" ] },
            "$fieldA",
            { "$cond": [ 
                { "$eq": [ "$array", "B" ] },
                "$fieldB",
                "$fieldC"
            ]}
        ]
    }}
}}

这可能更现代化地被替换为类似于:

{ "$project": {
    "trans": {
        "$map": {
            "input": ["A","B","C"],
            "as": "el",
            "in": {
                "$cond": [
                    { "$eq": [ "$$el", "A" ] },
                    "$fieldA",
                    { "$cond": [
                        { "$eq": [ "$$el", "B" ] },
                        "$fieldB",
                        "$fieldC"
                    ]}
                ]
            }
        }
    }
}}

作为一种将选定字段基于位置移动到数组中的构造,不同之处在于作为“数组”和字段赋值时需要使用$literal,但作为“输入”参数时,普通的数组表示法就可以了。
因此,一般情况如下:
  1. 需要像$这样的保留字符作为匹配值的情况

  2. 需要将特定值注入为字段赋值,而不是另一个操作符表达式的参数。


1
你提供的$1示例会尝试将price字段与1字段进行比较。通过指定$literal操作符,您告诉MongoDB它是确切的字符串"$1"。如果您想在代码中使用MongoDB函数名称作为字段名,甚至使用查询片段作为字段值,也可能是这样。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接