2012-02-02 114 views
1

前提:由于缺省驱动程序以单向消息方式工作(只要不使用​​),更新语句是无害的。mongodb批量插入的微优化?或者这是一个重要的优化?

问题以下片段是在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,自$运营商需要的查询部分的查询字段吸更新。 amirite? iamrite?

如果这是做事情的最佳方式,我可以在我的代码中获得创意,并坚持更新操作?

编辑:新形式

有我的逻辑错误,谢谢盖茨。还是想折叠如果可能的更新: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没有在这种情况下有用的,因为它确实元素智能匹配,也没有办法表达可能是一个数组哪些元素mutable在C++中按照OO按位对比的说法

问题是毫无意义的数据模型是错误的。请投票结束(OP)。

回答

1

因此,首先要注意的是位置运算符$有点粗略。它有很多“陷阱”:它不适合用upserts,它只影响第一次真正的匹配,等等。

要理解#2和#3的“折叠”,你需要看看输出你的命令:

db.test.insert({ x :1}) 
{ x:1 } // DB value 

db.test.update({ x:1 }, { "$addToSet" : { "u" : { i : 1, p : 2 } } }, false) 
{ x:1, u: [ {i:1,p;2} ] } // DB value 

db.test.update({ x : 1, "u.i" : 1}, { "$inc" : { "u.$.c" : 1 } },false) 
{ x:1, u: [ {i:1,p:2,c:1} ] } // DB value 

根据你提供的顺序,整个事情可以被整合到一个更新中。

如果你只是想找到一起#2 &#3,那么你担心匹配'u.i':1u.$.c。但是这里有一些边缘案例需要澄清。

让你开始文档如下所示:

{ 
    x:1, 
u: [ 
     {i:1, p:2}, 
     {i:1, p:3} 
    ] 
} 

你从运行更新#3有什么期望?

书面你:

{ 
    x:1, 
u: [ 
     {i:1, p:2, c:1}, 
     {i:1, p:3} 
    ] 
} 

这是正确的吗?这是第一份文件合法吗? (语义正确)?根据答案,这可能实际上是文档结构的问题。

+0

你是对的,这是非法的。'c'应该是集合中的一个可变元素:/。 – 2012-02-03 09:39:53