对于基本情况,我认为
文档已经相当自解释了:
在表达式中,美元符号$评估为字段路径;即提供对字段的访问。例如,$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
,但作为“输入”参数时,普通的数组表示法就可以了。
因此,一般情况如下:
需要像$
这样的保留字符作为匹配值的情况
需要将特定值注入为字段赋值,而不是另一个操作符表达式的参数。