Запрос/фильтрация по полному значению поля Elasticsearch с регулярным выражением

Мы используем Nutch для обхода некоторых сайтов, отправляем индекс в Elasticsearch и используем настраиваемый пользовательский интерфейс для поиска, вызывая API Elasticsearch.

Проблема в том, что мне нужно просканировать некоторые сайты но исключить их из индекса Elasticsearch (например, мне нужно просканировать A, B и C, но исключить B из индекса) Мы не смогли найти решение которые мы могли бы реализовать на этапе отправки индекса в Elasticsearch, поэтому мы решили попробовать отфильтровать на странице запроса Elasticsearch.

Индекс elasticsearch (который создает nutch) содержит поле URL. Это прекрасно, но проблема в том, что Elasticsearch (насколько я понимаю) проанализировал это, используя полнотекстовый метод, где, например, http://www.somesite.com фактически разбивается на 4 или более клавиатур (http,www,somesite,com). Я не могу понять, как построить запрос Elasticsearch, который, например, исключит эти URL-адреса:

http://www.somesite.com/contact/

http://www.somesite.com/privacy/

Когда я запускаю свой DSL-запрос, кажется, что он разбивает его на части (я имею в виду http,www,somesite,com) и объединяет их вместе, что всегда возвращает все результаты.

Например:

{
    "query": {
        "must": { "match": { "url": "http://www.somesite.com/page1" }}
    }
}

Всегда возвращает все результаты.

Кто-нибудь делал что-то подобное?


person ColdAir    schedule 29.01.2018    source источник
comment
Не могли бы вы предоставить карту, которая у вас есть (тот, который создает nutch)? Можете ли вы в принципе управлять отображением?   -  person Nikolay Vasiliev    schedule 30.01.2018


Ответы (2)


Для регулярного выражения попробуйте-

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-regexp-query.html

Вы можете проиндексировать URL-адрес как ключевое слово и просто выполнить терминальный запрос по нему или не анализировать это поле, установив not_analysed в сопоставлении.

Токенизатор ключевых слов -

https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-keyword-tokenizer.html

О не_анализе читайте здесь-

https://www.elastic.co/guide/en/elasticsearch/guide/current/mapping-intro.html

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

person xrage    schedule 29.01.2018
comment
Nutch отправляет данные в E.S., поэтому я не могу контролировать, какие типы полей E.S. создает. Я бы предпочел не изменять их позже, потому что в следующий раз, когда нам нужно будет заново создать индекс, мне нужно будет не забыть применить шаги. В чем разница между termи query? - person ColdAir; 29.01.2018
comment
Я чувствую, что вы спрашиваете разницу между термином и запросом соответствия. stackoverflow.com/a/40124408/1523811 - person xrage; 30.01.2018
comment
Вы также можете попробовать регулярное выражение. - person xrage; 30.01.2018

Вы не указали, какую версию Nutch используете. Есть несколько способов сделать то же самое, используя Nutch (не принимая во внимание ваш бэкэнд Solr/ES).

Одним из вариантов является реализация собственного IndexingFilter (https://github.com/apache/nutch/blob/master/src/java/org/apache/nutch/indexer/IndexingFilter.java#L55-L56) в метод filter, если вы вернете null, документ будет отброшен (т.е. не проиндексирован), поэтому в вашей реализации вы можете иметь свою собственную логику (например, сопоставление имени хоста с URL-адресом) и отклонить те документы, которые вы не хотите индексировать .

В Nutch v1.14 был добавлен новый общий способ сделать то же самое, новый IndexingFilter, который поддерживает общие выражения JEXL (https://commons.apache.org/proper/commons-jexl/reference/syntax.html), чтобы можно было исключить некоторые документы, соответствующие определенному условию. Преимущество этого подхода в том, что вам не нужно писать код. Недостаток в том, что сейчас hostname недоступен для фильтрации, но вы можете использовать URL с регулярным выражением. На самом деле, если вы используете фильтр index-basic, то имя хоста должно быть доступно по ключу doc.host в контексте JEXL.

Что касается стороны вопроса ES, по умолчанию Nutch не применяет никакого сопоставления при отправке документов в ES. Это означает, что ES попытается просмотреть содержимое каждого поля, а затем выбрать наилучшее возможное отображение. Например, в этом случае я думаю, что поле url отображается как универсальное текстовое поле (которое действительно разбивает содержимое на токены).

Одним из решений может быть то, что перед отправкой документов в ES (индексация на Nutch) вы можете вручную создать сопоставление для тех полей, тип которых вам известен, например, url в виде строки/ключевого слова. Имейте в виду, что это не должно вызывать никаких проблем с Nutch, если вы не устанавливаете конфликтующие сопоставления, но обычно настраиваете все как строку/ключевое слово и видите, какие поля создаются, достаточно для определения собственного сопоставления.

Но если вы хотите только фильтровать контент перед индексированием, то, вероятно, лучшим подходом являются два других решения.

person Jorge Luis    schedule 30.01.2018