Array update 操作合并的问题

2015-05-26 17:06:24 +08:00
 ry_wang
Hi, 各位

又来请教问题了,这次是 update 操作合并的问题.
首先给一个简化版的文档数据如下:

{ "_id" : "8qwsax", "sys_cpu_user": 2, "sys_cpu_idle": 40, "sys_network_traffic" : [ { "device" : "eth0", "type" : "rx", "value" : 1231231 }, { "device" : "eth0", "type" : "tx", "value" : 1235 }, { "device" : "eth1", "type" : "rx", "value" : 1231231 }, { "device" : "eth1", "type" : "tx", "value" : 1235 } ]}

目前计划使用 mongodb 存储监控数据的最新状态, 由于服务器数量较多, 每个监控数据 update 一次数据库是无法接受的(理论每分钟100W条监控数据), 所以理所当然的想到了将多个监控数据合并起来写的问题.

比如 sys_cpu_user 和 sys_cpu_idle 这两个监控数据可以通过如下一条命令写入:

db.datapoint.update({'_id': '8qwsax'}, {'$set': {'sys_cpu_user': 3, 'sys_cpu_idle': 22}})

类似 sys_network_traffic 这种 array 数据, 针对每个 elem 的 update 操作是不支持 upsert 的, 比如下面的语句是行不通的:

db.datapoint.update({'_id': '8qwsax', 'sys_network_traffic': {'$elemMatch': {'device': 'eth0', 'type': 'rx'}}}}, {'$set': {'sys_network_traffic.$.value': 1000}}, upsert=True)

因为 upsert 这个参数和 array 的 $ 相冲突, 这个操作必须拆分成先 pull 再 push(upsert 模式).

上面全是废话, 正题来了.....

前面的 set 操作可以简单的合并起来, 但是 pull 操作如何合并写呢?
开始我简单的以为应该这么写:

db.datapoint.update({'_id': '8qwsax'}, {'$pull': {'sys_network_traffic': [{'device': 'eth0', 'type': 'tx'}, {'device': 'eth0', 'type': 'rx'}]}})

不行, 然后我又猜测应该这么写:

db.datapoint.update({'_id': '8qwsax'}, {'$pull': {'sys_network_traffic': {'$in': [{'device': 'eth0', 'type': 'tx'}, {'device': 'eth0', 'type': 'rx'}]}}})

不行, 然后我又猜测应该这么写:

db.datapoint.update({'_id': '8qwsax'}, {'$pull': {'sys_network_traffic': {'$elemMatch': {'$in': [{'device': 'eth0', 'type': 'rx'}, {'device': 'eth0', 'type': 'tx'}]}}}})

还是不行.....看官方的文档也没见有更新同一 array 下多个 elem 的例子, 都是更新不同 array(多个_id)下相同 elem 的例子

作为新手表示无能为力了,各位大神求帮忙?
3510 次点击
所在节点    MongoDB
1 条回复
jiangzhuo
2015-06-19 16:40:38 +08:00
頻繁改變Array的大小而沒有實現進行相應的優化就比較作死了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/193880

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX