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","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限制的课程。我的回答是基于相同的:

考虑您当前的架构方法以查找所需内容:

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

现在是问题所在

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

当前架构的解决方案较差:

  1. 对于每门课程,请检查其是否适用。对于n个课程,对E.S的查询数量将与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
    }
    }
    }
    

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...