弹性搜索动态字段映射与价格字段的范围查询



我的弹性搜索中有两个字段,分别是lowest_local_pricelowest_global_price

我想在运行时将动态值映射到第三个字段price基于本地或全球国家

如果当地国家匹配,那么我想将lowest_local_price值映射到价格字段。

如果全球国家匹配,那么我想将lowest_global_price值映射到价格字段。

如果本地或全球国家/地区匹配,则我想在价格字段上应用范围查询,并将该文档提升2.0

注意:这不是强制过滤或查询,如果匹配,则只想提升单据。

我已经尝试了以下解决方案,但对我不起作用。

查询1:

$params["body"] = [
"runtime_mappings" => [
"price" => [
"type" => "double",
"script" => [
"source" => "if (params['_source']['country_en_name'] == '$country_name' ) { emit(params['_source']['lowest_local_price']); } else { emit( params['_source']['global_rates']['$country->id']['lowest_global_price']); }"
]
]
],
"query" => [
"bool" => [
"filter" => [
"range" => [ "price" => [ "gte" => $min_price]]
],
"boost" => 2.0
]
]
];

查询2:

$params["body"] = [
"runtime_mappings" => [
"price" => [
"type" => "double",
"script" => [
"source" => "if (params['_source']['country_en_name'] == '$country_name' ) { emit(params['_source']['lowest_local_price']); } else { emit( params['_source']['global_rates']['$country->id']['lowest_global_price']); }"
]
]
],
"query" => [
"bool" => [
"filter" => [
"range" => [ "price" => [ "gte" => $min_price, "boost" => 2.0]]
],

]
]
];

他们都不为我工作,因为这可以提高医生的士气。我知道filter不适用于boost,那么使用范围查询和boost的动态字段映射的解决方案是什么?

请帮我解决这个问题。

提前谢谢!

您可以(很可能(通过使用bool查询的组合在没有runtime_mappings的情况下实现您想要的,方法如下。

让我们定义测试映射

我们需要澄清我们正在使用的映射,因为不同的字段类型需要不同的查询类型。

让我们假设您的映射如下:

PUT my-index-000001
{
"mappings": {
"dynamic": "runtime",
"properties": {
"country_en_name": {
"type": "text"
},
"lowest_local_price": {
"type": "float"
},
"global_rates": {
"properties": {
"UK": {
"properties":{
"lowest_global_price": {
"type": "float"
}
}
},
"FR": {
"properties":{
"lowest_global_price": {
"type": "float"
}
}
},
"US": {
"properties":{
"lowest_global_price": {
"type": "float"
}
}
}
}
}
}
}
}

注意,country_en_name的类型为text,通常情况下,这些字段应被索引为keyword,但为了演示runtime_mappings的使用,我将其保留为text,并将在稍后展示如何克服这一限制。

对于Elasticsearch,boolif相同

没有运行时映射的查询可能如下所示:

POST my-index-000001/_search
{
"query": {
"bool": {
"should": [
{
"match_all": {}
},
{
"bool": {
"should": [
{
"bool": {
"must": [
{
"match": {
"country_en_name": "UK"
}
},
{
"range": {
"lowest_local_price": {
"gte": 1000
}
}
}
]
}
},
{
"range": {
"global_rates.UK.lowest_global_price": {
"gte": 1000
}
}
}
],
"boost": 2
}
}
]
}
}
}

这可以解释为:

Any document
OR (
(document with country_en_name=UK AND lowest_local_price > X)
OR
(document with global_rates.UK.lowest_global_price > X)
)[boost this part of OR]

match_all还需要返回与其他查询不匹配的文档。

查询的响应会是什么样子

让我们把一些文件放在ES:中

POST my-index-000001/_doc/1
{
"country_en_name": "UK",
"lowest_local_price": 1500,
"global_rates": {
"FR": {
"lowest_global_price": 1000
},
"US": {
"lowest_global_price": 1200
}
}
}
POST my-index-000001/_doc/2
{
"country_en_name": "FR",
"lowest_local_price": 900,
"global_rates": {
"UK": {
"lowest_global_price": 950
},
"US": {
"lowest_global_price": 1500
}
}
}
POST my-index-000001/_doc/3
{
"country_en_name": "US",
"lowest_local_price": 950,
"global_rates": {
"UK": {
"lowest_global_price": 1100
},
"FR": {
"lowest_global_price": 1000
}
}
}

现在,上面搜索查询的结果将类似于:

{
...
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 4.9616585,
"hits" : [
{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "1",
"_score" : 4.9616585,
"_source" : {
"country_en_name" : "UK",
"lowest_local_price" : 1500,
...
}
},
{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "3",
"_score" : 3.0,
"_source" : {
"country_en_name" : "US",
"lowest_local_price" : 950,
"global_rates" : {
"UK" : {
"lowest_global_price" : 1100
},
...
}
}
},
{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"country_en_name" : "FR",
"lowest_local_price" : 900,
"global_rates" : {
"UK" : {
"lowest_global_price" : 950
},
...
}
}
}
]
}
}

请注意,带有_id:2的文档位于底部,因为它与任何增强的查询都不匹配。

runtime_mappings有用吗

如果现有映射的数据类型不允许执行特定类型的查询,则运行时映射非常有用。在以前的版本(7.11之前(中,在这种情况下必须重新索引,但现在可以使用运行时映射(但查询更昂贵(。

在我们的案例中,我们将country_en_name索引为text,这适用于全文搜索,而不适用于精确查找。我们应该改为使用keyword。这就是在runtime_mappings:的帮助下查询的样子

POST my-index-000001/_search
{
"runtime_mappings": {
"country_en_name_keyword": {
"type": "keyword",
"script": {
"source": "emit(params['_source']['country_en_name'])"
}
}
},
"query": {
"bool": {
"should": [
{
"match_all": {}
},
{
"bool": {
"should": [
{
"bool": {
"must": [
{
"term": {
"country_en_name_keyword": "UK"
}
},
{
"range": {
"lowest_local_price": {
"gte": 1000
}
}
}
]
}
},
{
"range": {
"global_rates.UK.lowest_global_price": {
"gte": 1000
}
}
}
],
"boost": 2
}
}
]
}
}
}

请注意,我们创建了一个类型为keyword的新运行时字段country_en_name_keyword,并使用了term查找而不是match查询。

相关内容

  • 没有找到相关文章

最新更新