2013-02-02 03 Голушко. Полнотекстовый поиск с Elasticsearch

Post on 28-Nov-2014

2.985 views 11 download

description

 

Transcript of 2013-02-02 03 Голушко. Полнотекстовый поиск с Elasticsearch

Дмитрий Голушко

О докладчике

Java разработчик, server-side

Важные параметры:

Скорость индексирования(в том числе realtime)

Способы взаимодействия(API, REST, etc.)

Работа с языками, стемминг, нечеткие запросы

Дополнительные типы полей в документах(numeric, geo, source, etc.)

Платформа и язык

Встроенные механизмы ранжирования и сортировки

Какие есть варианты?

Elasticsearch(based on Lucene, Java)

Solr(based on Lucene, Java)

Sphinx search engine(C++)

Xapian(C++)

Почему мы выбрали Elasticsearch?

Отличная поддержка шардинга и репликации на лету

Шардинг и репликация. Создаем индекс.

Нода 1

Street1

Street2

{ “number_of_shards” : 2, “number_of_replicas” : 1 }

Шардинг и репликация. Добавляем еще одну ноду.

Нода 1 Нода 2

Street1 Street1

Street2 Street2

Репликация

Шардинг и репликация. Добавляем еще 2 ноды.

Нода 1 Нода 2

Street1

Street2

Нода 3 Нода 4

Street1

Street2

Почему мы выбрали Elasticsearch?

Написан на Java и базируется на известном движке Lucene

Отличная поддержка шардинга и репликации на лету

Near-realtime индексация.

Поиск по «свежему» индексу

Поиск по индексу, с одновременной индексацией

Поиск по большому индексу, с одновременной индексацией

Почему мы выбрали Elasticsearch?

Написан на Java и базируется на известном движке Lucene

Отличная поддержка шардинга и репликации на лету

Near-realtime индексация.

Есть всё что нам нужно

Имеется возможность для расширения

Opensource, ASL v2

Возможность для расширения

River-плагины(поток данных из другого источника)

CouchDB RabbitMQ MongoDB

Анализаторы

Русская морфология Hunspell(орфография)

… Transport(расширения протоколов взаимодействия)

Memcached ZeroMQ Servlet

Site Plugins(чаще всего UI для управления кластером)

Scripting Plugins(ЯП для скриптов)

ElasticSearch Paramedic

BigDesk

elasticsearch-head

Особенности Elasticsearch

Документно-ориентированный

Schema-free

JSON как основной способ работы с данными

JSON как основной способ работы с данными

GET “http://localhost:9200/index_name/streets/_search?q=Жукова”

{ "took" : 138, "timed_out" : false, "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 }, "hits" : { "total" : 1, "max_score" : 1.9674579, "hits" : [{ "_index" : “index_name", "_type" : "street", "_id" : "VLvO7h7bQUiCOlGwd2iJrA", "_score" : 1.9674579, "_source" : {"STREET_NAME":"Маршала Жукова", "CITY_NAME":"Омск", “STREET_ID” : 3} } ] } }

Затраченное время

Количество результатов

Исходный документ

Особенности Elasticsearch

Документно-ориентированный

Schema-free

JSON как основной способ работы с данными

Распределенный поиск

Распределенный поиск

Node Node Node

Node Node Node

Приложение

Распределенный поиск

Node Node Node

Node Node Node

Приложение

Особенности Elasticsearch

Документно-ориентированный

Schema-free

JSON как основной способ работы с данными

Распределенный поиск

Скрипты для фильтрации(о них чуть позже)

Обновление настроек «на лету»

Обновление настроек «на лету»

"{ "index" : { "number_of_replicas" : 3 } }

POST “http://localhost:9200/index_name/_settings”

Обновление настроек на лету

Нода 1 Нода 2

Street1

Street2

Нода 3 Нода 4

Street1

Street2 Street2 Street2

Street1 Street1

Индексация

Анализатор

Tokenizer

Token Filter

Token Filter

Token Filter

Token Filter

Token Filters

Фонетические(Soundex, Metaphone, etc.)

Стеммеры(Стеммер Портера)

Ngramm

важно важного важное важной важном важному

важн важн важн важн важн важн

Soundex • Первая буква сохраняется • В остальной части слова:

• Буквы, обозначающие, как правило, гласные звуки: a, e, h, i, o, u, w и y — отбрасываются • Оставшиеся буквы (согласные) заменяются на цифры от 1 до 6, причём похожим по звучанию буквам соответствуют одинаковые цифры:

• 1: b, f, p, v • 2: c, g, j, k, q, s, x, z • 3: d, t • 4: l • 5: m, n • 6: r

• Любая последовательность одинаковых цифр сокращается до одной такой цифры. • Итоговая строка обрезается до первых четырёх символов. Если длина строки меньше требуемой, недостающие символы заменяются знаком 0. Примеры: аmmonium → ammnm → a5555 → a5 → a500 implementation → implmnttn → i51455335 → i514535 → i514

Ngramm

Запросы

«Обычные» запросы Term Match\Not match Bool Prefix Wildcard Range

Нечеткие запросы

Географические запросы

Boosting запросы

Span запросы

Fuzzy запросы(нечеткие)

Расстояние Левенштейна - минимальное количество операций

вставки одного символа, удаления одного символа и замены одного символа на другой, необходимых для превращения одной строки в другую.

Жукава Жукова

Лизной (проезд) Лесной (проезд)

Бухольца Бухгольца

1

2

1

Это важно! В большинстве случаев вы должны использовать для поиска

тот же алгоритм анализа, что и при индексировании!

Fuzzy Query «жукава»

Soundex «a500»

3gramm «жук ука кав ава»

Fuzzy Query «жукава»

Фильтрация

Обычные фильтры

Геофильтры

Script фильтр

Term Prefix Range Missing\Exists Query

Геофильтры

Geo distance Geo distance range Geo polygon Geo shape Geo BBox

{ “address" : { "location" : { "lat" : 41.12, "lon" : -71.34 } } }

{ "location" : { "type" : "envelope", "coordinates" : [[-45.0, 45.0], [45.0, -45.0]] } }

Геофильтры

Geo distance Geo distance range Geo polygon Geo shape Geo BBox

"filter" : { "geo_bounding_box" : { "pin.location" : { "top_left" : {"lat" : 40.73, "lon" : -74.1 }, "bottom_right" : {"lat" : 40.717, "lon" : -73.99} } } }

Геофильтры

Geo distance Geo distance range Geo polygon Geo shape Geo BBox

Геофильтры

Geo distance Geo distance range Geo polygon Geo shape Geo BBox

"filter" : { "geo_distance" : { "distance" : "2km", "pin.location" : { "lat" : 40, "lon" : -70 } } }

Геофильтры

Geo distance Geo distance range Geo polygon Geo shape Geo BBox

Геофильтры

Geo distance Geo distance range Geo polygon Geo shape Geo BBox

"filter": { "geo_shape": { "location": { "indexed_shape": {"id": "Украина", "type": "countries", "index": "shapes", "shape_field_name": "shape" }, "relation": "within" } } }

Скрипт-фильтр

"filtered" : { "query" : { ... }, "filter" : { "script" : { "script" : "doc['num1'].value > 1" } } }

Скрипт-фильтр. Доступные языки

Java

Groovy

Python

JavaScript

Advanced features Подсветка(Highlighting)

Именованные фильтры(Named Filters)

Percolation

Facets

Attachment indexing(с помощью Apache Tika) Microsoft Office, Open Document Formats, ePub, PDF, etc.

Time-to-live fields

Percolation

Индексируются запросы, а не документы!

Тем не менее это обычный индекс

Запросы распространяются на все реплики

Поддерживают все обычные запросы и фильтры

Percolation

{ "query" : { "terms" : {

"message" : ["путин","навальный", "террорист","бомба", "наркотики","взятка"]

} } }

“http://localhost:9200/_percolator/messages/kgb” POST

{"ok":true, "matches":["kgb"]}

Здарова! Зацени чо творится «Одесский террорист, "метивший в Путина", заявил о милицейских пытках наркотиками и пакетами».

"doc" : { "message" : "..." }

“http://localhost:9200/messages/type/_percolate” GET

Facets

Агрегированная информация по запросу

Статистическая информация Сумма, минимальное\максимальное значение, среднее и т.д.

Гистограммы(включая гистрограмму по дате)

Географический facet

Географический facet { "facets" : { "geo1" : { "geo_distance" : { "pin.location" : {"lat" : 40, "lon" : -70 }, "ranges" : [ { "to" : 10 }, { "from" : 10, "to" : 20 }, { "from" : 20, "to" : 100 }, { "from" : 100 } ] } } } }

А теперь небольшой real-world пример!

Развлечения!

{ "query" : { "match_all" : {} }, "facets" : { "facet_search" : { "terms" : { "quick_address_type" : ["restaurant", "cafe", "sauna", "pool", "bowling","bar"] } } } }

"facets" : { "tags" : { "_type" : "terms", "missing" : 0, "total": 30, "other": 0, "terms" : [ { "term" : "restaurant", "count" : 7 }, {"term" : "cafe", "count" : 5 }, {"term" : "sauna","count" : 6}, {"term" : "pool","count" : 3}, {"term" : "bowling","count" : 2}, {"term" : "bar","count" : 7 } ] } }

Рестораны(7)

Кафе(5)

Сауны(6)

Боулинги(2)

Бильярды(3)

Бары(7)

{ "query" : { "term" : {"quick_address_type" : "restaurant"} }, "sort" : [ { "_geo_distance" : { "pin.location" : [-73.13, 55.01], "order" : "asc", "unit" : "km" } }, { "rating" : { "user_rating" : "desc" } } ] }

«Беляшкино» 1км.

«Пампуши» 2км.

«Фуаграшная» 0,5км.

КОНЕЦ!