有没有办法让ElasticSearch识别分析字段的完全匹配?理想情况下,我想小写,标记,干,甚至语音化我的文档,然后让查询拉出"精确"匹配.
我的意思是,如果我将"汉堡包"和"汉堡包"编入索引,它们将被分析为["汉堡包","包子"]和["汉堡包"].如果我搜索"汉堡包",它将仅返回"汉堡包"文档,因为这是"精确"匹配.
我尝试过使用关键字tokenizer,但这不会阻止个别令牌.我是否需要做一些事情以确保令牌的数量相等?
我熟悉多字段并使用"not_analyzed"类型,但这比我正在寻找的更具限制性.我想要完全匹配,后期分析.
And*_*fan 11
使用带状疱疹标记器以及阻塞和其他任何需要的东西.添加一个类型的子字段,token_count用于计算字段中的标记数.
在搜索时,您需要添加一个额外的过滤器,以使索引中的标记数与搜索文本中的标记数相匹配.在执行实际搜索时,您需要一个额外的步骤来计算搜索字符串中的标记.这是这样的,因为带状符会创建令牌的多个排列,您需要确保它与搜索文本的大小相匹配.
尝试这个,只是为了给你一个想法:
{
"settings": {
"analysis": {
"filter": {
"filter_shingle": {
"type": "shingle",
"max_shingle_size": 10,
"min_shingle_size": 2,
"output_unigrams": true
},
"filter_stemmer": {
"type": "porter_stem",
"language": "_english_"
}
},
"analyzer": {
"ShingleAnalyzer": {
"tokenizer": "standard",
"filter": [
"lowercase",
"snowball",
"filter_stemmer",
"filter_shingle"
]
}
}
}
},
"mappings": {
"test": {
"properties": {
"text": {
"type": "string",
"analyzer": "ShingleAnalyzer",
"fields": {
"word_count": {
"type": "token_count",
"store": "yes",
"analyzer": "ShingleAnalyzer"
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
和查询:
{
"query": {
"filtered": {
"query": {
"match_phrase": {
"text": {
"query": "HaMbUrGeRs BUN"
}
}
},
"filter": {
"term": {
"text.word_count": "2"
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
该shingles过滤器是在这里非常重要,因为它可以创建令牌的组合.更重要的是,这些是保持订单或令牌的组合.Imo,这里最难实现的要求是更改标记(词干,小写等),并且还要回收原始文本.除非您定义自己的"连接"过滤器,否则我认为除了使用shingles过滤器之外没有其他任何方法.
但是shingles还有另一个问题:它创造了不需要的组合.对于像"Hamburgers buns in Los Angeles"你这样的文本最终得到一长串的带状疱疹:
"angeles",
"buns",
"buns in",
"buns in los",
"buns in los angeles",
"hamburgers",
"hamburgers buns",
"hamburgers buns in",
"hamburgers buns in los",
"hamburgers buns in los angeles",
"in",
"in los",
"in los angeles",
"los",
"los angeles"
Run Code Online (Sandbox Code Playgroud)
如果您只对那些符合确切含义的文件感兴趣,那么上述文件只有在您搜索"洛杉矶汉堡包子"时才会匹配(并且与"洛杉矶的任何汉堡包子"不匹配),那么您需要一个过滤那长长的带状疱疹列表的方法.我看到它的方式是使用word_count.
您可以为此目的使用多字段,并not_analyzed在您的analyzed字段中有一个子字段(item在本示例中将其称为)。您的映射必须如下所示:
{
"yourtype": {
"properties": {
"item": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
有了这种映射,可以检查如何每个值Hamburgers和Hamburger Buns相对于“观察”的分析仪的多领域item和item.raw
对于Hamburger:
curl -XGET 'localhost:9200/yourtypes/_analyze?field=item&pretty' -d 'Hamburger'
{
"tokens" : [ {
"token" : "hamburger",
"start_offset" : 0,
"end_offset" : 10,
"type" : "<ALPHANUM>",
"position" : 1
} ]
}
curl -XGET 'localhost:9200/yourtypes/_analyze?field=item.raw&pretty' -d 'Hamburger'
{
"tokens" : [ {
"token" : "Hamburger",
"start_offset" : 0,
"end_offset" : 10,
"type" : "word",
"position" : 1
} ]
}
Run Code Online (Sandbox Code Playgroud)
对于Hamburger Buns:
curl -XGET 'localhost:9200/yourtypes/_analyze?field=item&pretty' -d 'Hamburger Buns'
{
"tokens" : [ {
"token" : "hamburger",
"start_offset" : 0,
"end_offset" : 10,
"type" : "<ALPHANUM>",
"position" : 1
}, {
"token" : "buns",
"start_offset" : 11,
"end_offset" : 15,
"type" : "<ALPHANUM>",
"position" : 2
} ]
}
curl -XGET 'localhost:9200/yourtypes/_analyze?field=item.raw&pretty' -d 'Hamburger Buns'
{
"tokens" : [ {
"token" : "Hamburger Buns",
"start_offset" : 0,
"end_offset" : 15,
"type" : "word",
"position" : 1
} ]
}
Run Code Online (Sandbox Code Playgroud)
如您所见,该not_analyzed字段将完全按照输入的原样进行索引。
现在,我们为两个示例文档建立索引以说明这一点:
curl -XPOST localhost:9200/yourtypes/_bulk -d '
{"index": {"_type": "yourtype", "_id": 1}}
{"item": "Hamburger"}
{"index": {"_type": "yourtype", "_id": 2}}
{"item": "Hamburger Buns"}
'
Run Code Online (Sandbox Code Playgroud)
最后,要回答您的问题,如果您想对进行完全匹配Hamburger,则可以在子字段中进行item.raw如下搜索(请注意,大小写也必须匹配):
curl -XPOST localhost:9200/yourtypes/yourtype/_search -d '{
"query": {
"term": {
"item.raw": "Hamburger"
}
}
}'
Run Code Online (Sandbox Code Playgroud)
您会得到:
{
...
"hits" : {
"total" : 1,
"max_score" : 0.30685282,
"hits" : [ {
"_index" : "yourtypes",
"_type" : "yourtype",
"_id" : "1",
"_score" : 0.30685282,
"_source":{"item": "Hamburger"}
} ]
}
}
Run Code Online (Sandbox Code Playgroud)
更新(请参阅下面的评论/讨论和问题重新编辑)
从注释中获取示例并尝试使之HaMbUrGeR BuNs匹配,Hamburger buns您可以简单地通过这样的match查询来实现。
curl -XPOST localhost:9200/yourtypes/yourtype/_search?pretty -d '{
"query": {
"match": {
"item": {
"query": "HaMbUrGeR BuNs",
"operator": "and"
}
}
}
}'
Run Code Online (Sandbox Code Playgroud)
根据上面相同的两个索引文件,将得出
{
...
"hits" : {
"total" : 1,
"max_score" : 0.2712221,
"hits" : [ {
"_index" : "yourtypes",
"_type" : "yourtype",
"_id" : "2",
"_score" : 0.2712221,
"_source":{"item": "Hamburger Buns"}
} ]
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将分析器保持为您所期望的(小写,标记,词干......),并将其用query_string作主查询,match_phrase作为要搜索的提升查询.像这样的东西:
{
"bool" : {
"should" : [
{
"query_string" : {
"default_field" : "your_field",
"default_operator" : "OR",
"phrase_slop" : 1,
"query" : "Hamburger"
}
},
{
"match_phrase": {
"your_field": {
"query": "Hamburger"
}
}
}
]
}
}
Run Code Online (Sandbox Code Playgroud)
它将匹配两个文档,并且完全匹配(match_phrase)将位于顶部,因为查询匹配两个should子句(并获得更高的分数)
default_operator设置为OR,它将帮助查询"Hamburger Buns"(匹配hamburgerOR bun)匹配文档"Hamburger".
phrase_slop设置为1以匹配仅与距离= 1的条件,例如搜索Hamburger Buns将与文档不匹配Hamburger Big Buns.您可以根据您的要求进行调整.
| 归档时间: |
|
| 查看次数: |
21288 次 |
| 最近记录: |