Elasticsearch return 带搜索的拼音标记
Elasticsearch return phonetic token with search
由于语音转换,我使用弹性搜索中的 phonetic analysis plugin 进行一些字符串匹配。
我的问题是,如何在查询结果中进行弹性搜索处理的语音转换?。
首先,我使用 metaphone
转换创建索引:
request_body = {
'settings': {
'index': {
'analysis': {
'analyzer': {
'metaphone_analyzer': {
'tokenizer':
'standard',
'filter': [
'ascii_folding_filter', 'lowercase',
'metaphone_filter'
]
}
},
'filter': {
'metaphone_filter': {
'type': 'phonetic',
'encoder': 'metaphone',
'replace': False
},
'ascii_folding_filter': {
'type': 'asciifolding',
'preserve_original': True
}
}
}
}
},
'mappings': {
'person_name': {
'properties': {
'full_name': {
'type': 'text',
'fields': {
'metaphone_field': {
'type': 'string',
'analyzer': 'metaphone_analyzer'
}
}
}
}
}
}
}
res = es.indices.create(index="my_index", body=request_body)
然后,我添加一些数据:
# Add some data
names = [{
"full_name": "John Doe"
}, {
"full_name": "Bob Alice"
}, {
"full_name": "Foo Bar"
}]
for name in names:
res = es.index(index="my_index",
doc_type='person_name',
body=name,
refresh=True)
最后,我查询了一个名字:
es.search(index="my_index",
body={
"size": 5,
"query": {
"multi_match": {
"query": "Jon Doe",
"fields": "*_field"
}
}
})
搜索 returns:
{
'took': 1,
'timed_out': False,
'_shards': {
'total': 5,
'successful': 5,
'skipped': 0,
'failed': 0
},
'hits': {
'total':
1,
'max_score':
0.77749264,
'hits': [{
'_index': 'my_index',
'_type': 'person_name',
'_id': 'AWwYjl4Mqo63y_hLp5Yl',
'_score': 0.77749264,
'_source': {
'full_name': 'John Doe'
}
}]
}
}
在搜索中return我想在elastic search中获取名称的语音转换(也来自查询名称,但不太重要)当我执行搜索。
我知道,我可以使用 explain
API 但我想避免第二次请求,而且 explain
API 看起来有点 "overkill" 为了我想要达到的目标。
谢谢!
在 Elasticsearch 查询中实现它看起来并不容易,但您可以尝试 analyze API and scripted fields with fielddata
enabled, and term vectors 可能会派上用场。方法如下。
从任意查询中检索标记
Analyze API 如果您想了解 Elasticsearch 究竟如何标记您的查询,这是一个很好的工具。
使用你的映射你可以做,例如:
GET myindex/_analyze
{
"analyzer": "metaphone_analyzer",
"text": "John Doe"
}
并得到这样的结果:
{
"tokens": [
{
"token": "JN",
"start_offset": 0,
"end_offset": 4,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "john",
"start_offset": 0,
"end_offset": 4,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "T",
"start_offset": 5,
"end_offset": 8,
"type": "<ALPHANUM>",
"position": 1
},
{
"token": "doe",
"start_offset": 5,
"end_offset": 8,
"type": "<ALPHANUM>",
"position": 1
}
]
}
这在技术上是一个不同的查询,但仍然可能有用。
从文档的字段中检索标记
理论上,我们可以尝试从与我们的查询匹配的文档中检索在上一节中分析 API return 的完全相同的标记。
实际上 Elasticsearch 不会存储 text
field it has just analyzed: fielddata
的令牌,默认情况下是禁用的。我们需要启用它:
PUT /myindex
{
"mappings": {
"person_name": {
"properties": {
"full_name": {
"fields": {
"metaphone_field": {
"type": "text",
"analyzer": "metaphone_analyzer",
"fielddata": true
}
},
"type": "text"
}
}
}
},
"settings": {
...
}
}
现在,我们可以使用 scripted fields 请求 Elasticsearch return 那些标记。
查询可能如下所示:
POST myindex/_search
{
"script_fields": {
"my tokens": {
"script": {
"lang": "painless",
"source": "doc[params.field].values",
"params": {
"field": "full_name.metaphone_field"
}
}
}
}
}
响应如下所示:
{
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "myindex",
"_type": "person_name",
"_id": "123",
"_score": 1,
"fields": {
"my tokens": [
"JN",
"T",
"doe",
"john"
]
}
}
]
}
}
如您所见,完全相同的标记(但顺序随机)。
我们还可以检索有关这些标记在文档中的位置的信息吗?
检索代币及其位置
term vectors 可能会有帮助。为了能够使用它们,我们实际上不需要启用 fielddata
。我们可以查找文档的术语向量:
GET myindex/person_name/123/_termvectors
{
"fields" : ["full_name.metaphone_field"],
"offsets" : true,
"positions" : true
}
这会 return 像这样:
{
"_index": "myindex",
"_type": "person_name",
"_id": "123",
"_version": 1,
"found": true,
"took": 1,
"term_vectors": {
"full_name.metaphone_field": {
"field_statistics": {
"sum_doc_freq": 4,
"doc_count": 1,
"sum_ttf": 4
},
"terms": {
"JN": {
"term_freq": 1,
"tokens": [
{
"position": 0,
"start_offset": 0,
"end_offset": 4
}
]
},
"T": {
"term_freq": 1,
"tokens": [
{
"position": 1,
"start_offset": 5,
"end_offset": 8
}
]
},
"doe": {
"term_freq": 1,
"tokens": [
{
"position": 1,
"start_offset": 5,
"end_offset": 8
}
]
},
"john": {
"term_freq": 1,
"tokens": [
{
"position": 0,
"start_offset": 0,
"end_offset": 4
}
]
}
}
}
}
}
这提供了一种获取文档字段标记的方法,就像分析器生成的标记一样。
遗憾的是,据我所知,无法将这三个查询合并为一个查询。另外 fielddata
应谨慎使用,因为它会占用大量内存。
希望对您有所帮助!
由于语音转换,我使用弹性搜索中的 phonetic analysis plugin 进行一些字符串匹配。
我的问题是,如何在查询结果中进行弹性搜索处理的语音转换?。
首先,我使用 metaphone
转换创建索引:
request_body = {
'settings': {
'index': {
'analysis': {
'analyzer': {
'metaphone_analyzer': {
'tokenizer':
'standard',
'filter': [
'ascii_folding_filter', 'lowercase',
'metaphone_filter'
]
}
},
'filter': {
'metaphone_filter': {
'type': 'phonetic',
'encoder': 'metaphone',
'replace': False
},
'ascii_folding_filter': {
'type': 'asciifolding',
'preserve_original': True
}
}
}
}
},
'mappings': {
'person_name': {
'properties': {
'full_name': {
'type': 'text',
'fields': {
'metaphone_field': {
'type': 'string',
'analyzer': 'metaphone_analyzer'
}
}
}
}
}
}
}
res = es.indices.create(index="my_index", body=request_body)
然后,我添加一些数据:
# Add some data
names = [{
"full_name": "John Doe"
}, {
"full_name": "Bob Alice"
}, {
"full_name": "Foo Bar"
}]
for name in names:
res = es.index(index="my_index",
doc_type='person_name',
body=name,
refresh=True)
最后,我查询了一个名字:
es.search(index="my_index",
body={
"size": 5,
"query": {
"multi_match": {
"query": "Jon Doe",
"fields": "*_field"
}
}
})
搜索 returns:
{
'took': 1,
'timed_out': False,
'_shards': {
'total': 5,
'successful': 5,
'skipped': 0,
'failed': 0
},
'hits': {
'total':
1,
'max_score':
0.77749264,
'hits': [{
'_index': 'my_index',
'_type': 'person_name',
'_id': 'AWwYjl4Mqo63y_hLp5Yl',
'_score': 0.77749264,
'_source': {
'full_name': 'John Doe'
}
}]
}
}
在搜索中return我想在elastic search中获取名称的语音转换(也来自查询名称,但不太重要)当我执行搜索。
我知道,我可以使用 explain
API 但我想避免第二次请求,而且 explain
API 看起来有点 "overkill" 为了我想要达到的目标。
谢谢!
在 Elasticsearch 查询中实现它看起来并不容易,但您可以尝试 analyze API and scripted fields with fielddata
enabled, and term vectors 可能会派上用场。方法如下。
从任意查询中检索标记
Analyze API 如果您想了解 Elasticsearch 究竟如何标记您的查询,这是一个很好的工具。
使用你的映射你可以做,例如:
GET myindex/_analyze
{
"analyzer": "metaphone_analyzer",
"text": "John Doe"
}
并得到这样的结果:
{
"tokens": [
{
"token": "JN",
"start_offset": 0,
"end_offset": 4,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "john",
"start_offset": 0,
"end_offset": 4,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "T",
"start_offset": 5,
"end_offset": 8,
"type": "<ALPHANUM>",
"position": 1
},
{
"token": "doe",
"start_offset": 5,
"end_offset": 8,
"type": "<ALPHANUM>",
"position": 1
}
]
}
这在技术上是一个不同的查询,但仍然可能有用。
从文档的字段中检索标记
理论上,我们可以尝试从与我们的查询匹配的文档中检索在上一节中分析 API return 的完全相同的标记。
实际上 Elasticsearch 不会存储 text
field it has just analyzed: fielddata
的令牌,默认情况下是禁用的。我们需要启用它:
PUT /myindex
{
"mappings": {
"person_name": {
"properties": {
"full_name": {
"fields": {
"metaphone_field": {
"type": "text",
"analyzer": "metaphone_analyzer",
"fielddata": true
}
},
"type": "text"
}
}
}
},
"settings": {
...
}
}
现在,我们可以使用 scripted fields 请求 Elasticsearch return 那些标记。
查询可能如下所示:
POST myindex/_search
{
"script_fields": {
"my tokens": {
"script": {
"lang": "painless",
"source": "doc[params.field].values",
"params": {
"field": "full_name.metaphone_field"
}
}
}
}
}
响应如下所示:
{
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "myindex",
"_type": "person_name",
"_id": "123",
"_score": 1,
"fields": {
"my tokens": [
"JN",
"T",
"doe",
"john"
]
}
}
]
}
}
如您所见,完全相同的标记(但顺序随机)。
我们还可以检索有关这些标记在文档中的位置的信息吗?
检索代币及其位置
term vectors 可能会有帮助。为了能够使用它们,我们实际上不需要启用 fielddata
。我们可以查找文档的术语向量:
GET myindex/person_name/123/_termvectors
{
"fields" : ["full_name.metaphone_field"],
"offsets" : true,
"positions" : true
}
这会 return 像这样:
{
"_index": "myindex",
"_type": "person_name",
"_id": "123",
"_version": 1,
"found": true,
"took": 1,
"term_vectors": {
"full_name.metaphone_field": {
"field_statistics": {
"sum_doc_freq": 4,
"doc_count": 1,
"sum_ttf": 4
},
"terms": {
"JN": {
"term_freq": 1,
"tokens": [
{
"position": 0,
"start_offset": 0,
"end_offset": 4
}
]
},
"T": {
"term_freq": 1,
"tokens": [
{
"position": 1,
"start_offset": 5,
"end_offset": 8
}
]
},
"doe": {
"term_freq": 1,
"tokens": [
{
"position": 1,
"start_offset": 5,
"end_offset": 8
}
]
},
"john": {
"term_freq": 1,
"tokens": [
{
"position": 0,
"start_offset": 0,
"end_offset": 4
}
]
}
}
}
}
}
这提供了一种获取文档字段标记的方法,就像分析器生成的标记一样。
遗憾的是,据我所知,无法将这三个查询合并为一个查询。另外 fielddata
应谨慎使用,因为它会占用大量内存。
希望对您有所帮助!