如何将这个mongodb多更新查询减少到一个涉及嵌套数组的查询?

vnzz0bqm  于 2023-03-29  发布在  Go
关注(0)|答案(2)|浏览(102)

模式:

{
   img: // array of minimum length 1 of ObjectIds or field is "missing" to indicate that array is empty
   tar: [
     { img:  // array of minimum length 1 of ObjectIds or field is "missing" to indicate that array is empty },
     { img:  // array of minimum length 1 of ObjectIds or field is "missing" to indicate that array is empty },
     ... 
   ]
}

这是我删除照片的查询,它是顶级img数组中的ObjectId,并且可能在某些tar子文档的img字段中:

await mongo_tran_ses.withTransaction(async () => {
        // pulling the ObjectId matching `req.params._id` from `img`, and all `tar.img`
        await user.updateOne(
          { _id: ObjectId(req.user._id) },
          {
            $pull: {
              img: { _id: { $eq: ObjectId(req.params._id) } },
              "tar.$[].img": { $eq: ObjectId(req.params._id) },
            },
          },
          { session: mongo_tran_ses }
        );
        // removing all `tar.img` if it is now an empty array 
        await user.updateOne(
          {
            _id: ObjectId(req.user._id),
          },
          {
            $unset: {
              "tar.$[element].img": "",
            },
          },
          {
            arrayFilters: [{ "element.img": { $size: 0 } }],
            session: mongo_tran_ses,
          }
        );
        // removing `img` if it is now an empty array 
        await user.updateOne(
          {
            _id: ObjectId(req.user._id),
            img: { $size: 0 },
          },
          {
            $unset: {
              img: undefined,
            },
          },
          {
            session: mongo_tran_ses,
          }
        );
      }, tran_option);

目标:
只使用一个update查询而不是上面的3个查询来执行上面的操作。

iklwldmw

iklwldmw1#

这是如何在mongo shell 4.2+中完成的:

db.collection.update({},
[
{
// remove element img.tar.img:2
$addFields: {
  img: {
    "$map": {
      "input": "$img",
      "as": "i",
      "in": {
        "$mergeObjects": [
          "$$i",
          {
            tar: {
              "$map": {
                "input": "$$i.tar",
                "as": "t",
                "in": {
                  "$mergeObjects": [
                    "$$t",
                    {
                      "img": {
                        "$filter": {
                          "input": "$$t.img",
                          "as": "i2",
                          "cond": {
                            $ne: [
                              "$$i2",
                              2
                            ]
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        ]
      }
    }
   }
  }
  },
  {
   // remove empty img:[] + empty {} under img.tar[]
 $addFields: {
  img: {
    "$map": {
      "input": "$img",
      "as": "i",
      "in": {
        "$mergeObjects": [
          "$$i",
          {
            tar: {
              $filter: {
                input: {
                  "$map": {
                    "input": "$$i.tar",
                    "as": "t",
                    "in": {
                      $arrayToObject: {
                        $filter: {
                          input: {
                            $objectToArray: "$$t"
                          },
                          as: "tf",
                          cond: {
                            $ne: [
                              "$$tf.v",
                              []
                            ]
                          }
                        }
                      }
                    }
                  }
                },
                as: "te",
                cond: {
                  $ne: [
                    "$$te",
                    {}
                  ]
                }
              }
            }
          }
        ]
      }
     }
     }
    }
   },
   {
   // remove img.tar:[]
   $addFields: {
   img: {
    $filter: {
      input: {
        "$map": {
          "input": "$img",
          "as": "i",
          "in": {
            $arrayToObject: {
              $filter: {
                input: {
                  $objectToArray: "$$i"
                },
                as: "tf",
                cond: {
                  $ne: [
                    "$$tf.v",
                    []
                  ]
                }
              }
            }
          }
        }
       },
       as: "te",
       cond: {
        $ne: [
          "$$te",
          {}
        ]
       }
      }
     }
    }
   },
  {
   // remove empty 1st level img:[]
  $project: {
   "img": {
    "$cond": [
      {
        $ne: [
          "$img",
          []
        ]
      },
      "$img",
      "$$REMOVE"
     ]
    }
   }
  }
  ],
  {
   multi: true
  })

解释:
1.通过$map/$filter对img.tar.img[]进行项目/AddField操作以删除元素(示例中为2)
1.要删除的项目/addFields(如果有空img.tar.img[])(如果有)
1.要删除的项目/addFields(如果有空img.tar[])(如果有)
1.要再次删除的项目/addFields空img:[](如果有)
Playground

ndh0cuux

ndh0cuux2#

Abit后来看到你的schema是不同的,这里是img[]和tar.img[]作为不同字段的选项:

db.collection.update({},
[
{
// remove 2 from img[]
"$addFields": {
  "img": {
    "$filter": {
      "input": "$img",
      "as": "i",
      "cond": {
        "$ne": [
          "$$i",
          2
        ]
      }
    }
   }
   }
 },
 {
// remove 2 from tar.img:[]
 "$addFields": {
  "tar": {
    "$map": {
      "input": "$tar",
      "as": "t",
      "in": {
        "$mergeObjects": [
          "$$t",
          {
            img: {
              "$filter": {
                "input": "$$t.img",
                "as": "ti",
                "cond": {
                  "$ne": [
                    "$$ti",
                    2
                  ]
                }
              }
            }
          }
        ]
      }
    }
   }
  }
 },
 {
 // remove empty img:[]
 "$addFields": {
  "img": {
    "$cond": {
      "if": {
        "$ne": [
          "$img",
          []
        ]
      },
      "then": "$img",
      "else": "$$REMOVE"
    }
   }
  }
 },
 {
// remove {img:[]} from tar:[]
 "$addFields": {
  "tar": {
    $filter: {
      input: {
        "$map": {
          "input": "$tar",
          "as": "t",
          "in": {
            $arrayToObject: {
              $filter: {
                input: {
                  $objectToArray: "$$t"
                },
                as: "tf",
                cond: {
                  $ne: [
                    "$$tf.v",
                    []
                  ]
                }
              }
            }
          }
        }
      },
      as: "te",
      cond: {
        $ne: [
          "$$te",
          {}
        ]
      }
    }
    }
   }
  },
 {
// remove empty tar:[]
"$addFields": {
  "tar": {
    "$cond": {
      "if": {
        "$ne": [
          "$tar",
          []
        ]
      },
      "then": "$tar",
      "else": "$$REMOVE"
    }
  }
 }
}
],
{
 multi: true
})

解释:
1.从img[]中删除id:2
1.从tar.img[]中删除id:2

  1. remove if empty img[]
  2. remove if empty tar[ {img[]} ]
  3. remove if empty tar[]
    Playground

相关问题