问题:
我正在尝试获取一份文档列表,并针对每个文档来计算同一文档的嵌套数组中给定值出现的次数。
我有一个使用聚合框架的有效示例,但是我想知道是否有更好的方法可以完成同一件事,因此我可以对不同的方法进行基准测试。
简化的数据模型:
“ 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
数组,则当前解决方案将引发错误。有办法解决吗?
非常感谢您花费大量时间阅读这篇长文章!
答案 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});