问题描述
我有一个用于存储课程详细信息的以下索引(为简洁起见,我已将某些属性删节了):
{
"settings": {
"index": {
"number_of_replicas": "1","number_of_shards": "1"
}
},"aliases": {
"course": {
}
},"mappings": {
"properties": {
"name": {
"type": "text"
},"id": {
"type": "integer"
},"max_per_user": {
"type": "integer"
}
}
}
}
此处max_per_user是用户可以完成课程的次数。允许用户多次通过一门课程,但最多不能超过max_per_user 我想跟踪用户与课程的互动。我创建了以下索引来跟踪交互事件。 event_type_id代表互动类型
{
"settings": {
"index": {
"number_of_replicas": "1","aliases": {
"course_events": {
}
},"mappings": {
"properties": {
"user_progress": {
"dynamic": "true","properties": {
"current_count": {
"type": "integer"
},"user_id": {
"type": "integer"
},"events": {
"dynamic": "true","properties": {
"event_type_id": {
"type": "integer"
},"event_timestamp": {
"type": "date","format": "strict_date_time"
}
}
}
}
},"created_at": {
"type": "date","format": "strict_date_time"
},"course_id": {
"type": "integer"
}
}
}
}
现在,当我对课程索引进行搜索时,我还希望能够传递user_id并仅获取那些给定用户的current_count小于课程的max_per_user的课程
我对课程索引的搜索查询是这样的(为简洁起见,一些过滤器被删节了)。当用户搜索课程时会执行此查询,因此基本上在执行此查询时我将拥有user_id。
{
"sort": [
{
"id": "desc"
}
],"query": {
"bool": {
"filter": [
{
"range": {
"end_date": {
"gte": "2020-09-28T12:27:55.884Z"
}
}
},{
"range": {
"start_date": {
"lte": "2020-09-28T12:27:55.884Z"
}
}
}
],"must": [
{
"term": {
"is_active": true
}
}
]
}
}
}
我不确定如何构造搜索查询,以便能够过滤出针对给定user_id已达到max_per_user的课程。
解决方法
如果我正确理解了这个问题,那么您想查找不超过max_per_user限制的课程。我的回答是基于相同的:
考虑您当前的架构方法以查找所需内容:
- 对于给定的user_id,找到所有course_id及其对应的完成计数
- 使用#1中获取的数据找出不超过max_per_user限制的课程。
现在是问题所在:
- 在关系数据库中,可以使用表连接和检查来解决这种用例
- 弹性搜索不支持联接,因此无法在此处完成。
当前架构的解决方案较差:
- 对于每门课程,请检查其是否适用。对于n个课程,对E.S的查询数量将与N成正比。
使用当前架构的解决方案:
-
在“用户课程完成索引”(您提到的第二个索引)中,还跟踪max_per_user并使用如下所示的简单查询来获取所需的课程ID:
{ "size": 10,"query": { "script": { "script": "doc['current_usage'].value<doc['max_per_user'].value && doc['u_id'].value==1" // <======= 1 is the user_id here } } }