- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这可能是一个非常常见的问题,但是到目前为止我得到的答案并不令人满意。
问题:
我有一个由近 100 个字段组成的 es 索引。大多数字段是string
输入并设置为 analyzed
.但是,查询既可以是部分的( match
),也可以是精确的(更像是 term
)。所以,如果我的索引包含一个值为 super duper cool pizza
的字符串字段,可以有部分查询,如 duper super
并且将与文档匹配,但是,可以有像 cool pizza
这样的精确查询这不应该与文档匹配。另一方面,Super Duper COOL PIzza
再次应与此文件匹配。
到目前为止,部分匹配部分很容易,我使用了AND
match
中的运算符询问。但是无法完成其他类型。
我查看了与此问题相关的其他帖子,这篇文章包含最接近的解决方案:
Elasticsearch exact matches on analyzed fields
在这三个解决方案中,第一个感觉非常复杂,因为我有很多字段,而且我不使用 REST api,我正在使用来自 Java api 的 NativeSearchQueryBuilder 的 QueryBuilders 动态创建查询。它还会产生许多可能的模式,我认为这些模式会导致性能问题。
第二个是一个更简单的解决方案,但同样,我必须维护更多(几乎)冗余数据,我不认为使用 term
查询将永远解决我的问题。
最后一个我觉得有问题,不会阻止super duper
配用super duper cool pizza
这不是我想要的输出。
那么有没有其他方法可以实现我的目标?如果需要进一步解决问题,我可以发布一些示例映射。我也已经保留了源代码(以防可以使用)。请随时提出任何改进建议。
提前致谢。
[ 更新 ]
最后,我用了 multi_field
,为精确查询保留原始字段。当我插入时,我对数据使用了一些自定义修改,在搜索期间,我对输入文本使用了相同的修改例程。这部分不由 Elasticsearch 处理。如果你想这样做,你还必须设计合适的分析器。
索引设置和映射查询:
PUT test_index
POST test_index/_close
PUT test_index/_settings
{
"index": {
"analysis": {
"analyzer": {
"standard_uppercase": {
"type": "custom",
"char_filter": ["html_strip"],
"tokenizer": "keyword",
"filter": ["uppercase"]
}
}
}
}
}
PUT test_index/doc/_mapping
{
"doc": {
"properties": {
"text_field": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"analyzer": "standard_uppercase"
}
}
}
}
}
}
POST test_index/_open
POST test_index/doc/_bulk
{"index":{"_id":1}}
{"text_field":"super duper cool pizza"}
{"index":{"_id":2}}
{"text_field":"some other text"}
{"index":{"_id":3}}
{"text_field":"pizza"}
GET test_index/doc/_search
{
"query": {
"bool": {
"must": {
"bool": {
"should": {
"term": {
"text_field.raw": "PIZZA"
}
}
}
}
}
}
}
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1.4054651,
"hits": [
{
"_index": "test_index",
"_type": "doc",
"_id": "3",
"_score": 1.4054651,
"_source": {
"text_field": "pizza"
}
}
]
}
}
GET test_index/doc/_search
{
"query": {
"bool": {
"must": {
"bool": {
"should": {
"match": {
"text_field": {
"query": "pizza",
"operator": "AND",
"type": "boolean"
}
}
}
}
}
}
}
}
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "test_index",
"_type": "doc",
"_id": "3",
"_score": 1,
"_source": {
"text_field": "pizza"
}
},
{
"_index": "test_index",
"_type": "doc",
"_id": "1",
"_score": 0.5,
"_source": {
"text_field": "super duper cool pizza"
}
}
]
}
}
最佳答案
我认为这会做你想要的(或至少尽可能接近),使用 keyword tokenizer和 lowercase token filter :
PUT /test_index
{
"settings": {
"analysis": {
"analyzer": {
"lowercase_analyzer": {
"type": "custom",
"tokenizer": "keyword",
"filter": ["lowercase_token_filter"]
}
},
"filter": {
"lowercase_token_filter": {
"type": "lowercase"
}
}
}
},
"mappings": {
"doc": {
"properties": {
"text_field": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
},
"lowercase": {
"type": "string",
"analyzer": "lowercase_analyzer"
}
}
}
}
}
}
}
POST /test_index/doc/_bulk
{"index":{"_id":1}}
{"text_field":"super duper cool pizza"}
{"index":{"_id":2}}
{"text_field":"some other text"}
{"index":{"_id":3}}
{"text_field":"pizza"}
text_field
设置为由标准分析器分析,然后是子字段
raw
那是
not_analyzed
(你可能不想要这个,我只是为了比较而添加的),以及另一个子字段
lowercase
创建与输入文本完全相同的标记,除了它们被小写(但没有在空格上拆分)。所以这个
match
查询返回您期望的内容:
POST /test_index/_search
{
"query": {
"match": {
"text_field.lowercase": "Super Duper COOL PIzza"
}
}
}
...
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.30685282,
"hits": [
{
"_index": "test_index",
"_type": "doc",
"_id": "1",
"_score": 0.30685282,
"_source": {
"text_field": "super duper cool pizza"
}
}
]
}
}
match
查询也会针对搜索短语使用字段的分析器,因此在本例中搜索
"super duper cool pizza"
与搜索
"Super Duper COOL PIzza"
的效果完全相同(如果您想要完全匹配,您仍然可以使用
term
查询)。
raw
和
lowercase
具有相同的标记,但这只是因为所有输入已经是小写了):
POST /test_index/_search
{
"size": 0,
"aggs": {
"text_field_standard": {
"terms": {
"field": "text_field"
}
},
"text_field_raw": {
"terms": {
"field": "text_field.raw"
}
},
"text_field_lowercase": {
"terms": {
"field": "text_field.lowercase"
}
}
}
}
...{
"took": 26,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 0,
"hits": []
},
"aggregations": {
"text_field_raw": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "pizza",
"doc_count": 1
},
{
"key": "some other text",
"doc_count": 1
},
{
"key": "super duper cool pizza",
"doc_count": 1
}
]
},
"text_field_lowercase": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "pizza",
"doc_count": 1
},
{
"key": "some other text",
"doc_count": 1
},
{
"key": "super duper cool pizza",
"doc_count": 1
}
]
},
"text_field_standard": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "pizza",
"doc_count": 2
},
{
"key": "cool",
"doc_count": 1
},
{
"key": "duper",
"doc_count": 1
},
{
"key": "other",
"doc_count": 1
},
{
"key": "some",
"doc_count": 1
},
{
"key": "super",
"doc_count": 1
},
{
"key": "text",
"doc_count": 1
}
]
}
}
}
关于elasticsearch - 如何对 Elasticsearch 中的分析字段执行完全匹配查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34888144/
我是一名优秀的程序员,十分优秀!