mongodb 批量插入的微优化?或者这是一个重要的优化?
前提:更新语句是无害的,因为默认情况下驱动程序以一种消息传递方式工作(只要不使用 getLastError
)。
问题以下片段是在 mongodb 中进行大容量插入的最佳方法吗?是否可以折叠步骤2和3?
编辑:旧的有缺陷的表单,见下文
// step 1 : making sure the top-level document is present (an upsert in the real
example)
db.test.insert( { x :1} )
// step 2 : making sure the sub-document entry is present
db.test.update( { x:1 }, { "$addToSet" : { "u" : { i : 1, p : 2 } } }, false)
// step 3 : increment a integer within the subdocument document
db.test.update( { x : 1, "u.i" : 1}, { "$inc" : { "u.$.c" : 1 } },false)
我有一种感觉,没有办法退出操作3,因为$
运算符需要在查询部分的查询字段中启动更新。阿米里特?亚姆莱特?
如果这是最好的做事方式,我可以在代码中发挥创意并疯狂进行更新操作吗?
编辑:新形式
我的逻辑中有一个错误,谢谢盖茨。如果可能的话,仍然希望折叠更新:D
// make sure the top-level entry exists and increase the incidence counter
db.test.update( { x : 1 }, { $inc : { i : 1 } }, true ) --1
// implicetly creates the array
db.test.update( { x : 1 , u : { $not : { $elemMatch : { i : 1 } } } } ,
{ $push : { u : { i : 1 , p :2 , c:0} } }) -- 2
db.test.update( { x :1 , "u.i" : 1}, { $inc : { "u.$.c" : 1 } },false) --3
注意: $addToSet
在这种情况下没有用,因为它进行逐元素匹配,因此无法表达数组中的元素可能是什么可变
如C++ OO按位比较说法
问题毫无意义数据模型是错误的。请投票结束(OP)。
premise : update statements are harmless since the driver by default works in one way messaging (as long as getLastError
isn't used).
question Is the following fragment the best way to do this in mongodb for high volume inserts ? Is it possible to fold step 2 and 3 ?
edit : old buggy form , see below
// step 1 : making sure the top-level document is present (an upsert in the real
example)
db.test.insert( { x :1} )
// step 2 : making sure the sub-document entry is present
db.test.update( { x:1 }, { "$addToSet" : { "u" : { i : 1, p : 2 } } }, false)
// step 3 : increment a integer within the subdocument document
db.test.update( { x : 1, "u.i" : 1}, { "$inc" : { "u.$.c" : 1 } },false)
I have a feeling there is no way out of operation 3, since the$
operator requires priming in the query field of the query part of an update. amirite ? iamrite ?
If this is the best way to do things, can I get creative in my code and go nuts with update operations ?
edit : new form
There was a bug in my logic, thanks Gates. Still want to fold the updates if possible :D
// make sure the top-level entry exists and increase the incidence counter
db.test.update( { x : 1 }, { $inc : { i : 1 } }, true ) --1
// implicetly creates the array
db.test.update( { x : 1 , u : { $not : { $elemMatch : { i : 1 } } } } ,
{ $push : { u : { i : 1 , p :2 , c:0} } }) -- 2
db.test.update( { x :1 , "u.i" : 1}, { $inc : { "u.$.c" : 1 } },false) --3
notes : $addToSet
is not usefull in this case, since it does a element-wise match, there is no way to express what elements in an array may be mutable
as in C++ OO bitwise comparison parlance
question is pointless Data model is wrong. Please vote to close (OP).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
因此,首先要注意的是
$
位置运算符有点粗略。它有很多“陷阱”:它不能很好地处理 upserts,它只影响第一个真正的匹配,等等。要理解 #2 和 #3 的“折叠”,您需要查看命令的输出:
根据您提供的顺序,整个事情可以整合到一个更新中。
如果你只想一起努力 #2 和 #2 #3,那么您担心
'ui':1
与u.$.c
的匹配。但这里有一些边缘情况你必须澄清。让您的起始文档如下:
您对运行更新 #3 有何期望?
正如所写,您会得到:
这是正确的吗?第一份文件合法吗? (语义正确)?根据答案,这实际上可能是文档结构的问题。
So, the first thing to note is that the
$
positional operator is a little sketchy. It has a lot of "gotchas": it doesn't play well with upserts, it only affects the first true match, etc.To understand "folding" of #2 and #3, you need to look at the output of your commands:
Based on the sequence you provided, the whole thing can be rolled into a single update.
If you're only looking to roll together #2 & #3, then you're worried about matching
'u.i':1
withu.$.c
. But there are some edge cases here you have to clarify.Let your starting document be the following:
What do you expect from running update #3?
As written you get:
Is this correct? Is that first document legal? (semantically correct)? Depending on the answers, this may actually be an issue of document structure.