使用 Pagy gem 时限制 ElasticSearch 结果

问题描述 投票:0回答:0

我在限制网络应用程序中的搜索结果总数时遇到问题。

Web 应用程序是用 Ruby 编写的,搜索功能由 ElasticSearch 提供支持,分页由 Pagy ruby gem 处理(文档位于 here)。

首先,为了给您一个大的了解,到目前为止我发现的主要问题是我用来运行和分页 ElasticSearch 查询的

pagy_elasticsearch_rails
方法。当我将
size
参数传递给查询时,它会覆盖查询的
items
参数(该参数又用于限制返回的结果总数)。我还需要使用
items
的原因是限制每页结果的数量(根据文档,这是与 Pagy 一起使用的正确参数)。
pagy_elasticsearch_rails
删除来自 ElasticSearch 查询的
size
参数,并将
items
作为
size
放置在查询中。它确实限制了每页的结果数,但它也会回落到默认的结果总数(即 10,000)。

现在,更具体地说,我有包含

search
方法的控制器文件 - 这是运行搜索的起点。 这里发生的第一件事是调用
pagy_search
方法:

@pagy_cars, cars = pagy_search(params[:query], "car")
@pagy_bikes, bikes = pagy_search(params[:query], "bike")

我调用

pagy_search
两次,因为我有两种类型的结果(以及相应的两个不同的 ElasticSearch 查询和索引:carsbikes)。
pagy_search
方法位于同一个文件中:

def pagy_search(search_term, results_type)
search_query = Matches::SearchQuery::Elasticsearch.call(search_term)
query_by_type = search_query[results_type.to_sym] # To treat car and bike queries differently
pagy_elasticsearch_rails(query_by_type, items: 24)

search_query
变量包含 Elasticsearch 调用的结果 - 特别是 elasticsearch.rb 文件,它保存构建搜索查询本身的逻辑。我还在那里设置了结果总数的限制。以下是部分内容:

module Matches
  module SearchQuery
    class Elasticsearch < Base

      def initialize(term)
        @search_term   = term
        car_query = { min_score: 0.5, query: function_score_wrapper("car"), size: 120 } # I use function_score_wrapper method here because I apply a custom function to refine _score
        bike_query = { min_score: 0.5, query: function_score_wrapper("bike"), size: 120 }
        @car_response = Car.pagy_search(car_query)
        @course_response = Bike.pagy_search(bike_query)
      end

      def results
        {
          car: @car_response,
          bike: @bike_response
        }
      end

      private

      def function_score_wrapper(type)
        {
          function_score: {
            max_boost: 1.6,
            boost_mode: "multiply",
            script_score: {
              script: {
                lang: "painless",
                source:
                  "some_custom_function_here_with_logic_based_on_type_parameter"
              }
            },
            query: general_query(type)
          }
        }
      end
    
      def general_query(type)
        {
          bool: {
            should: multi_match_queries(type),
            filter: filters(type)
          }
        }
      end

      def multi_match_queries(type)
        if type == "car"
          [
            nested_text_match_query_clause(type, nested: true)
          ]
        else
          [
            fuzzy_text_match_query_clause(type, nested: false),
            text_match_query_clause(type, nested: false),
            nested_text_match_query_clause(type, nested: true)
          ]
        end
      end

等等。 - 我认为不值得复制粘贴所有方法,因为我在这里的目的是向您展示一般性的结构。否则,请告诉我:)

如果我们打印

pagy_elasticsearch_rails(query_by_type, items: 24)
的结果,我们将得到这个结构:

[
  #<Pagy object
      pagy_object_parameters
  >,
  <Elasticsearch::Model::Response::Response object
      Car(car table fields),
      @search = #<Elasticsearch::Model::Searching::SearchRequest object
      Car(car table fields),
      @options = {},
      @definition = {search query}
      >,
  @raw_response = {search query results}
  >
]

@definition
变量中,我可以看到大小被覆盖:
:size=>24
,因此我在 elasticsearch.rb 中设置的值被
items
值替换。然后它被用来限制我也需要的每页结果的数量。

您以前遇到过类似的问题吗?您对如何绕过它有什么想法吗?

附注我使用的是pagy版本3.7.0 P.P.S 我可以确认

size
参数正确地限制了 ElasticSearch 结果,因为我在 Kibana 中验证了它

ruby elasticsearch limit pagy
© www.soinside.com 2019 - 2024. All rights reserved.