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

MongoDB:为什么需要$literal?在哪里可以使用它?,mongodb,aggregation-framework,Mongodb,Aggregation Framework,我在聚合框架中使用了MongoDB$literal,但我不知道它可以在哪里使用?更重要的是,为什么需要它 官方MongoDB文档中的示例 与上面使用$literal的示例不同,为什么我不能使用如下所示 db.records.aggregate( [ { $project: { costsOneDollar: { $eq: [ "$price", "$1" ] } } } ] ) 还提供了一些其他示例,展示了$literal的最佳(或有效)用法。您给出的$1示例将尝试将价格字段与1字段进行

我在聚合框架中使用了MongoDB$literal,但我不知道它可以在哪里使用?更重要的是,为什么需要它

官方MongoDB文档中的示例

与上面使用$literal的示例不同,为什么我不能使用如下所示

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

还提供了一些其他示例,展示了$literal

的最佳(或有效)用法。您给出的
$1
示例将尝试将
价格
字段与
1
字段进行比较。通过指定
$literal
运算符,您告诉MongoDB它就是确切的字符串
“$1”
。如果您希望在代码中使用MongoDB函数名作为字段名,或者甚至使用查询片段作为字段值,则可能会出现同样的情况。

您给出的
$1
示例将尝试将
price
字段与
1
字段进行比较。通过指定
$literal
运算符,您告诉MongoDB它就是确切的字符串
“$1”
。如果您希望在代码中使用MongoDB函数名作为字段名,或者甚至使用查询片段作为字段值,则可能会出现同样的情况。

对于您的基本情况,我认为这是不言自明的:

在表达式中,美元符号$计算为字段路径;i、 e.提供进入现场的通道。例如,$eq表达式$eq:[“$price”,“$1”]在文档中名为price的字段中的值和名为1的字段中的值之间执行相等检查

因此,由于
$
保留用于评估文档中的字段路径值,因此这将被视为在文档中查找名为
1
的“字段”。因此,实际的比较可能在名为“price”的字段之间,由于没有名为“1”的字段,因此每个文档都将被视为
null
,因此
false

另一方面,如果字段“price”的值实际上等于
“$1”
,则使用
$literal
可以考虑该“值”(而不是字段路径引用)。因此是“字面的”

该操作符实际上已经存在了一段时间(实际上是从MongoDB 2.2开始),但它的伪装是
$const
,虽然没有添加,但它仍然是基本操作符,
$literal
实际上只是它的一个“别名”

其用途主要是且始终是在管道中要求具有某些“特定值”的情况下使用。就拿这句简单的话来说吧:

{“$project”:{“myField”:“one”}
因此,出于各种原因,您可能希望这样做,并且基本上在这样的语句中返回一个“literal”值。但如果您尝试,它将导致错误,因为它基本上不会解析为字段选择的“字段路径”或
布尔值
条件,这在这里是必需的。因此,如果您改为使用:

{“$project”:{“myField”:{“$literal”:“one”}}
然后你有一个值为“1”的“myField”,就像你要求的那样

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

{“$project”:{“array”:{“$literal”:[“A”、“B”、“C”]},
{“$unwind”:“$array”},
{“$组”:{
“\u id”:“$\u id”,
“trans”:{“$push”:{
“$cond”:[
{“$eq”:[“$array”,“A”]},
“$fieldA”,
{“$cond”:[
{“$eq”:[“$array”,“B”]},
“$fieldB”,
“$fieldC”
]}
]
}}
}}
这可能更现代地被以下内容取代:

{“$project”:{
“trans”:{
“$map”:{
“输入”:[“A”、“B”、“C”],
“as”:“el”,
“在”:{
“$cond”:[
{“$eq”:[“$$el”,“A”]},
“$fieldA”,
{“$cond”:[
{“$eq”:[“$$el”,“B”]},
“$fieldB”,
“$fieldC”
]}
]
}
}
}
}}
作为一种基于位置将选定字段移动到数组中的构造,不同之处在于作为“数组”和字段赋值,
$literal
是必需的,但作为“输入”参数,纯数组表示法就可以了

因此,一般情况是:

  • 其中需要保留一些内容(如
    $
    )作为匹配的值

  • 其中有一个特定值要作为字段赋值注入,而不是作为另一个运算符表达式的参数注入


  • 对于你的基本情况,我认为答案是不言自明的:

    在表达式中,美元符号$计算为字段路径;i、 e.提供进入现场的通道。例如,$eq表达式$eq:[“$price”,“$1”]在文档中名为price的字段中的值和名为1的字段中的值之间执行相等检查

    因此,由于
    $
    保留用于评估文档中的字段路径值,因此这将被视为在文档中查找名为
    1
    的“字段”。因此,实际的比较可能在名为“price”的字段之间,由于没有名为“1”的字段,因此每个文档都将被视为
    null
    ,因此
    false

    另一方面,如果字段“price”的值实际上等于
    “$1”
    ,则使用
    $literal
    可以考虑该“值”(而不是字段路径引用)。因此是“字面的”

    该操作符实际上已经存在了一段时间(实际上是从MongoDB 2.2开始),但它的伪装是
    $const
    ,虽然没有添加,但它仍然是基本操作符,
    $literal
    实际上只是它的一个“别名”

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