elasticsearch - Elasticsearch 多索引查询
问题描述
我有一个存储课程详细信息的以下索引(为简洁起见,我截断了一些属性):
{
"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",
"number_of_shards": "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"
}
}
}
}
其中 current_count 是用户完成完整课程的次数
现在,当我对课程索引进行搜索时,我还希望能够传入 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 限制的课程。我的回答是基于相同的:
考虑到您当前的 Schema 查找所需内容的方法是:
- 对于给定的 user_id,找到所有 course_id 及其相应的完成计数
- 使用 #1 中获取的数据找出未超过 max_per_user 限制的课程。
现在问题来了:
- 在关系数据库中,这种用例可以使用表连接和检查来解决
- Elastic Search 不支持连接,因此无法在此处完成。
当前架构的不良解决方案:
- 对于每门课程,检查它是否适用。对于 n 门课程,对 ES 的查询数将与 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 } } }
推荐阅读
- firebase - 如何让 Firebase.dart 中的 updateProfile 工作?
- c - 如何使用星星作为框架和内部的破折号创建一个框架框?
- airflow - 气流任务调度独特的子任务
- javascript - .join() 函数在 map 函数中无法正常工作
- mysql - 有没有更好的方法来按部门获得最高(薪水)并确保只有你获得平均(薪水)> 50,000 的部门?
- kubernetes - 运行 `linkerd upgrade --from-manifests` 时没有类型的“APIService”注册错误
- list - 如何订购firebase的文件?
- c# - 如何将子项从 ListBox 添加到 ListView?
- python - use ValueProvider to format a BigQuery in Dataflow
- php - 联系表格 7 提交后调用 PHP 函数