【问题标题】:Mongo updating inside a double nested arrayMongo 在双嵌套数组中更新
【发布时间】:2017-01-05 02:43:29
【问题描述】:

我有一个像这样的 mongo 集合

db.users.find().pretty()
{
    "_id" : ObjectId("57c3d5b3d364e624b4470dfb"),
    "fullname" : "tim",
    "username" : "tim",
    "email" : "tim@gmail.com",
    "password" : "$2a$10$.Z9CnK4oKrC/CujDKxT6YutohQkHbAANUoAHTXQp.73KfYWrm5dY2",
    "workout" : [
        {
            "workoutId" : "Bkb6HIWs",
            "workoutname" : "chest day",
            "BodyTarget" : "Chest",
            "date" : "Monday, August 29th, 2016, 2:27:04 AM",
            "exercises" : [
                {
                    "exerciseId" : "Bym88LZi",
                    "exercise" : "bench press",
                    "date" : "Monday, August 29th, 2016, 2:29:30 AM"
                },
                {
                    "exerciseId" : "ByU8II-s",
                    "exercise" : "flys",
                    "date" : "Monday, August 29th, 2016, 2:29:34 AM"
                }
            ]
        },
        {
            "workoutId" : "Bk_TrI-o",
            "workoutname" : "Back day",
            "BodyTarget" : "Back",
            "date" : "Monday, August 29th, 2016, 2:27:12 AM"
        }
    ]
}

所以我最终希望它看起来像这样

db.users.find().pretty()
{
    "_id" : ObjectId("57c3d5b3d364e624b4470dfb"),`enter code here`
    "fullname" : "tim",
    "username" : "tim",
    "email" : "tim@gmail.com",
    "password" : "$2a$10$.Z9CnK4oKrC/CujDKxT6YutohQkHbAANUoAHTXQp.73KfYWrm5dY2",
    "workout" : [
        {
            "workoutId" : "Bkb6HIWs",
            "workoutname" : "chest day",
            "BodyTarget" : "Chest",
            "date" : "Monday, August 29th, 2016, 2:27:04 AM",
            "exercises" : [
                {
                    "exerciseId" : "Bym88LZi",
                    "exercise" : "bench press",
                    "date" : "Monday, August 29th, 2016, 2:29:30 AM",
                    "stats" : [
                          {
                            "reps: '5',
                            "weight":'105'
                          }
                },
                {
                    "exerciseId" : "ByU8II-s",
                    "exercise" : "flys",
                    "date" : "Monday, August 29th, 2016, 2:29:34 AM"
                }
            ]
        },
        {
            "workoutId" : "Bk_TrI-o",
            "workoutname" : "Back day",
            "BodyTarget" : "Back",
            "date" : "Monday, August 29th, 2016, 2:27:12 AM"
        }
    ]
}

我想将 stats 数组添加到当前的运动数组中。我在使用双嵌套数组的点符号时遇到问题

我试过了

db.users.update({
  'email': 'jeffreyyourman@gmail.com', "workout.workoutId": "Bkb6HIWs" ,"workout.exercises.exerciseId":"ByU8II-s"
},
{
  $push: {
          "workout.0.exercises.$.stats": {"sets":"sets", "reps":"reps"}}})

这确实有效,但总是会推送到第一个嵌套练习对象。

现在如果我这样做......

db.users.update({
  'email': 'jeffreyyourman@gmail.com', "workout.workoutId": "Bkb6HIWs" ,"workout.exercises.exerciseId":"ByU8II-s"
},
{
  $push: {
          "workout.0.exercises.1.stats": {"sets":"sets", "reps":"reps"}}})

并用 1 替换 $ 它将推送到第二个练习数组,这显然是我想要的。但是我正在建立一个网站,所以我显然无法对其进行硬编码。我需要使用 $ 但它似乎并没有超过第一个练习对象。

任何帮助我将不胜感激!

【问题讨论】:

  • $ 表示第一个。 mongo 应该如何知道要更新哪个索引?查询只是说明要查找的内容。我认为您需要找到文档,在服务器中更新并保存。
  • 如果锻炼次数无限制地增长,您可能需要重新考虑架构设计,因为文档在某个时间点可能会超过 16MB 的大小限制。

标签: node.js mongodb multidimensional-array


【解决方案1】:

现在 (MongoDB >=3.6) 可以使用 arrayFilters$[identifier] 来实现此目的。

下面的示例使用猫鼬并将一个项目添加到双嵌套数组内的数组中。一篇很好的文章解释了这一点是here

  const blogPost = await BlogPost.create({
    title    : 'A Node.js Perspective on MongoDB 3.6: Array Filters',
    comments : [
      { author : 'Foo', text : 'This is awesome!', replies : { name : 'George', seenBy : ['Pacey'] } },
      { author : 'Bar', text : 'Where are the upgrade docs?', replies : { name : 'John', seenBy : ['Jenny'] } }
    ]
  });

  const updatedPost = await BlogPost.findOneAndUpdate({ _id : blogPost._id }, {
    $addToSet : {
      'comments.$[comment].replies.$[reply].seenBy' : 'Jenny'
    }
  }, {
    arrayFilters : [{ 'comment.author' : 'Foo' }, { 'reply.name' : 'George' }],
    new          : true
  });

  console.log(updatedPost.comments[0].replies);

【讨论】:

    【解决方案2】:
    db.users.update({
      'email': 'jeffreyyourman@gmail.com', 
      "workout.workoutId": "Bkb6HIWs",
      "workout.exercises.exerciseId":"ByU8II-s"
    },
    

    此查询部分返回第一个匹配对象,它是整个用户资料而不是练习条目。因此,您只需指定电子邮件即可获取相同的对象。 “workoutId”和“exerciseId”是多余的。

    {
      $push: {
        "workout.0.exercises.$.stats": {"sets":"sets", "reps":"reps"}
      }
    })
    

    因此,这个推送命令只会像 Amiram 在评论中所说的那样推送到运动的第一个条目。在这种情况下,您可以检索整个对象,对其进行修改,然后保存。

    但我认为您可能需要重新设计架构以获得更好的性能。也许为锻炼和锻炼制定一个模式,然后使用参考来连接它们。 http://mongoosejs.com/docs/populate.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-01
      • 1970-01-01
      • 2017-09-11
      • 2019-12-07
      • 2017-01-05
      • 1970-01-01
      • 2022-01-24
      相关资源
      最近更新 更多