带有 ngram 索引的 Elasticsearch 找不到部分匹配项
Elasticsearch with ngram indexing not finding partial matches
所以我有一个这样创建的 elasticsearch 索引:
curl -XPUT 'http://localhost:9200/person' -d '{
"settings": {
"number_of_shards": 1,
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 20
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
}
}'
在查询名为 'ian' 的人时,我得到了两个结果
curl -XGET http://localhost:9200/person/_search -d '{
"query": {
"match": {
"_all": "ian"
}
}
}’
但是在查询字母 ia
时,我应该得到尽可能多或更多的结果,但我没有得到任何结果:
curl -XGET http://localhost:9200/person/_search -d '{
"query": {
"match": {
"_all": "ia"
}
}
}’
我的 edge_ngram
过滤器设置有问题吗?我该如何解决这个问题?
编辑:澄清一下,我希望我的插入语句符合以下内容
curl -XPOST "http://localhost:9200/person/RANDOM_STRING HERE/ANOTHER_RANDOM_STRING" -d "{
"field1" : "value",
"field2" : "value",
"field3" : "value"
}"
插入后,我希望对所有字段进行 edge_ngram 分析,以便我可以按任何这些字段的部分字符串进行搜索并返回此结果。
_all 字段将使用默认分析器 "standard",除非您为其指定一个。所以 _all 字段中的标记不是 edge_ngram。因此,搜索 "ia" 没有结果。您通常希望避免使用 _all 字段进行部分匹配搜索,因为它可能会产生意外或令人困惑的结果。
如果您仍然需要使用 _all 字段,则还需要将分析器指定为 "autocomplete"。
您没有指定任何使用您的分析器的类型。所以你定义了分析器,但没有使用它。当您将文档保存为新类型时,映射将被隐式定义,并且将使用 standard analyzer,这不会创建部分词项,因此您对 "ia" 的搜索不匹配任何东西。
处理此问题的一种方法是显式定义您的类型,并指定您要在映射中使用的分析器。这是一个示例,其中索引名称为 "person"(如您的),类型名称为 "doc",其中 属性 "name" 使用您的分析器进行索引(但不用于搜索):
PUT /person
{
"settings": {
"number_of_shards": 1,
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 20
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
},
"mappings": {
"doc":{
"properties": {
"name": {
"type": "string",
"index_analyzer": "autocomplete",
"search_analyzer": "standard"
}
}
}
}
}
为了测试它,我添加了几个文档:
POST /person/doc/_bulk
{"index":{"_id":1}}
{"name":"Ian"}
{"index":{"_id":2}}
{"name":"Bob Smith"}
然后 运行 针对 "name"
字段的匹配查询:
POST /person/_search
{
"query": {
"match": {
"name": "ia"
}
}
}
...
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "person",
"_type": "doc",
"_id": "1",
"_score": 1,
"_source": {
"name": "Ian"
}
}
]
}
}
这是我用来测试一些不同事物的一些代码,包括以一种使您的原始查询有效的方式使用 "_all"
字段:
http://sense.qbox.io/gist/61df5d17343651884c9422198b6a6bc00a6acb04
如果您只想对每种类型和所有属性使用您的分析器(除非另有说明),您只需为索引设置 "default" 分析器。我在 ES 文档中找不到这个(它们并不总是非常用户友好),但这里有一个例子。我正在使用 ES 1.5,但我认为这并不重要。
PUT /person
{
"settings": {
"number_of_shards": 1,
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 20
}
},
"analyzer": {
"default": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
}
}
然后我索引了文档和 运行 你的查询并且它工作正常:
POST /person/doc/_bulk
{"index":{"_id":1}}
{"name":"Ian"}
{"index":{"_id":2}}
{"name":"Bob Smith"}
POST /person/_search
{
"query": {
"match": {
"_all": "ia"
}
}
}
...
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1.4142135,
"hits": [
{
"_index": "person",
"_type": "doc",
"_id": "1",
"_score": 1.4142135,
"_source": {
"name": "Ian"
}
}
]
}
}
代码如下:
http://sense.qbox.io/gist/4e2114aafc4f3c507b4f23da8bb83f3ab00e2288
所以我有一个这样创建的 elasticsearch 索引:
curl -XPUT 'http://localhost:9200/person' -d '{
"settings": {
"number_of_shards": 1,
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 20
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
}
}'
在查询名为 'ian' 的人时,我得到了两个结果
curl -XGET http://localhost:9200/person/_search -d '{
"query": {
"match": {
"_all": "ian"
}
}
}’
但是在查询字母 ia
时,我应该得到尽可能多或更多的结果,但我没有得到任何结果:
curl -XGET http://localhost:9200/person/_search -d '{
"query": {
"match": {
"_all": "ia"
}
}
}’
我的 edge_ngram
过滤器设置有问题吗?我该如何解决这个问题?
编辑:澄清一下,我希望我的插入语句符合以下内容
curl -XPOST "http://localhost:9200/person/RANDOM_STRING HERE/ANOTHER_RANDOM_STRING" -d "{
"field1" : "value",
"field2" : "value",
"field3" : "value"
}"
插入后,我希望对所有字段进行 edge_ngram 分析,以便我可以按任何这些字段的部分字符串进行搜索并返回此结果。
_all 字段将使用默认分析器 "standard",除非您为其指定一个。所以 _all 字段中的标记不是 edge_ngram。因此,搜索 "ia" 没有结果。您通常希望避免使用 _all 字段进行部分匹配搜索,因为它可能会产生意外或令人困惑的结果。
如果您仍然需要使用 _all 字段,则还需要将分析器指定为 "autocomplete"。
您没有指定任何使用您的分析器的类型。所以你定义了分析器,但没有使用它。当您将文档保存为新类型时,映射将被隐式定义,并且将使用 standard analyzer,这不会创建部分词项,因此您对 "ia" 的搜索不匹配任何东西。
处理此问题的一种方法是显式定义您的类型,并指定您要在映射中使用的分析器。这是一个示例,其中索引名称为 "person"(如您的),类型名称为 "doc",其中 属性 "name" 使用您的分析器进行索引(但不用于搜索):
PUT /person
{
"settings": {
"number_of_shards": 1,
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 20
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
},
"mappings": {
"doc":{
"properties": {
"name": {
"type": "string",
"index_analyzer": "autocomplete",
"search_analyzer": "standard"
}
}
}
}
}
为了测试它,我添加了几个文档:
POST /person/doc/_bulk
{"index":{"_id":1}}
{"name":"Ian"}
{"index":{"_id":2}}
{"name":"Bob Smith"}
然后 运行 针对 "name"
字段的匹配查询:
POST /person/_search
{
"query": {
"match": {
"name": "ia"
}
}
}
...
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "person",
"_type": "doc",
"_id": "1",
"_score": 1,
"_source": {
"name": "Ian"
}
}
]
}
}
这是我用来测试一些不同事物的一些代码,包括以一种使您的原始查询有效的方式使用 "_all"
字段:
http://sense.qbox.io/gist/61df5d17343651884c9422198b6a6bc00a6acb04
如果您只想对每种类型和所有属性使用您的分析器(除非另有说明),您只需为索引设置 "default" 分析器。我在 ES 文档中找不到这个(它们并不总是非常用户友好),但这里有一个例子。我正在使用 ES 1.5,但我认为这并不重要。
PUT /person
{
"settings": {
"number_of_shards": 1,
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 20
}
},
"analyzer": {
"default": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
}
}
然后我索引了文档和 运行 你的查询并且它工作正常:
POST /person/doc/_bulk
{"index":{"_id":1}}
{"name":"Ian"}
{"index":{"_id":2}}
{"name":"Bob Smith"}
POST /person/_search
{
"query": {
"match": {
"_all": "ia"
}
}
}
...
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1.4142135,
"hits": [
{
"_index": "person",
"_type": "doc",
"_id": "1",
"_score": 1.4142135,
"_source": {
"name": "Ian"
}
}
]
}
}
代码如下:
http://sense.qbox.io/gist/4e2114aafc4f3c507b4f23da8bb83f3ab00e2288