elasticsearch - ElasticSearch 多个 AND/OR 查询
问题描述
我有一个如下所示的架构 -
{
"errorCode": "e015",
"errorDescription": "Description e015",
"storeId": "71102",
"businessFunction": "PriceFeedIntegration",
"createdDate": "2021-02-20T09:17:04.004",
"readBy": [
{
"userId": "scha3055"
},
{
"userId": "abcd1234"
}
]
}
我正在尝试搜索具有如下日期范围的“errorCode”、“storeId”、“businessFunction”的组合 -
{
"query": {
"bool": {
"must": [
{
"terms": {
"errorCode": [
"e015",
"e020",
"e022"
]
}
},
{
"terms": {
"storeId": [
"71102",
"71103"
]
}
},
{
"range": {
"createdDate": {
"gte": "2021-02-16T09:17:04.000",
"lte": "2021-02-22T00:00:00.005"
}
}
}
]
}
}
}
但是,当我使用“businessFunction”添加另一个条件时,查询不起作用。
{
"query": {
"bool": {
"must": [
{
"terms": {
"errorCode": [
"e015",
"e020",
"e022"
]
}
},
{
"terms": {
"storeId": [
"71102",
"71103"
]
}
},
{
"terms": {
"errorDescription": [
"Description e020",
"71103"
]
}
},
{
"range": {
"createdDate": {
"gte": "2021-02-16T09:17:04.000",
"lte": "2021-02-22T00:00:00.005"
}
}
}
]
}
}
}
我在查询中遗漏了什么?当我添加第三个“术语” cndition 时,查询不起作用。请建议或让我知道任何替代方式。
解决方案
在您的示例中,您正在搜索“Description e020”,但在您的示例中,您存储了“Description e015 ”。
简短的回答,我希望这适合你:
"Description e015" 将被索引为两个术语 ["description","e015"]。
使用match_phrase而不是术语
...
{
"match_phrase": {
"errorDescription": "Description e015"
}
},
{
"range": {
"createdDate": {
"gte": "2021-02-16T09:17:04.000",
"lte": "2021-02-22T00:00:00.005"
}
}
}
....
在不知道您的映射的情况下,我认为您的 errorDescription 字段已被分析。
不推荐其他选项:如果您的字段已分析并且您需要完全匹配,请在 errorDescription.keyword 中搜索
{
"terms": {
"errorDescription.keyword": [
"Description e015"
]
}
}
更新
长答案:
正如我之前提到的,您的字段值已被分析,然后从“PriceFeedIntegration2”转换为 pricefeedintegration2。
2 个选项
- 按您的 field.keyword 又名 businessFunction.keyword 搜索
- 将您的字段映射更改为未分析。然后,您可以使用术语获得预期的结果。
选项1
这是一种简单的方法,如果您从未在该字段上运行全文搜索,最好不要将其用作默认值。如果没关系,就用这个选项,是最简单的。
检查您的 businessFunction.keyword 字段(如果您不指定映射,则默认创建)
索引数据而不映射到my000001索引
curl -X "POST" "http://localhost:9200/my000001/_doc" \
-H "Content-type: application/json" \
-d $'
{
"errorCode": "e015",
"errorDescription": "Description e015",
"storeId": "71102",
"businessFunction": "PriceFeedIntegration",
"createdDate": "2021-02-20T09:17:04.004"
}'
查看
curl -X "GET" "localhost:9200/my000001/_analyze" \
-H "Content-type: application/json" \
-d $'{
"field": "businessFunction.keyword",
"text": "PriceFeedIntegration"
}'
结果:
{
"tokens": [
{
"token": "PriceFeedIntegration",
"start_offset": 0,
"end_offset": 20,
"type": "word",
"position": 0
}
]
}
使用 businessFunction.keyword 获取结果
curl -X "GET" "localhost:9200/my000001/_search" \
-H "Content-type: application/json" \
-d $'{
"query": {
"bool": {
"must": [
{
"terms": {
"errorCode": [
"e015",
"e020",
"e022"
]
}
},
{
"terms": {
"storeId": [
"71102",
"71103"
]
}
},
{
"terms": {
"businessFunction.keyword": [
"PriceFeedIntegration2",
"PriceFeedIntegration"
]
}
},
{
"range": {
"createdDate": {
"gte": "2021-02-16T09:17:04.000",
"lte": "2021-02-22T00:00:00.005"
}
}
}
]
}
}
}' | jq
为什么不推荐作为默认选项?
“默认的动态字符串映射会将字符串字段作为文本和关键字进行索引。如果您只需要其中一个,这将是一种浪费。”
https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-disk-usage.html
选项 2
在my000001索引上运行
curl -X "GET" "localhost:9200/my000001/_analyze" \
-H "Content-type: application/json" \
-d $'{
"field": "businessFunction",
"text": "PriceFeedIntegration"
}'
您可以看到,您的字段值已被分析(标记化、小写和其他修改,具体取决于分析器和提供的值)结果:
{
"tokens": [
{
"token": "pricefeedintegration",
"start_offset": 0,
"end_offset": 20,
"type": "<ALPHANUM>",
"position": 0
}
]
}
这就是您的搜索不返回结果的原因。
“PriceFeedIntegration”与“pricefeedintegration”不匹配
“问题不在于术语查询;而在于数据的索引方式。”
您的 businessFunction 字段值已被分析。
如果您需要按精确值查找(搜索/过滤),则可能需要将“businessFunction”字段映射更改为 not_analyzed。
更改您的映射需要删除您的索引并再次创建提供所需的映射。
如果您尝试更改现有索引的映射,您将收到“resource_already_exists_exception”错误。
以下是解决问题所需了解的背景: https ://www.elastic.co/guide/en/elasticsearch/guide/master/_finding_exact_values.html#_finding_exact_values
在新的my000005索引上创建映射
curl -X "PUT" "localhost:9200/my000005" \
-H "Content-type: application/json" \
-d $'{
"mappings" : {
"properties" : {
"businessFunction" : {
"type" : "keyword"
},
"errorDescription" : {
"type" : "text"
},
"errorCode" : {
"type" : "keyword"
},
"createdDate" : {
"type" : "date"
},
"storeId": {
"type" : "keyword"
}
}
}
}'
索引数据
curl -X "POST" "http://localhost:9200/my000005/_doc" \
-H "Content-type: application/json" \
-d $'
{
"errorCode": "e015",
"errorDescription": "Description e015",
"storeId": "71102",
"businessFunction": "PriceFeedIntegration",
"createdDate": "2021-02-20T09:17:04.004"
}'
使用术语 businessFunction 获得您期望的结果
curl -X "GET" "localhost:9200/my000005/_search" \
-H "Content-type: application/json" \
-d $'{
"query": {
"bool": {
"must": [
{
"terms": {
"errorCode": [
"e015",
"e020",
"e022"
]
}
},
{
"terms": {
"storeId": [
"71102",
"71103"
]
}
},
{
"terms": {
"businessFunction": [
"PriceFeedIntegration2",
"PriceFeedIntegration"
]
}
},
{
"range": {
"createdDate": {
"gte": "2021-02-16T09:17:04.000",
"lte": "2021-02-22T00:00:00.005"
}
}
}
]
}
}
}' | jq
这个答案是基于我认为你的映射和你的需求。
将来分享你的映射和你的 ES 版本,以便从社区中得到更好的答案。
curl -X "GET" "localhost:9200/yourindex/_mappings"
请阅读此https://www.elastic.co/guide/en/elasticsearch/guide/master/_finding_exact_values.html#_finding_exact_values 和此https://www.elastic.co/blog/strings-are-dead-long-现场弦乐
推荐阅读
- vhdl - 整数输出在合成 ISE 中变为二进制
- javascript - Stripe:从 HTML 到 Checkout-Sessions PHP 的元数据
- amazon-web-services - 提供的 region_name 'US East (Ohio) us-east-2' 与支持的格式不匹配
- javascript - 修改字符串中的特定匹配项
- javascript - 流冒险。节点.js。秘密。代码不输入任何内容
- javascript - 强制网页在屏幕旋转时完全重新渲染
- node.js - res.cookie() 在 Nodejs/Angular 中不起作用
- c# - 创建一个按顺序运行任务的类
- swift - 无法为领域对象添加属性包装器
- php - wkhtmltopdf 使用 apache 用户执行时出错