且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

当父文档可能不存在时更新MongoDB子文档

更新时间:2023-11-26 17:58:46

您基本上有3种情况:

    书和评论都存在.这是一个简单的$set
  1. 这本书存在,但没有评论.这需要一个$push
  2. 这本书不存在.这需要{upsert:1}$setOnInsert
  1. both the book and the review exists. This is a simple $set
  2. the book exists but not the review. This need a $push
  3. the book does not exists. This need {upsert:1} and a $setOnInsert

在出现故障的情况下,我无法找到一种方法来统一这两种方法而不损害数据完整性(请记住,MongoDB没有原子事务).

I was not able to find a way to unify any two of these without compromising data integrity in case of failure (remember that MongoDB does not have atomic transaction).

因此,我的***的主意如下:

So my best idea is the following:

// Case 1:
db.books.update({isbn:'1234567890',
                 review: { $elemMatch: {userID: '01234'}}},
                {$set: {'review.$.rating': NEW_RATING}}
               )

// Case 2:
db.books.update({isbn:'1234567890',
                 review: { $not: { $elemMatch: {userID: '01234'}}}},
                {$push: {review: {rating: NEW_RATING, userID:'01234'}}}
               )

// Case 3:
db.books.update({isbn:'1234567890'},
                {$setOnInsert: {review: [{rating: NEW_RATING, userID:'01234'}]}},
                {upsert:1}
               )

您可能会盲目地原始运行这三个更新,因为它们之间没有重叠的情况.事情的妙处是所有这些操作都是幂等.因此,您可以一次或多次应用它们,并始终获得相同的结果.这在故障转移的情况下尤其重要.此外,万一发生故障,数据库也不会不一致或丢失现有数据.最糟糕的是,该评论被更新.最后,即使在并发更新的情况下,此也应保证数据的一致性(即:在这种情况下,一个更新将覆盖另一个更新,但是您不应该最终为同一本书拥有两个文档或获得两个评论)同一本书的同一用户的用户).
后面的一点必须确认,因为现在已经晚了,所以我的分析可能会有些疑问.

You may blindly run those three updates in a raw as there is no overlapping case between them. The beauty of the thing is all these operations are idempotent. So you can apply them once or several times and always get the same result. This is especially important in case of failover. In addition, there is no way for your DB to be inconsistent or to loose existing data in case of failure. At worst, the review is not updated. Finally this should guarantee data consistency even in case of concurrent updates (i.e.: in that case, one update will overwrite the other, but you shouldn't end up having two documents for the same book or two reviews of the same user for the same book).
That later point has to be confirmed as it is late here so my analysis might be somewhat doubtful.

最后一点,如果要减少MongoDB与应用程序之间的往返次数,可以查看

As final note, if you want to reduce the number of round-trips between MongoDB and your app, you might take a look at the update database command allowing you to wrap several updates in one command.