Статьи

Elasticsearch: анализ текста для обогащения контента

Каждое решение для поиска текста так же мощно, как и возможности анализа текста, которые оно предлагает. Lucene — это такая библиотека для поиска информации с открытым исходным кодом, которая предлагает множество возможностей анализа текста. В этом посте мы расскажем о некоторых основных функциях анализа текста, предлагаемых ElasticSearch, доступных для обогащения вашего поискового контента.

Обогащение контента

Принимая пример типичного сайта электронной коммерции, предоставление нужного контента в поиске конечному клиенту очень важно для бизнеса. Стратегия анализа текста, предоставляемая любым поисковым решением, играет в этом очень большую роль. Как пользователь поиска, я бы предпочел, чтобы некоторые из типичных поисковых запросов автоматически возвращали мой запрос.

  • следует искать синонимы, соответствующие тексту моего запроса
  • должен соответствовать одинарному и множественному числу слов или слов, звучащих одинаково, чтобы ввести текст запроса
  • не должен разрешать поиск по защищенным словам
  • должен разрешать поиск слов, смешанных с цифровыми или специальными символами
  • не должен разрешать поиск по тегам HTML
  • следует разрешить поиск текста на основе близости букв и количества совпадающих букв

Расширение содержания здесь будет означать добавление вышеуказанных возможностей поиска к вашему контенту при индексации и поиске контента.

Анализ текста Lucene

Lucene — это информационный поиск (IR), позволяющий выполнять полнотекстовую индексацию и поиск. Для быстрого ознакомления, проверьте пост Анализ текста внутри Lucene . В Lucene документ содержит поля Text. Анализ — это процесс дальнейшего преобразования текста поля в термины. Эти термины используются для соответствия поисковому запросу. Есть три основных реализации для всего процесса анализа,

  • Анализатор: Анализатор отвечает за создание TokenStream, который может использоваться процессами индексации и поиска.
  • Tokenizer: Tokenizer является TokenStream и отвечает за разбиение входящего текста на токены. В большинстве случаев Анализатор будет использовать Tokenizer в качестве первого шага в процессе анализа.
  • TokenFilter: TokenFilter также является TokenStream и отвечает за изменение токенов, созданных Tokenizer.

Обычный стиль использования TokenStreams и TokenFilters внутри Analyzer заключается в использовании шаблона цепочки, который позволяет создавать сложные анализаторы из простых строительных блоков Tokenizer / TokenFilter. Токенайзеры запускают процесс анализа, разграничивая ввод символов в токены (в основном они соответствуют словам в исходном тексте). Затем TokenFilters берет на себя оставшуюся часть анализа, первоначально оборачивая Tokenizer и последовательно оборачивая вложенные TokenFilters.

Анализ текста ElasticSearch

ElasticSearch использует встроенные возможности Lucene для анализа текста и позволяет обогащать содержимое вашего поиска. Как указано выше, анализ текста делится на фильтры, токенизаторы и анализаторы. ElasticSearch предлагает вам довольно много встроенных анализаторов с предварительно настроенными токенизаторами и фильтрами. Для получения подробного списка существующих анализаторов, проверьте полный список для анализа

Обновить настройки анализа

ElasticSearch позволяет динамически обновлять настройки индекса и сопоставления. Чтобы обновить настройки индекса из Java-клиента API,

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Settings settings = settingsBuilder().loadFromSource(jsonBuilder()
                    .startObject()
                        //Add analyzer settings
                        .startObject("analysis")
                            .startObject("filter")
                                .startObject("test_filter_stopwords_en")
                                    .field("type", "stop")
                                    .field("stopwords_path", "stopwords/stop_en")
                                .endObject()
                                .startObject("test_filter_snowball_en")
                                    .field("type", "snowball")
                                    .field("language", "English")
                                .endObject()
                                .startObject("test_filter_worddelimiter_en")
                                    .field("type", "word_delimiter")
                                    .field("protected_words_path", "worddelimiters/protectedwords_en")
                                    .field("type_table_path", "typetable")
                                .endObject()
                                .startObject("test_filter_synonyms_en")
                                    .field("type", "synonym")
                                    .field("synonyms_path", "synonyms/synonyms_en")
                                    .field("ignore_case", true)
                                    .field("expand", true)
                                .endObject()
                                .startObject("test_filter_ngram")
                                    .field("type", "edgeNGram")
                                    .field("min_gram", 2)
                                    .field("max_gram", 30)
                                .endObject()
                           .endObject()
                           .startObject("analyzer")
                                .startObject("test_analyzer")
                                    .field("type", "custom")
                                    .field("tokenizer", "whitespace")
                                    .field("filter", new String[]{"lowercase",
                                                                    "test_filter_worddelimiter_en",
                                                                        "test_filter_stopwords_en",
                                                                        "test_filter_synonyms_en",
                                                                        "test_filter_snowball_en"})
                                    .field("char_filter", "html_strip")
                                .endObject()
                           .endObject()
                        .endObject()
                    .endObject().string()).build();
  
CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(indexName);
createIndexRequestBuilder.setSettings(settings);

Вы также можете установить свой индекс и настройки в файле конфигурации. Путь, упомянутый в приведенном выше примере, относится к каталогу config установленного сервераasticsearch. Приведенный выше пример позволяет вам создавать собственные фильтры и анализаторы для вашего индекса. ElasticSearch имеет существующую комбинацию различных фильтров и токенизаторов, позволяющую вам выбрать правильную комбинацию для ваших данных.

Синонимы

Синонимом являются слова с одинаковым или сходным значением. Расширение синонима — это место, где мы берем варианты слова и присваиваем их поисковой системе во время индексации и / или запроса. Добавить фильтр синонимов в настройки индекса.

1
2
3
4
5
6
.startObject("test_filter_synonyms_en")
    .field("type", "synonym")
    .field("synonyms_path", "synonyms/synonyms_en")
    .field("ignore_case", true)
    .field("expand", true)
.endObject()

Проверьте фильтр синонимов для полного синтаксиса. Вы можете добавить синоним в формате Slor или WordNet. Взгляните на Slor Synonym Format для дальнейших примеров,

1
2
3
4
# If expand==true, "ipod, i-pod, i pod" is equivalent to the explicit mapping:
ipod, i-pod, i pod => ipod, i-pod, i pod
# If expand==false, "ipod, i-pod, i pod" is equivalent to the explicit mapping:
ipod, i-pod, i pod => ipod

Проверьте список слов для списка слов и синонимов, соответствующих вашим требованиям.

Морфологический

Определение слова определяется как способность включать вариации слова. Например, любое существительное слово может включать в себя вариации (важность которых прямо пропорциональна степени вариации). В случае использования слова мы используем количественные методы для правил грамматики, чтобы добавить основы слова и ранжировать их в соответствии с их степенью отделения от корня. слово. Добавить фильтр стволов в настройки индекса.

1
2
3
4
.startObject("test_filter_snowball_en")
    .field("type", "snowball")
    .field("language", "English")
.endObject()

Проверьте синтаксис Snowball Filter для деталей. Программы стемминга обычно называют алгоритмами стемминга или стеммерами. Анализ Lucene может быть алгоритмическим или словарным. Snowball , основанный на алгоритме Snowball Мартина Портера, обеспечивает функциональность стемминга и используется в качестве стеммера в приведенном выше примере. Проверьте список стеблеров снежного кома для различных поддерживаемых языков. Синоним и ствол иногда возвращают вам странные результаты в зависимости от порядка обработки текста. Убедитесь, что вы используете их в порядке, соответствующем вашим требованиям.

Стоп слова

Стоп-слова — это список слов, которые вы не хотите, чтобы пользователь мог индексировать или запрашивать. Чтобы добавить фильтр стоп-слов в настройки,

1
2
3
4
.startObject("test_filter_stopwords_en")
    .field("type", "stop")
    .field("stopwords_path", "stopwords/stop_en")
.endObject()

Проверьте полный синтаксис фильтра стоп-слов . Проверьте список слов стоп-слов Snowball для английского языка, чтобы получить свой собственный список. Проверьте Solr общий список стоп-слов для английского языка.

Разделитель слов

Фильтр разделителя слов позволяет разбить слово на подслово для дальнейшей обработки подслов. Чтобы добавить фильтр разделителей слов в настройки,

1
2
3
4
5
.startObject("test_filter_worddelimiter_en")
    .field("type", "word_delimiter")
    .field("protected_words_path", "worddelimiters/protectedwords_en")
    .field("type_table_path", "typetable")
.endObject()

Общее разделение слов основано на не алфавитно-цифровой природе, переходах регистра, разделителях слов и т. Д. Проверьте полный синтаксис и различные доступные параметры для фильтра разделителей слов . Список защищенных слов позволяет защитить деловые релевантные слова от разграничения в процессе.

N-граммы

N-грамм — это непрерывная последовательность из n букв для данной последовательности текста. Чтобы добавить фильтр граничной диаграммы в настройки,

1
2
3
4
5
.startObject("test_filter_ngram")
    .field("type", "edgeNGram")
    .field("min_gram", 2)
    .field("max_gram", 30)
.endObject()

В зависимости от конфигурации входной текст будет разбит на несколько токенов длины, настроенных выше, во время индексации. Это позволяет вам возвращать результат, основываясь на совпадающих токенах ngram, также на основе близости. Проверьте подробный синтаксис из Edge NGram Filter

HTML Strip Char Filter

Большинство веб-сайтов имеют контент в формате HTML, доступный для индексирования. Разрешение индексировать и запрашивать стандартный HTML-текст нежелательно для большинства сайтов. ElasticSearch позволяет фильтровать HTML-теги, которые не будут проиндексированы и не будут доступны для запроса.

1
2
3
4
5
6
7
8
.startObject("analyzer")
    .startObject("test_analyzer")
        .field("type", "custom")
        .field("tokenizer", "whitespace")
        .field("filter", new String[]{"lowercase", "test_filter_worddelimiter_en", "test_filter_stopwords_en", "test_filter_synonyms_en", "test_filter_snowball_en"})
        .field("char_filter", "html_strip")
    .endObject()
.endObject()

Проверьте полный синтаксис HTML Strip Char Filter для деталей. В дополнение к вышеупомянутым общим фильтрам, есть еще много доступных фильтров, позволяющих вам обогащать содержимое вашего поиска желаемым способом на основе требований конечного пользователя и ваших бизнес-данных.

Ссылка: Elasticsearch: Анализ текста для обогащения контента от нашего партнера JCG Jaibeer Malik в блоге Jai на блоге.