2016-11-02 10 views
0

私はMongooseとMongoDBを使い慣れており、ネストされた配列に存在するフィールド値を更新する必要があるシナリオを実装しようとしています。例えばMongoose - ネストされた配列のフィールド値をインクリメント

次のように、私のDBエントリは次のとおりです。

{ 
    "_id" : ObjectId("581999ecf97860b77c1625f6"),  // this is userID 
    "username" : "test", 
    "__v" : 0, 
    "polls" : [ 
      { 
        "url" : "xxxx", 
        "question" : "city or united", 
        "_id" : ObjectId("581999ec3ba2b15ad7fbcd50"), //this is questionID 
        "option" : [ 
          { 
            "votes" : 0, 
            "value" : "city", 
            "_id" : ObjectId("581999ec3ba2b15ad7fbcd52") //this is optionID 
          }, 
          { 
            "votes" : 0, 
            "value" : "united", 
            "_id" : ObjectId("581999ec3ba2b15ad7fbcd51") //this is optionID 
          } 
        ] 
      }, 
      { 
        "url" : "yyyy", 
        "question" : "chelsea or arsenal", 
        "_id" : ObjectId("58199d0ef11835685d3f41b7"), 
        "option" : [ 
          { 
            "votes" : 0, 
            "value" : "chelsea", 
            "_id" : ObjectId("58199d0ef11835685d3f41b9") 
          }, 
          { 
            "votes" : 0, 
            "value" : "arsenal", 
            "_id" : ObjectId("58199d0ef11835685d3f41b8") 
          } 
        ] 
      } 
    ] 
} 

私はそれは、フロントエンドから選択されるたびに、特定のオプションの票をインクリメントする必要があります。

以下は、これまで実装しようとしてきたものの、成功しなかったものです。以下は

PollsSchema.methods.submitVote = function(id, callback){ 
var increment = { $inc: { 'polls.option.$.votes': 1 } }; 
var query = { 
    '_id': id.userID, 
    'polls._id': id.questionID, 
    'polls.option._id': id.optionID 
}; 

return this.model('Poll').update(query, increment, callback); 
}; 

私のスキーマです:

var PollsSchema = new Schema({ 
username: String, 
polls: [ 
    { 
     question: String, 
     option: [ 
      { 
       value: String, 
       votes: Number 
      } 
     ], 
     url: String 
    } 
] 
}); 

は、私はこっち間違ってやっているものはありますか?

お時間をありがとうございます。

+0

MongoDBの既知の問題です。既に開いているバグがあります。https://jira.mongodb.org/browse/SERVER-831 –

+0

[Mongoの2レベル階層でポジショナル演算子を使用する]の可能な複製(http://stackoverflow.com/questions/5038983/ 2レベル階層を使用したポジションオペレータ使用) –

答えて

1

ネストされた配列のプレースホルダーの置き換えをサポートしていないMongo dbの制限があります。位置演算子は、1つのレベルに対してのみ使用できます。あなたが投票のような質問を更新しようとしていたなら、それはうまくいくでしょう。また、mongo db does notは投票のような複数のプレースホルダーをサポートしています。

コメントに指摘されているように、そのジラ欠陥を見ることができます。今すぐ回避策に来る。

オプションを平坦化して、投票の中に入れることができます。以下のようなもの質問とオプションの一意のIDを持っている限り、常に一意のレコードに解決する必要があります。

{ 
    "_id": ObjectId("581999ecf97860b77c1625f6"), // this is userID 
    "username": "test", 
    "__v": 0, 
    "polls": [{ 
     "url": "xxxx", 
     "question": "city or united", 
     "_id": ObjectId("581999ec3ba2b15ad7fbcd50"), //this is questionID 
     "votes": 0, 
     "value": "city", 
     "option_id": ObjectId("581999ec3ba2b15ad7fbcd52") //this is optionID 
    }, { 
     "url": "xxxx", 
     "question": "city or united", 
     "_id": ObjectId("581999ec3ba2b15ad7fbcd50"), //this is questionID 
     "votes": 0, 
     "value": "united", 
     "option_id": ObjectId("581999ec3ba2b15ad7fbcd51") //this is optionID 
    }] 
} 

これで投票を増やすことができます。

PollsSchema.methods.submitVote = function(id, callback) { 
    var increment = { 
     $inc: { 
      'polls.$.votes': 1 
     } 
    }; 
    var query = { 
     '_id': id.userID, 
     'polls._id': id.questionID, 
     'polls.option_id': id.optionID 
    }; 

    return this.model('Poll').update(query, increment, callback); 
}; 

他のオプションは、集約パイプラインを使用してアイテムを見つけて、その返されたオブジェクトを更新することです。

+0

ありがとうございます。スキーマを再構築することができます。しかし、当面はquestionIDで投票を見つけて、オプションにループを実行し、option._idがfrontendから渡されたoptionIDと一致する場合に投票を増やすという回避策を使用しました。私はそれをDBに書き戻すためにsave()を使用しています。 –

関連する問題