ElasticSearch 5.x 对 Suggester API(文档)进行了一些(重大)更改。最显着的变化如下:
完成建议是面向文档的
建议知道它们所属的文档。现在,关联文档 (
_source
) 作为完成建议的一部分返回。
简而言之,所有完成查询都返回所有匹配的文档,而不仅仅是匹配的单词。这就是问题所在 - 如果自动完成的单词出现在多个文档中,则会出现重复。
假设我们有这个简单的映射:
{
"my-index": {
"mappings": {
"users": {
"properties": {
"firstName": {
"type": "text"
},
"lastName": {
"type": "text"
},
"suggest": {
"type": "completion",
"analyzer": "simple"
}
}
}
}
}
}
附上几份测试文件:
{
"_index": "my-index",
"_type": "users",
"_id": "1",
"_source": {
"firstName": "John",
"lastName": "Doe",
"suggest": [
{
"input": [
"John",
"Doe"
]
}
]
}
},
{
"_index": "my-index",
"_type": "users",
"_id": "2",
"_source": {
"firstName": "John",
"lastName": "Smith",
"suggest": [
{
"input": [
"John",
"Smith"
]
}
]
}
}
以及按书查询:
POST /my-index/_suggest?pretty
{
"my-suggest" : {
"text" : "joh",
"completion" : {
"field" : "suggest"
}
}
}
这会产生以下结果:
{
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"my-suggest": [
{
"text": "joh",
"offset": 0,
"length": 3,
"options": [
{
"text": "John",
"_index": "my-index",
"_type": "users",
"_id": "1",
"_score": 1,
"_source": {
"firstName": "John",
"lastName": "Doe",
"suggest": [
{
"input": [
"John",
"Doe"
]
}
]
}
},
{
"text": "John",
"_index": "my-index",
"_type": "users",
"_id": "2",
"_score": 1,
"_source": {
"firstName": "John",
"lastName": "Smith",
"suggest": [
{
"input": [
"John",
"Smith"
]
}
]
}
}
]
}
]
}
简而言之,对于文本“joh”的完成建议,返回了两 (2) 个文档- John 的文档和两者都具有相同的text
属性值。
但是,我想收到一 (1) 个字。像这样简单的东西:
{
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"my-suggest": [
{
"text": "joh",
"offset": 0,
"length": 3,
"options": [
"John"
]
}
]
}
问题:如何实现基于单词的完成建议。无需返回任何与文档相关的数据,因为此时我不需要它。
“完成建议”是否适合我的场景?还是我应该使用完全不同的方法?
编辑:正如你们中的许多人指出的那样,额外的仅完成索引将是一个可行的解决方案。但是,我可以看到这种方法存在多个问题:
- 保持新索引同步。
- 自动完成后续单词可能是全局的,而不是缩小范围。例如,假设您在附加索引中有以下单词:
"John", "Doe", "David", "Smith"
. 查询时"John D"
,不完整单词的结果应该是"Doe"
而不是"Doe", "David"
。
为了克服第二点,仅索引单个单词是不够的,因为您还需要将所有单词映射到文档,以便正确缩小自动完成后续单词的范围。有了这个,你实际上和查询原始索引有同样的问题。因此,附加索引不再有意义。