我在限制网络应用程序中的搜索结果总数时遇到问题。
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 查询和索引:cars 和 bikes)。
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 中验证了它