MongoDB-过滤后获取具有嵌套数组大小的文档

时间:2018-10-25 10:58:27

标签: database mongodb nosql aggregation-framework

问题:

我正在尝试获取一份文档列表,并针对每个文档来计算同一文档的嵌套数组中给定值出现的次数。

我有一个使用聚合框架的有效示例,但是我想知道是否有更好的方法可以完成同一件事,因此我可以对不同的方法进行基准测试。

简化的数据模型:

“ Raffles”集合中的单个文档:

{
  "_id" : objectId,
  "name" : string,
  "ends_at" : ISODate/Timestamp,
   ...
  "subscribers" : string[] //List of user ids
}
  • 馆藏由代表抽奖/抽奖的文件组成,并带有名称和开始/结束日期。
  • 用户可以订阅抽奖。
  • 用户可以多次订阅同一抽奖活动。

95%的读取查询将需要抽奖数据,例如名称,描述和日期以及有关已订阅用户的信息。这就是为什么我决定将所有内容都放在一个抽奖文件中,而不是:在用户文档中引用已订阅的抽奖文件,或使用一个带有抽奖和订阅计数的单独集合。

也许是替代方法?:

subscribers数组是代表用户ID的字符串的列表。这种添加订户的方式就像推送新值一样简单。另一个选择是拥有一个像这样的对象数组并增加计数:

{
  "subscribers: [
     {
       "id": objectId  //User id
       "count": integer //Number of subscriptions
     },
     ...
  ]
}

预期结果:

预期结果是拥有完整的抽奖活动文档以及给定用户拥有多少订阅的附加值。

{
    "_id" : objectId,
    "name" : string,
    "ends_at" : ISODate/Timestamp,
     ...
    "subscriptions" : 3 //Number of entries for a given user
}

当前解决方案

使用给定的用户ID

过滤嵌套数组后,我得到了大小
db.raffles.aggregate([
    ...
    {
        $project: {
            "name" : 1,
            "ends_at" :1,
             ...
            "subscriptions" : {
                 $size : {
                    $filter : {
                        input: "$subscribers",
                        as: "user",
                        cond: {
                            $eq: ["$$user", <USER_ID>]
                        },
                    }
                 }
            }
        }
    }
    ...
])

问题:

  • 还有其他/更好的方法来完成当前解决方案的结果吗?也许进行分组和汇总或映射/归约?

  • 不仅值得保留用户ID,还要保留具有用户ID和订阅计数的对象吗?

  • 如果未设置subscriptions数组,则当前解决方案将引发错误。有办法解决吗?

非常感谢您花费大量时间阅读这篇长文章!

1 个答案:

答案 0 :(得分:1)

我会将用户ID和计数都保留在订阅数组中,并在与用户ID匹配时增加计数。

类似

db.Raffles.update({"subscriptions.id":userid}, {$inc:{"subscriptions.$.count":1}}})

您可以使用以下查询访问代码。

db.Raffles.find({"subscriptions.id":userid},{"name":1,"ends_at":1,"subscriptions.$":1});