mongoDB 中 $ 和 $$ 详解

初学 mongo 的时候就体验到了 aggregate 函数的强大。aggregate 函数也毫无疑问的是 mongo 的核心功能。

但是 aggregate 中存在两个很神秘的符号 $ 和 $$。下面着重讲一下 aggregate 的设定。

首先明确 mongo 中的一个概念:query 和 expression 的区别。

query 是查询语句,而 expression 是表达式。两者有基本不同的语法,mongo 的官方文档中对 queryexpression 的语法都有很详细的定义。

不同的语法带来不同的功能。

query 只会用在查询中,表达了一种筛选条件,对结果集运行后就可以直接获得筛选结果。

expression 则在 aggregate 中广泛存在,而且通常都会产生一个返回值。

这里就产生了第一个很让人迷惑的点,因为绝大多数的操作符(例如 $in / $or / $lt 等等)同时存在于 query 和 expression 中,并且他们的写法是完全不同的。

以 $in 举例,query 的 $in 的用法是

这表示查询所有 fieldA 值为 “A” 或 “D” 的文档

而在 expression 中 $in 的用法变成了

表达 fieldA 值为 “A” 或 “D” 时返回 true

 


介绍完了 query 和 expression 的区别之后 我们开始介绍 $ 和 $$ 的含义。

$ 的含义很简单,在 query 中,如果想要选中一个变量可以直接写他的字段名 例如上面例子里的 fieldA。

而在 expression 中,如果你需要选中一个变量,为了和普通字符串区别开,你就得在他的开头写上 $ 符,如上例中的 $fieldA。

似乎这样已经很全面没什么问题了?

并不是,因为 expression 中有 $let 和 $map 等等操作符可以定义变量,甚至 filter 中的 as 别名也会参合进来搅屎。那这些变量如果和本身的字段冲突了怎么办?更何况语义里这两个就完全不是同一种东西啊。

解决方案是 $$ 符。

$$ 符的适用场景就是调用一些与文档无关的变量(包括系统变量和人为定义变量)时使用。举例来说。

这时 $$fieldB 就指向了我们刚刚取了别名的 $fieldA。

另外,如果你闲的蛋疼。想要统一变量名,觉得什么 $ 啊 $$ 啊的太乱了。很简单,官方提供了一个系统变量 CURRENT。你可以把每一个 aggregate 中的变量都写成 $$CURRENT.xxx。例如 $fieldA 可以写成 $$CURRENT.fieldA。

总结:

以 fieldA 为例

fieldA:存在于 query 中,表示选定的字段名

$fieldA:存在于 expression 中,表示选定的字段名

$$fieldA:存在于 expression 中,表示 自定义变量/系统变量/别名


一些补充。

比较特殊的是 $match 表达式,他会在 $ 遍地的 aggregate 中引入一个 query。再加上 $match 表达式实在太常用了。所以 aggregate 函数中经常出现 fieldA / $fieldA / $$fieldA 三巨头共同出现的现象,可以说是很让人困扰了。

#EOF

发表评论

电子邮件地址不会被公开。

This site uses Akismet to reduce spam. Learn how your comment data is processed.