【问题标题】:How to update 2 arrays elements within a document based on certain conditions如何根据特定条件更新文档中的 2 个数组元素
【发布时间】:2019-07-02 21:53:48
【问题描述】:

我有一个包含 2 个数组的文档,我正在尝试使用 $elemMatch 同时根据某些条件更新两个数组的特定数组元素。

查询

targetManagementSchema.findOneAndUpdate({
     franchiseeId : franchiseeId,
     'yearlyTarget.year': 2019,
     'quarterlyTarget': {
        $elemMatch: {
            'quarter.from': 7,
            'quarter.to': 9
        }
      },
     'monthlyTarget': {
        $elemMatch: {
           'month': 7
        }
      }
    }, {
    $set: {
        'yearlyTarget.targetAchieved': 101540.7,
        'quarterlyTarget.$.targetAchieved': 101540.7,
        'monthlyTarget.$.targetAchieved': 101540.7
    }
}, (err, updatedTargetRes) => {
      if (err) {
         console.log("error in updating targetsAchieved " + err);
      } else if (updatedTargetRes != null && updatedTargetRes != '') {
         console.log(updatedTargetRes + " :updatedTargetRes");
      } else {
         console.log("target not updated");
      }
})

更新前的文档

{
    "_id": ObjectId("5cc6d6151b74b719acd36eaf"),
    "quarterlyTarget": [
        {
            "quarter": {
                "from": 4,
                "to": 6
            },
            "target": 47000,
            "targetAchieved": 0
        },
        {
            "quarter": {
                "from": 7,
                "to": 9
            },
            "target": 51200,
            "targetAchieved": 0
        },
        {
            "quarter": {
                "from": 10,
                "to": 12
            },
            "target": 64000,
            "targetAchieved": 0
        },
        {
            "quarter": {
                "from": 1,
                "to": 3
            },
            "target": 35000,
            "targetAchieved": 0
        }
    ],
    "monthlyTarget": [
        {
            "month": 1,
            "target": 10000,
            "targetAchieved": 0
        },
        {
            "month": 2,
            "target": 10000,
            "targetAchieved": 0
        },
        {
            "month": 3,
            "target": 15000,
            "targetAchieved": 0
        },
        {
            "month": 4,
            "target": 15500,
            "targetAchieved": 0
        },
        {
            "month": 5,
            "target": 15500,
            "targetAchieved": 0
        },
        {
            "month": 6,
            "target": 16000,
            "targetAchieved": 0
        },
        {
            "month": 7,
            "target": 16200,
            "targetAchieved": 0
        },
        {
            "month": 8,
            "target": 17000,
            "targetAchieved": 0
        },
        {
            "month": 9,
            "target": 18000,
            "targetAchieved": 0
        },
        {
            "month": 10,
            "target": 19000,
            "targetAchieved": 0
        },
        {
            "month": 11,
            "target": 20000,
            "targetAchieved": 0
        },
        {
            "month": 12,
            "target": 19000,
            "targetAchieved": 0
        }
    ],
    "franchiseeId": "5c42bd6085edaa215cba5a21",
    "yearlyTarget": {
        "year": 2019,
        "target": 197200,
        "targetAchieved": 0
    },
    "offer": null,
    "status": "1",
    "createdAt": ISODate("2019-04-29T10:46:45.643Z"),
    "__v": 0
}

更新后的文档

{
    "_id": ObjectId("5cc6d6151b74b719acd36eaf"),
    "quarterlyTarget": [
        {
            "quarter": {
                "from": 4,
                "to": 6
            },
            "target": 47000,
            "targetAchieved": 0
        },
        {
            "quarter": {
                "from": 7,
                "to": 9
            },
            "target": 51200,
            "targetAchieved": 101540.7 //updates successfully
        },
        {
            "quarter": {
                "from": 10,
                "to": 12
            },
            "target": 64000,
            "targetAchieved": 0
        },
        {
            "quarter": {
                "from": 1,
                "to": 3
            },
            "target": 35000,
            "targetAchieved": 0
        }
    ],
    "monthlyTarget": [
        {
            "month": 1,
            "target": 10000,
            "targetAchieved": 0
        },
        {
            "month": 2,
            "target": 10000,
            "targetAchieved": 101540.7 //updates here, which is wrong
        },
        {
            "month": 3,
            "target": 15000,
            "targetAchieved": 0
        },
        {
            "month": 4,
            "target": 15500,
            "targetAchieved": 0
        },
        {
            "month": 5,
            "target": 15500,
            "targetAchieved": 0
        },
        {
            "month": 6,
            "target": 16000,
            "targetAchieved": 0
        },
        {
            "month": 7,
            "target": 16200,
            "targetAchieved": 0 //must update the value 101540.7 here
        },
        {
            "month": 8,
            "target": 17000,
            "targetAchieved": 0
        },
        {
            "month": 9,
            "target": 18000,
            "targetAchieved": 0
        },
        {
            "month": 10,
            "target": 19000,
            "targetAchieved": 0
        },
        {
            "month": 11,
            "target": 20000,
            "targetAchieved": 0
        },
        {
            "month": 12,
            "target": 19000,
            "targetAchieved": 0
        }
    ],
    "franchiseeId": "5c42bd6085edaa215cba5a21",
    "yearlyTarget": {
        "year": 2019,
        "target": 197200,
        "targetAchieved": 101540.7
    },
    "offer": null,
    "status": "1",
    "createdAt": ISODate("2019-04-29T10:46:45.643Z"),
    "__v": 0
}

它采用第一个匹配项的索引,即 quarterlyTarget 数组的 1 并将其应用于 monthlyTarget 数组,而不是根据我指定的条件获取索引。因此更新了 monthlyTarget 数组的错误索引。

我知道这可以使用arrayFilters 来实现,我也做到了。但是我使用的mongodb版本是3.2,很遗憾无法升级,所以需要使用3.2支持的方法。

【问题讨论】:

    标签: arrays node.js mongodb updates


    【解决方案1】:
    viewmultiplrarrayupdate: (callback) => {
        maultipleArrayUpdate.findOneAndUpdate({
          "franchiseeId": '5c42bd6085edaa215cba5a21',
          'yearlyTarget.year': 2019,
          'quarterlyTarget': {
            $elemMatch: {
              'quarter.from': 7,
              'quarter.to': 9
            }
          }
        },
          {
            $set: {
              'yearlyTarget.targetAchieved': 101540.7,
              'quarterlyTarget.$.targetAchieved': 101540.7,
            }
          }
          , (err, updatedTargetResponse) => {
            if (err) {
              callback(err, null)
            }
            else {
              maultipleArrayUpdate.findOneAndUpdate({
                "franchiseeId": '5c42bd6085edaa215cba5a21',
                'yearlyTarget.year': 2019,
                'monthlyTarget': {
                  $elemMatch: {
                    'month': 7
                  }
                }
              }, { 'monthlyTarget.$.targetAchieved': 101540.7 }, (error, updatedTargetRes) => {
                if (error) {
                  callback(error, null)
                }
                else {
                  callback(null, "successfully updated")
                }
              })
            }
          })
      },
    

    【讨论】:

    • 可能这不是最聪明的方法,但却是避免索引问题达到预期结果的最简单方法
    • 尝试使用 $and 进行查找查询(将确保所有条件都必须满足提取文档的条件),而不是使用 findAndUpdate 尝试仅使用 update 而不使用 @987654325 @
    • @SouravDe 我确实这样做了,因为这是我发现工作的唯一方法。
    • @JBone 我已经尝试过使用$and,但没有成功。如果我只使用更新它会给我警告,因为我正在使用猫鼬。
    【解决方案2】:

    好的,你错过了{upsert:true}

    我在 Mongo Editor 上运行了这个查询,它工作正常。让我知道这是否适合您(也知道我只使用了部分查找查询,因为只有一个文档。您可以继续使用完整的查找块。我的重点是更新文档)

    db.user_test.findOneAndUpdate(
    
        {franchiseeId: "5c42bd6085edaa215cba5a21", "yearlyTarget.year":2019, "quarterlyTarget": {
            $elemMatch: {
                "quarter.from": 7,
                "quarter.to": 9
            }
          }},
    
          {
        $set: {
            'yearlyTarget.targetAchieved': 101540.7,
            'quarterlyTarget.$.targetAchieved': 101540.7,
            'monthlyTarget.$.targetAchieved': 101540.7
        }
    }, 
    
    {upsert:true})
    

    这是我更新后返回的文档

    {
        "_id" : ObjectId("5d1a1212a9eea913c2b8229a"),
        "quarterlyTarget" : [
            {
                "quarter" : {
                    "from" : 4,
                    "to" : 6
                },
                "target" : 47000,
                "targetAchieved" : 0
            },
            {
                "quarter" : {
                    "from" : 7,
                    "to" : 9
                },
                "target" : 51200,
                "targetAchieved" : 101540.7
            },
            {
                "quarter" : {
                    "from" : 10,
                    "to" : 12
                },
                "target" : 64000,
                "targetAchieved" : 0
            },
            {
                "quarter" : {
                    "from" : 1,
                    "to" : 3
                },
                "target" : 35000,
                "targetAchieved" : 0
            }
        ],
        "monthlyTarget" : [
            {
                "month" : 1,
                "target" : 10000,
                "targetAchieved" : 0
            },
            {
                "month" : 2,
                "target" : 10000,
                "targetAchieved" : 101540.7
            },
            {
                "month" : 3,
                "target" : 15000,
                "targetAchieved" : 0
            },
            {
                "month" : 4,
                "target" : 15500,
                "targetAchieved" : 0
            },
            {
                "month" : 5,
                "target" : 15500,
                "targetAchieved" : 0
            },
            {
                "month" : 6,
                "target" : 16000,
                "targetAchieved" : 0
            },
            {
                "month" : 7,
                "target" : 16200,
                "targetAchieved" : 0
            },
            {
                "month" : 8,
                "target" : 17000,
                "targetAchieved" : 0
            },
            {
                "month" : 9,
                "target" : 18000,
                "targetAchieved" : 0
            },
            {
                "month" : 10,
                "target" : 19000,
                "targetAchieved" : 0
            },
            {
                "month" : 11,
                "target" : 20000,
                "targetAchieved" : 0
            },
            {
                "month" : 12,
                "target" : 19000,
                "targetAchieved" : 0
            }
        ],
        "franchiseeId" : "5c42bd6085edaa215cba5a21",
        "yearlyTarget" : {
            "year" : 2019,
            "target" : 197200,
            "targetAchieved" : 101540.7
        },
        "offer" : null,
        "status" : "1",
        "createdAt" : ISODate("2019-04-29T06:46:45.643-04:00"),
        "__v" : 0
    }
    

    【讨论】:

    • 这也适用于我,但您错过了我在查询中给出的第二个 $elemMatch 条件。我的问题是每月目标应该更新为当前月份7,而是更新2,因为它采用quarterlyTarget 数组的第一个$elemMatch 的第一个匹配条件的索引。另外我不想插入新数据,我只想更新现有数据,这就是我没有使用{upsert : true}的原因
    猜你喜欢
    • 2018-12-23
    • 2015-08-30
    • 2018-12-14
    • 2020-06-06
    • 2021-01-24
    • 2011-12-19
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多