首页 > 解决方案 > 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 的课程。

标签: elasticsearchelasticsearch-dsl

解决方案


如果我正确理解了这个问题,您想找到不超过 max_per_user 限制的课程。我的回答是基于相同的:

考虑到您当前的 Schema 查找所需内容的方法是:

  1. 对于给定的 user_id,找到所有 course_id 及其相应的完成计数
  2. 使用 #1 中获取的数据找出未超过 max_per_user 限制的课程。

现在问题来了

  1. 在关系数据库中,这种用例可以使用表连接和检查来解决
  2. Elastic Search 不支持连接,因此无法在此处完成。

当前架构的不良解决方案:

  1. 对于每门课程,检查它是否适用。对于 n 门课程,对 ES 的查询数将与 N 成正比。

当前架构的解决方案:

  1. 在用户课程完成索引(您提到的第二个索引)中,跟踪 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
    }
    }
    }
    

推荐阅读