Как сопоставить префикс в Elasticsearch - программирование
Подтвердить что ты не робот

Как сопоставить префикс в Elasticsearch

скажем, что в моем индексе elasticsearch у меня есть поле под названием "точки", которое будет содержать строку разделенных пунктуацией слов (например, "first.second.third" ).

Мне нужно искать, например. "first.second", а затем получить все записи, чье поле "точек" содержит строку, которая будет точно "first.second" или начинается с "first.second.".

У меня проблема с пониманием того, как работает текстовое расследование, по крайней мере, я не смог создать запрос, который выполняет задание.

4b9b3361

Ответ 1

Elasticsearch имеет указатель иерархии путей, который был создан именно для такого варианта использования. Вот пример того, как установить его для вашего индекса:

# 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

Ответ 2

Посмотрите префиксные запросы.

$ curl -XGET 'http://localhost:9200/index/type/_search' -d '{
    "query" : {
        "prefix" : { "dots" : "first.second" }
    }
}'

Ответ 4

Существует также более простой способ, как указано в документации elasticsearch :

просто используйте:

{
    "text_phrase_prefix" : {
        "fieldname" : "yourprefix"
    }
}

или с 0,19.9:

{
    "match_phrase_prefix" : {
        "fieldname" : "yourprefix"
    }
}

вместо:

{   
    "prefix" : { 
        "fieldname" : "yourprefix" 
}

Ответ 5

Я искал аналогичное решение, но сопоставлял только префикс. Я нашел @imtov ответ, чтобы получить меня почти там, но за одно изменение - переключение анализаторов вокруг:

"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"}'

Не совсем то, что вы просили, но каким-то образом связанным, поэтому я подумал, что может помочь кому-то.