mongodb Mongoose -在对象数组中增加一个值

0tdrvxhp  于 2023-10-16  发布在  Go
关注(0)|答案(3)|浏览(134)

我很难弄清楚如何在数组中增加对象的值
例如,我有一个基于Poll模式的文档:

{
  "_id": "584b2cc6817758118e9557d8",
  "title": "Number of Skittles",
  "description": "Test1",
  "date": "Dec 9, 2016",
  "__v": 0,
  "labelOptions": [
    {
      "Bob": 112
    },
    {
      "Billy": 32
    },
    {
      "Joe": 45
    }
  ]
}

使用Express,我可以做到这一点:

app.put('/polls/:id', function(req, res){
  let id = req.params.id;
  let labelOption = req.query.labelOption;
  Poll.findOneAndUpdate(
    {'_id' :  id},
    {$inc: {`labelOptions.$.${labelOption}`: 1 }},
    function(err){
      console.log(err)
    })

其中labelOption是我想增加其值的值
更简洁地说,我在文档内部遇到了问题。

41zrol4v

41zrol4v1#

如果labelOptions是一个Object数组,则不可能直接递增.find查询中的值。为了更简单,你应该把labelOptions类型从Array of Objects改为Object:

"labelOptions": {
    "Bob": 112,
    "Billy": 32,
    "Joe": 45
};

如果您要通过文档的_id进行查询,请考虑使用.findByIdAndUpdate而不是.findOneAndUpdate。然后,你可以通过以下方式实现你想要的:

Poll.findByIdAndUpdate(
    id,
    {$inc: {`labelOptions.${labelOption}`: 1 }},
    function(err, document) {
    console.log(err);
});

更新:如果你坚持使用labelOptions的对象数组,有一个解决办法:

Poll.findById(
    id,
    function (err, _poll) {

        /** Temporarily store labelOptions in a new variable because we cannot directly modify the document */
        let _updatedLabelOptions = _poll.labelOptions;

        /** We need to iterate over the labelOptions array to check where Bob is */
        _updatedLabelOptions.forEach(function (_label) {

            /** Iterate over key,value of the current object */
           for (let _name in _label) {

               /** Make sure that the object really has a property _name */
               if (_label.hasOwnProperty(_name)) {

                   /** If name matches the person we want to increment, update it's value */
                   if (_name === labelOption) ++_label._name;
               }
           }
        });

        /** Update the documents labelOptions property with the temporary one we've created */
        _poll.update({labelOptions: _updatedLabelOptions}, function (err) {

            console.log(err);
        });
    });
fxnxkyjh

fxnxkyjh2#

还有另一种方法可以做到这一点,它允许更灵活的文档模型。如果你给对象添加一个字段,比如:

{
  "_id": "584b2cc6817758118e9557d8",
  "title": "Number of Skittles",
  "description": "Test1",
  "date": "Dec 9, 2016",
  "__v": 0,
  "labelOptions": [
    {
      "name": "Bob",
      "number": 112
    },
    {
      "name": "Billy",
      "number": 32
    },
    {
      "name": "Joe"
      "number": 45
    }
  ]
}

然后你可以这样做:

app.put('/polls/:id', function(req, res){
  let id = req.params.id;
  let labelOption = req.query.labelOption;
  Poll.findOneAndUpdate(
    {
     '_id' :  id,
     'labelOptions.name': labelOption
    },
    {$inc: {
      "labelOptions.$.number": 1 
    }},
    function(err){
      console.log(err)
    })
 });
oxosxuxt

oxosxuxt3#

人们解决了它,但是,如果你使用它,如果数组中的元素不存在,一个解决方案:

app.put('/polls/:id', async function (req, res) {
                let id = req.params.id;
                let labelOption = req.query.labelOption;
                const exits = await Poll.exists({ _id: id, "labelOptions.name": labelOption });

                if (exits)
                    await Poll.updateOne(
                        { _id: id, "labelOptions.name": labelOption },
                        {
                            $inc: {
                                "labelOptions.$.number": 1
                            }
                        }
                    );
                else
                    await Poll.updateOne({ _id: id }, {
                        $push: {
                            labelOptions: {
                                name: labelOption,
                                number: 1
                            }
                        }
                    });

            });

相关问题