【问题标题】:MongoDB: Update outer array and nested arrays in single updateMongoDB:在单个更新中更新外部数组和嵌套数组
【发布时间】:2020-07-08 22:04:36
【问题描述】:

cities集合中的文档结构是这样的

城市

  {
   _id:  ObjectId("5e78ec62bb5b406776e92fac"),
   city_name: "Mumbai",
   ...
   ...
   subscriptions: [
    {
       _id: 1,
       category: "Print Magazine",
       subscribers: 183476
       options: [
         {
            name: "Time",
            subscribers: 56445
         },
         {
            name: "The Gentlewoman",
            subscribers: 9454
         },
         {
            name: "Gourmand",
            subscribers: 15564
         }
         ...
         ...
       ]
     },
     {
       _id: 2,
       category: "RSS Feed",
       subscribers: 2645873
       options: [
         {
            name: "Finance",
            subscribers: 168465
         },
         {
            name: "Politics",
            subscribers: 56945
         },
         {
            name: "Entrepreneurship",
            subscribers: 56945
         },
         ...
         ...
       ]
     }
   ]
}

现在当用户像下面这样订阅时

{
  cityId: 5e78ec62bb5b406776e92fac
  selections: [
    {
      categoryId: 1,
      options : ["Time", "Gourmand"]
    }, 
    {
      categoryId: 2, 
      selected: ["Politics", "Entrepreneurship"]
    }    
  ]
}

我想更新cities文档中的以下内容

  • 将“印刷杂志”的订阅者增加 1
    • 将“时间”的订阅者增加 1
    • 将“美食家”的订阅人数增加 1
  • 将“RSS Feed”的订阅者增加 1
    • 将“政治”的订阅者增加 1
    • “创业”的订阅人数增加 1

所以当一个item被订阅时,它的订阅数加1。它所属的类别,它的订阅数也加1。

我想在单个更新查询中实现这一点。任何提示我该怎么做?

用例详情

每个用户的订阅详情都存储在user_subscription_details 集合中(此处未列出)。 cities 中的 subscriptions 属性仅包含每个城市的订阅摘要。

【问题讨论】:

  • 用户订阅 数据是 JSON(不是集合文档)?可能会使用聚合进行更新。
  • @prasad_这有关系吗?因为我需要更新文档的一部分而不是整个文档。
  • 您想根据user subscribes 更新city_subscriptions?
  • @Valijon 是的。每个文档代表一个城市及其订阅。
  • user suscribers 是否存储在单独的集合中?我们需要以$out 作为最后阶段执行聚合以覆盖整个集合(由 prasad_ 说)

标签: mongodb spring-boot nosql mongodb-update


【解决方案1】:

所以我可以通过以下查询来实现它

db.cities.updateOne(
{
   _id : ObjectId("5e78ec62bb5b406776e92fac")
},
{ 
   $inc: { 
     "subscriptions.$[category].subscribers" : 1,
     "subscriptions.$[category].options.$[option].subscribers" : 1
   }
},
{ multi: true,
   arrayFilters: [
     { "category._id": {$in: ["1", "2"]} },
     { "option.name": {$in: ["Time", "Gourmand", "Politics", "Entrepreneurship"]} } 
   ]
}
)

简要说明

  • 首先文档与_id匹配。
  • 在更新块中,我们将声明要更新的字段
    • "subscriptions.$[?].subscribers" : 1,
    • "subscriptions.$[?].options.$[?].subscribers" : 1

我在这里使用了? 来表明我们还不知道我们需要对数组中的哪些元素进行这些更新。我们可以通过过滤需要更新的数组元素在下一个块中声明。

  • 在过滤器块中,我们在某些条件下过滤数组元素
    • { "category._id": {$in: ["1", "2"]} }
    • { "option.name": {$in: ["Time", "Gourmand", "Politics", "Entrepreneurship"]} }

首先,我们通过_id 过滤外部数组中的元素,即仅_id 为1 或2 的订阅类别。 接下来,我们在name 字段上过滤内部options 数组中的元素。将通过两个过滤器的元素将得到更新。

注意:category._id 中的 category 和 option.name 中的 option 可以是任何名称。但是更新块中的字段路径要使用相同的名称。

对于这个查询的 Spring Boot MongoOperation 翻译看这个answer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-26
    • 2020-10-22
    • 2017-09-11
    • 2019-12-07
    • 1970-01-01
    • 2011-05-06
    相关资源
    最近更新 更多