【发布时间】:2012-08-24 22:09:16
【问题描述】:
假设在我的弹性搜索索引中,我有一个名为“dots”的字段,其中包含一串标点分隔的单词(例如“first.second.third”)。
我需要搜索例如“first.second”,然后获取其“dots”字段包含正好是“first.second”或以“first.second”开头的字符串的所有条目。
我无法理解文本查询的工作原理,至少我无法创建一个可以完成这项工作的查询。
【问题讨论】:
标签: elasticsearch
假设在我的弹性搜索索引中,我有一个名为“dots”的字段,其中包含一串标点分隔的单词(例如“first.second.third”)。
我需要搜索例如“first.second”,然后获取其“dots”字段包含正好是“first.second”或以“first.second”开头的字符串的所有条目。
我无法理解文本查询的工作原理,至少我无法创建一个可以完成这项工作的查询。
【问题讨论】:
标签: elasticsearch
Elasticsearch 有 Path Hierarchy Tokenizer 正是为此类用例创建的。以下是如何为您的索引设置它的示例:
# Create a new index with custom path_hierarchy analyzer
# See http://www.elasticsearch.org/guide/reference/index-modules/analysis/pathhierarchy-tokenizer.html
curl -XPUT "localhost:9200/prefix-test" -d '{
"settings": {
"analysis": {
"analyzer": {
"prefix-test-analyzer": {
"type": "custom",
"tokenizer": "prefix-test-tokenizer"
}
},
"tokenizer": {
"prefix-test-tokenizer": {
"type": "path_hierarchy",
"delimiter": "."
}
}
}
},
"mappings": {
"doc": {
"properties": {
"dots": {
"type": "string",
"analyzer": "prefix-test-analyzer",
//"index_analyzer": "prefix-test-analyzer", //deprecated
"search_analyzer": "keyword"
}
}
}
}
}'
echo
# Put some test data
curl -XPUT "localhost:9200/prefix-test/doc/1" -d '{"dots": "first.second.third"}'
curl -XPUT "localhost:9200/prefix-test/doc/2" -d '{"dots": "first.second.foo-bar"}'
curl -XPUT "localhost:9200/prefix-test/doc/3" -d '{"dots": "first.baz.something"}'
curl -XPOST "localhost:9200/prefix-test/_refresh"
echo
# Test searches.
curl -XPOST "localhost:9200/prefix-test/doc/_search?pretty=true" -d '{
"query": {
"term": {
"dots": "first"
}
}
}'
echo
curl -XPOST "localhost:9200/prefix-test/doc/_search?pretty=true" -d '{
"query": {
"term": {
"dots": "first.second"
}
}
}'
echo
curl -XPOST "localhost:9200/prefix-test/doc/_search?pretty=true" -d '{
"query": {
"term": {
"dots": "first.second.foo-bar"
}
}
}'
echo
curl -XPOST "localhost:9200/prefix-test/doc/_search?pretty=true&q=dots:first.second"
echo
【讨论】:
client.admin().indices().prepareCreate("test").addMapping("type1", mapping).setSettings(settings).execute().actionGet();
还有一种更简单的方法,正如 elasticsearch documentation 中指出的那样:
只需使用:
{
"text_phrase_prefix" : {
"fieldname" : "yourprefix"
}
}
或从 0.19.9 开始:
{
"match_phrase_prefix" : {
"fieldname" : "yourprefix"
}
}
代替:
{
"prefix" : {
"fieldname" : "yourprefix"
}
【讨论】:
$ curl -XGET 'http://localhost:9200/index/type/_search' -d '{
"query" : {
"prefix" : { "dots" : "first.second" }
}
}'
【讨论】:
prefix 查询是术语查询,所以没有分析 => 这么快。但没有分析。
您应该使用 commodin 字符进行查询,如下所示:
$ curl -XGET http://localhost:9200/myapp/index -d '{
"dots": "first.second*"
}'
更多关于语法的例子:http://lucene.apache.org/core/old_versioned_docs/versions/2_9_1/queryparsersyntax.html
【讨论】:
我正在寻找类似的解决方案 - 但只匹配一个前缀。我发现@imtov 的answer 让我快到了那里,但有一个变化 - 切换分析器:
"mappings": {
"doc": {
"properties": {
"dots": {
"type": "string",
"analyzer": "keyword",
"search_analyzer": "prefix-test-analyzer"
}
}
}
}
而不是
"mappings": {
"doc": {
"properties": {
"dots": {
"type": "string",
"index_analyzer": "prefix-test-analyzer",
"search_analyzer": "keyword"
}
}
}
}
这样添加:
'{"dots": "first.second"}'
'{"dots": "first.third"}'
将仅添加这些完整令牌,而不存储 first、second、third 令牌。
还在搜索中
first.second.anyotherstring
first.second
只会正确返回第一个条目:
'{"dots": "first.second"}'
不完全是您要求的,但在某种程度上相关,所以我认为可以帮助某人。
【讨论】: