$set 一个字段,oplog 里存的是什么?$inc 存增量还是结果?改数组呢?这篇逐个操作符读 local.oplog.rs,看 diff 的记法,再比较 100 KB 文档改一个字段与整个替换的 oplog 大小。
$set: {a: 2} → o = {'$v': 2, 'diff': {'u': {'a': 2}}}
$set: {b: "y", a: 3} → o = {'$v': 2, 'diff': {'u': {'a': 3, 'b': 'y'}}}
$unset: {keep: ""} → o = {'$v': 2, 'diff': {'d': {'keep': False}}}
$inc: {a: 10} → o = {'$v': 2, 'diff': {'u': {'a': 13}}}
$set: {brand_new: 1}(新字段) → o = {'$v': 2, 'diff': {'i': {'brand_new': 1}}}
$rename: {brand_new: "renamed"} → o = {'$v': 2, 'diff': {'d': {'brand_new': False}, 'i': {'renamed': 1}}}update 条目的 o 带 $v: 2 和 diff:u 是新值,d 是删除的字段,i 是新增的字段,s<字段> 对子文档或数组递归。
$set: {"n.p": 2}(子文档里的字段) → o = {'$v': 2, 'diff': {'sn': {'u': {'p': 2}}}}
$set: {"n.q.r": 6}(两层嵌套) → o = {'$v': 2, 'diff': {'sn': {'sq': {'u': {'r': 6}}}}}
$set: {"n.p": 3, "a": 4}(同时改子文档和顶层) → o = {'$v': 2, 'diff': {'u': {'a': 4}, 'sn': {'u': {'p': 3}}}}$inc 记录的是结果值(13),不是增量(10)。
$set: {"arr.1": 20} → o = {'$v': 2, 'diff': {'sarr': {'a': True, 'u1': 20}}}
$push: {arr: 4} → o = {'$v': 2, 'diff': {'sarr': {'a': True, 'u3': 4}}}
$push: {tags: {$each: ["c", "d"]}} → o = {'$v': 2, 'diff': {'stags': {'a': True, 'u2': 'c', 'u3': 'd'}}}
$pop: {arr: 1}(删最后一个) → o = {'$v': 2, 'diff': {'u': {'arr': [1, 20, 3]}}}
$pull: {tags: "a"}(从头部删) → o = {'$v': 2, 'diff': {'u': {'tags': ['b', 'c', 'd']}}}嵌套路径逐层 s;数组改元素或追加用 a: true 加 u<下标>;$pop 与 $pull 记整个数组。
文档约 100,031 字节。$inc 一个字段:oplog 条目 o = {'$v': 2, 'diff': {'u': {'v': 1}}},整个条目 165 字节
replace_one:oplog 条目 o 的键 ['_id', 'pad', 'v']…,整个条目 100,157 字节(存的是整个新文档)只改一个字段,100 KB 文档的 oplog 条目 165 字节;整个替换要 100,157 字节,复制和 oplog 窗口都受影响。
把 a 设成它已有的值 4:matched 1 modified 0;oplog 新增 0 条
update_many 修改 5 个文档:oplog 新增 5 条,各自的 o: [{'u': {'v': 1}}, {'u': {'v': 1}}, {'u': {'v': 1}}] …(每个文档一条,o2 是 [{'_id': 0}, {'_id': 1}, {'_id': 2}, {'_id': 3}, {'_id': 4}])没有实际修改的 update 不写 oplog;update_many 每个被修改的文档一条。
[{$set: {a: {$add: ["$a", 1]}}}] → o = {'$v': 2, 'diff': {'u': {'a': 5}}}
[{$unset: "b"}] → o = {'$v': 2, 'diff': {'d': {'b': False}}}
[{$replaceWith: {x: 1, y: 2}}] → o = {'_id': 1, 'x': 1, 'y': 2}
上一条的 o 的键: ['_id', 'x', 'y'](没有 diff,是整个新文档)管道形式的 $set、$unset 同样是 diff,$replaceWith 换掉整个文档则整文档替换。