5

これは、 books.reviewsサブコレクションを含むbookコレクションで構成される私のデータです。

books = [{
    _id: ObjectId("5558f40ad498c653748cf045"),
    title: "Widget XYZ",
    isbn: 1234567890,
    reviews: [
        {
            _id: ObjectId("5558f40ad498c653748cf046"),
            userId: "01234",
            rating: 5,
            review: "Yay, this great!"
        },
        {
            _id: ObjectId("5558f40ad498c653748cf047"),
            userId: "56789",
            rating: 3,
            review: "Meh, this okay."
        }
    ]
}]

Node.js (Mongoose を使用) では、次の条件で、ユーザーがフォームからレビューを送信し、レビューと本の isbn をサーバーに送信できるようにする必要があります。

  1. 特定の isbn を持つ本がまだ存在しない場合は、それを追加してから、レビューを追加します (明らかに、まだ存在していません)。
  2. 本が実在するなら…
    • このユーザーのこの書籍のレビューが存在しない場合は、レビューを追加します。
    • このユーザーのこの書籍のレビューが存在する場合は、更新します。

これは 4 つの個別のクエリで実行できますが、最適ではないことはわかっています。使用できるクエリの最小数はいくつですか (もちろん、それらのクエリは何ですか)?

4

1 に答える 1

5

基本的に 3 つのケースがあります。

  1. 本とレビューの両方が存在します。これは単純な$set
  2. 本は存在しますが、レビューはありません。これには$push
  3. 本は存在しません。この必要性{upsert:1}$setOnInsert

障害が発生した場合にデータの整合性を損なうことなく、これらのうちの 2 つを統合する方法を見つけることができませんでした (MongoDB にはアトミック トランザクションがないことを思い出してください)。

したがって、私の最良のアイデアは次のとおりです。

// 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}
               )

それらの間に重複するケースがないため、これら3つの更新をそのままで盲目的に実行できます。すばらしいのは、これらすべての操作がべき等であることです。したがって、それらを 1 回または数回適用して、常に同じ結果を得ることができます。これは、フェールオーバーの場合に特に重要です。さらに、DB が矛盾したり、障害が発生した場合に既存のデータを失ったりすることはありません。最悪、レビューが更新されません。最後に、これにより、同時更新の場合でもデータの一貫性が保証されるはずです (つまり、その場合、1 つの更新で別の更新が上書きされますが、同じ書籍に対して 2 つのドキュメントや、同じユーザーの同じ書籍に対する 2 つのレビューが発生することはありません)。本)。
ここで遅いので、その後の点を確認する必要があるため、私の分析はやや疑わしいかもしれません.

最後に、MongoDB とアプリ間の往復回数を減らしたい場合は、1 つのコマンドで複数の更新をラップできるようにするupdateデータベース コマンドを検討してください。

于 2015-05-18T21:23:27.977 に答える