假设您拥有普通会员和高级会员资格的电影订阅服务。
以下是用户活动生成的数据样本,并作为文档存储在集合中:
[
{
"eventType": "sessionInfo",
"userType": "premium",
"sessionGroupID": 1
},
{
"eventType": "mediaPlay",
"productSKU": "starwars",
"sessionGroupID": 1,
"elapsed": 200
},
{
"eventType": "sessionInfo",
"userType": "premium",
"sessionGroupID": 2
},
{
"eventType": "mediaPlay",
"productSKU": "xmen",
"sessionGroupID": 2,
"elapsed": 500
},
{
"eventType": "sessionInfo",
"userType": "normal",
"sessionGroupID": 3
},
{
"eventType": "mediaPlay",
"productSKU": "xmen",
"sessionGroupID": 3,
"elapsed": 10
},
{
"eventType": "sessionInfo",
"userType": "normal",
"sessionGroupID": 4
},
{
"eventType": "mediaPlay",
"productSKU": "xmen",
"sessionGroupID": 4,
"elapsed": 100
},
{
"eventType": "sessionInfo",
"userType": "normal",
"sessionGroupID": 5
},
{
"eventType": "mediaPlay",
"productSKU": "xmen",
"sessionGroupID": 5,
"elapsed": 5
},
{
"eventType": "mediaPlay",
"productSKU": "starwars",
"sessionGroupID": 5,
"elapsed": 25
}
]
您可以看到有两个“eventTypes”:
“sessionInfo”文档,包含整个公共信息 用户会话
“mediaPlay”文件,用于存储多少秒 电影被观看了。
(每个“mediaPlay”事件都包含sessionGroupID,因此它可以与该会话相关联。)
鉴于总共有数千万份文件,您如何编写一个总计每部电影的已用观看时间的查询,按用户类型分组?
所需的查询结果:
premium users - total of "elapsed":
xmen: 500
starwars: 200
normal users - total of "elapsed":
xmen: 115
starwars: 25
如果数据没有针对此类查询进行最佳结构化,那么理想的结构是什么?
喜欢这个吗?
[
{
"eventType": "sessionInfo",
"userType": "premium",
"sessionGroupID": 1,
"viewLog": [
{
"eventType": "mediaPlay",
"productSKU": "starwars",
"sessionGroupID": 1,
"elapsed": 200
}
]
},
{
"eventType": "sessionInfo",
"userType": "premium",
"sessionGroupID": 2,
"viewLog": [
{
"eventType": "mediaPlay",
"productSKU": "xmen",
"sessionGroupID": 2,
"elapsed": 500
}
]
},
{
"eventType": "sessionInfo",
"userType": "normal",
"sessionGroupID": 3,
"viewLog": [
{
"eventType": "mediaPlay",
"productSKU": "xmen",
"sessionGroupID": 3,
"elapsed": 10
}
]
},
{
"eventType": "sessionInfo",
"userType": "normal",
"sessionGroupID": 4,
"viewLog": [
{
"eventType": "mediaPlay",
"productSKU": "xmen",
"sessionGroupID": 4,
"elapsed": 100
}
]
},
{
"eventType": "sessionInfo",
"userType": "normal",
"sessionGroupID": 5,
"viewLog": [
{
"eventType": "mediaPlay",
"productSKU": "xmen",
"sessionGroupID": 5,
"elapsed": 5
},
{
"eventType": "mediaPlay",
"productSKU": "starwars",
"sessionGroupID": 5,
"elapsed": 25
}
]
}
]
感谢您提供任何指导和建议!
答案 0 :(得分:2)
以下查询迭代集合并收集按userTypes分组的所有会话ID。然后它创建一个子查询,它遍历集合并收集所有电影以及eventType
为“mediaPlay”且收集的会话包含sessionGroupID
的已用时间总和。
@@coll
是bind parameter,其中包含您的收藏名称。
FOR doc IN @@coll
FILTER doc.eventType == "sessionInfo"
COLLECT userTypes = doc.userType INTO sessions = doc.sessionGroupID
RETURN {
"userTypes" : userTypes,
"movies" : (
FOR event IN @@coll
FILTER event.sessionGroupID IN sessions
FILTER event.eventType == "mediaPlay"
COLLECT movie = event.productSKU INTO elapsed = event.elapsed
RETURN { "movie" : movie, "elapsed" : SUM(elapsed) }
)
}
此查询的结果是:
[
{
"userTypes": "normal",
"movies": [
{
"movie": "starwars",
"elapsed": 25
},
{
"movie": "xmen",
"elapsed": 115
}
]
},
{
"userTypes": "premium",
"movies": [
{
"movie": "starwars",
"elapsed": 200
},
{
"movie": "xmen",
"elapsed": 500
}
]
}
]
关于你的第二个问题。嵌套数组/对象不会优化此查询,但您应该将数据拆分为两个集合。每个eventType
一个(例如,将事件命名为eventType sessionInfo
和mediaPlay
)。这减少了所需过滤器语句的数量,更重要的是,它允许您通过sessionInfos和mediaPlay单独查询,从而大大提高您的性能。
查询将如下所示:
FOR doc IN sessionInfo
COLLECT userTypes = doc.userType INTO sessions = doc.sessionGroupID
RETURN {
"userTypes" : userTypes,
"movies" : (
FOR event IN mediaPlay
FILTER event.sessionGroupID IN sessions
COLLECT movie = event.productSKU INTO elapsed = event.elapsed
RETURN { "movie" : movie, "elapsed" : SUM(elapsed) }
)
}