$merge
的用途是把聚合管道产生的结果写入指定的集合,有时候可以用$merge
来做物化视图。需要注意,$meger
操作必须是聚合管道的最后一个阶段。具体功能有:
featureCompatibilityVersion
不小于4.4,且读选项允许二级读取。注意:
$merge
读取操作会发送到二级节点,写入操作只发生在主节点。$merge
在副本集二级节点的操作,在使用前要确认驱动支持。{ $merge: {
into: <collection> -or- { db: <db>, coll: <collection> },
on: <identifier field> -or- [ <identifier field1>, ...], // 可选
let: <variables>, // 可选
whenMatched: <replace|keepExisting|merge|fail|pipeline>, // 可选
whenNotMatched: <insert|discard|fail> //可选
} }
举例:
{ $merge: {into: "mycollection", on: "_id", whenMatched: "replace", whenNotMatched: "insert" } }
如果都使用$merge
的默认选项并且输出到当前数据库,可以使用简化形式:
{ $merge: <collection> } //输出到当前数据库
输出到的集合,可以指定到数据库,也可以不指定数据库,输出到当前数据库。例如:
输出到当前库的my_coll
集合:into: "my_coll"
输出到mydb
的my_coll
集合:into:{db:"mydb", coll:"my_coll"}
注意:
可选字段,可以指定一个或多个字段作为判断文档唯一性的ID,用于匹配目标集合中是否已经存在相同ID的文档。
举例:
on: "_id"
on: ["date", "name"]
注意:
on
字段,除非on
是_id
,否则在聚合结果文档中必须存在on
中指定的字段,如果聚合结果中没有_id
字段,会自动添加一个。on
指定的字段的值不允许为空或数组。$merge
必须要有一个包含on
字段的唯一索引,索引键顺序无关紧要。
on
的缺省值依赖于输出集合:
on
的标识符必须且缺省为_id
字段,相应的唯一索引_id
是被自动创建的。on
标识符缺省为_id
字段on
标识符缺省为所有分片键值字段和_id
字段,如果指定了一个不同的on
标识符,on
必须包含所有的分片键值字段。可选字段,指定当输出集合中存在与on
字段指定的键值相同的文档时的处理方式,可以为以下值:
使用聚合结果替换已经存在的文档。当执行替换的时候不能修改对应文档_id
字段的值,如果输出集合是分片集合,也不能修改分片键值,否则操作会产生错误。为了避免这个错误,如果on
字段中没有包含_id
字段,可以从聚合结果中移除_id
字段以避免这个错误,比如可以使用类似$unset
的阶段预先处理以下。
不替换已经存在的文档
缺省值,合并匹配的文档,类似于$mergeObjects
操作
举例:
如果目标集合有一个文档:
{_id: 1, a: 1, b: 1 }
聚合结果的文档是:
{ _id: 1, b: 5, z: 1 }
则合并后的文档是:
{ _id: 1, a: 1, b: 5, z: 1 }
跟"replace"
类似,合并的时候"_id"字段或分片键值是不能被修改的。
停止并且报错,之前所有的输出和更改都不能撤销。
当on
指定的键值相同时,使用一个聚合管道更新输出集合的文档,如:
[ <stage1>, <stage2> ... ]
但是,管道只能包含下面的阶段:
$addFields
及其别名$set
$projecct
及其别名$unset
$replaceRoot
及其别名$replaceWith
管道不能修改on
涉及字段的值,比如匹配字段year
,管道是不能修改year
字段值的。另外whenMatched
管道可以使用$<field>
直接访问输出文档的字段。如果要在管道中访问聚合结果文档(就是输入文档)的字段,可以使用下面两种方式:
$$new
变量来访问字段,就是$$new.<field>
。$$new
变量只能在省略let
时才能使用。let
字段使用用户自定义的变量。以$$
符号为前缀指定变量名$$<variable_name>
,如:$$year
。如果变量是文档,也可以包含文档字段,格式为$$<变量名>.<字段>
。例如,$$year.month
。可选字段,为whenMatched
的管道指定变量。可以指定文档的变量名和表达式:
{ <variable_name_1>: <expression_1>,
...,
<variable_name_n>: <expression_n> }
可选字段,决定了$merge
在输出文档匹没有配到对应文档的情况,可以指定下面的预定义的字符串常量:
"insert"
插入,缺省值,将聚合后的文档插入到输出集合。discard
丢弃,就是不向输出集合中插入文档。fail
失败,停止并宣告聚合操作失败,之前已经在输出集合中写入或修改的文档不能回滚。