Статьи

Использование случаев граненого поиска для Apache Solr

В этом посте я пишу о некоторых случаях использования аспектов для Apache Solr. Пожалуйста, отправьте свои собственные идеи в комментариях.
Этот пост разделен на следующие части:

  • Какие грани?
  • Как включить и использовать простые аспекты?
  • Каковы другие варианты использования?
     — Навигация по категориям
     — Автозаполнение
     — Тенденции ключевых слов или ссылок
     — RSS-каналы
  • Вывод

Какие грани?

В Apache Solr элементы для навигационных целей называются фасетами . Имейте в виду, что Solr предоставляет фильтры запросов (указанных через http-параметр fq), которые отфильтровывают документы из результатов поиска. Напротив, фасетные запросы предоставляют только информацию (количество документов) и не изменяют итоговые документы, то есть они обеспечивают «фильтрацию запросов для будущих запросов». Поэтому определите фасетный запрос, а затем посмотрите, сколько документов я могу ожидать, если бы применил связанный фильтр-запрос.

Но картинка — из этого грандиозного введения — стоит тысячи слов:

Что ты видишь?

  • Вы видите различные аспекты, такие как производитель, разрешение, …
  • Каждый аспект имеет некоторые ограничения, где пользователь может легко фильтровать результаты поиска.
  • Хлебная крошка показывает все выбранные недостатки и позволяет их удалить

Все эти значения могут быть извлечены из результатов поиска Solrs и могут быть определены во время запроса, что выглядит удивительно, если вы пришли из FAST ESP. Тем не менее поля, на которых вы выполняете огранку, должны быть проиндексированы и не отмечены. Например, строка или целое число. Но тип полей, для которых вы хотите использовать фасетку, не должен быть текстовым типом по умолчанию, который маркируется.

В Solr у вас есть

Обычные фасеты могут быть полезны, если в ваших документах есть строковое поле производителя, например, документ может находиться в сегменте «Sony» или «Nikon». Напротив, вам понадобятся фасетные запросы для целых чисел, таких как цены. Например, если указать фасетный запрос от 0 до 10 EUR, Solr на лету вычислит все документы, попадающие в эту корзину. Но фасетные запросы становятся относительно неудобными, если у вас есть несколько одинаковых диапазонов, таких как 0-10, 10-20, 20-30, … EUR. Тогда вы можете использовать диапазон запросов.

Фасеты даты являются запросами специального диапазона. В качестве примера посмотрите на этот скриншот из jetwick :

где здесь интервал (который называется промежутком) для каждого сегмента равен одному дню.

Для хорошего знакомства с аспектами загляните в эту публикацию или воспользуйтесь Solr Wiki здесь .

Как включить и использовать простые аспекты?

Как указано ранее, они могут быть включены во время запроса. Для http API вы добавляете «& facet = true & facet.field = manu» к обычному запросу «http: // localhost: 8983 / solr / select? Q = *: *». Для SolrJ вы делаете:

new SolrQuery("*:*").setFacet(true).addFacetField("manu");

В XML, возвращенном с сервера Solr, вы получите что-то вроде этого — снова из этого поста :

<lst name="facet_fields">
<lst name="manu">
<int name="Canon USA">17</int>
<int name="Olympus">12</int>
<int name="Sony">12</int>
<int name="Panasonic">9</int>
<int name="Nikon">4</int>
</lst>
<pre></lst></pre>

Чтобы получить это с помощью SolrJ, вам, конечно, не нужно прикасаться к любому XML. Просто получите фасетные объекты:

List<FacetField> facetFields = queryResponse.getFacetFields();

Чтобы добавить фасетные запросы, укажите их с помощью addFacetQuery:

solrQuery.addFacetQuery("quality:[* TO 10]").addFacetQuery("quality:[11 TO 100]");

И как бы вы запросили документы, которые не имеют значения для этого поля? Это легко : q = -field_name: [* TO *]

Теперь я покажу вам, как я реализовал грани даты в jetwick :

q.setFacet(true).set(“facet.date”, “{!ex=dt}dt”).
set(“facet.date.start”, “NOW/DAY-6DAYS”).
set(“facet.date.end”, “NOW/DAY+1DAY”).
set(“facet.date.gap”, “+1DAY”);

 

С этим запросом вы получаете 7-дневные сегменты, которые визуализируются через:

Важно отметить, что вам нужно будет использовать локальные параметры, такие как {! Ex = dt}, чтобы убедиться, что если пользователь применяет фасет (использует фасетный запрос как запрос фильтра), то другие фасетные запросы не получат счет из 0. На картинке запрос фильтра был fq = {! tag = dt} dt: [2010-12-04T00: 00: 00.000Z + TO + 2010-12-05T00: 00: 00.000Z]. Опять же: запрос фильтра должен начинаться с {! Tag = dt}, чтобы это работало. Посмотрите исходный код DateFilter или это для получения дополнительной информации.

Имейте в виду, что вам придется настроить filterCache , чтобы сохранить производительность зеленой. Также важно использовать разогревающие запросы, чтобы избежать тайм-аутов и предварительно заполнить кэши старыми «тяжелыми» использованными данными.

Каковы другие варианты использования?

1. Категория навигации

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

Есть два относительно похожих решения этой проблемы. Я опишу один из них:

  • Создайте многозначное строковое поле с именем ‘category’. Используйте идентификатор категории (или имя, если вы хотите избежать запросов к БД).
  • У вас есть дерево категорий. Убедитесь, что документ получает не только конечную категорию, но и все категории вплоть до корневого узла.
  • Теперь фасетируйте над полем категории с «-1» в качестве предела
  • Но что, если вы хотите отображать только категории одного уровня? Например, если вы не хотите другой уровень за раз или если их слишком много.
    Затем индексируйте поле категории ala <level> _category. Для этого вам понадобится полное дерево категорий в оперативной памяти при индексации. Затем используйте facet.prefix = <level> _, чтобы отфильтровать список категорий для уровня.
  • Нажатие на запись категории должно привести к запросу фильтра ala fq = category: ”<levle> _categoryId”
  • Небольшая хитрость в том, что ваш пользовательский интерфейс или средний уровень должны проанализировать уровень, например, 2 и добавление 2 + 1 = 3 к запросу: facet.prefix = 3_
  • Если вы отфильтруете уровень, то останется один вопрос:
    Q: как вы можете отобразить путь от выбранной категории до корневой категории?
    A: Либо получите родителей категории через DB, что легко, если вы храните идентификаторы категорий в Solr, а не имена категорий.
    Или получить родителей из списка параметров, который немного сложнее, но выполнимо. В этом случае вам нужно хранить названия категорий в Solr.

Пожалуйста, дайте мне знать, если это объяснение имеет смысл для вас или если вы хотите увидеть это в действии — я не хочу делать рекламу для наших клиентов здесь :-)

Кстати, второй подход, который я имею в виду: вместо использования facet.prefix вы можете использовать динамические поля ala category_ <level> _s

2. Автозаполнение

Проблема: вы хотите показать предложения в качестве пользовательских типов.

Вам понадобится многозначное поле ‘tag’. Для jetwick я использую шумовой фильтр слов, чтобы получать только термины «с информацией» в поле тега из очень шумного текста твита. Если вы используете фильтр shingle, вы даже можете создавать предложения фраз. Но я опишу здесь предложение «еще одно слово», которое будет предлагать только следующее слово (не совсем другую фразу).

Для этого создайте следующий запрос, когда пользователь вводит некоторые символы (см. Метод getQueryChoices в SolrTweetSearch ):

  • Используйте старый запрос со всеми запросами фильтра и т. Д., Чтобы обеспечить контекстно-зависимое автозаполнение (т. Е. Только давать предложения, которые приведут к результатам)
  • разбить запрос на «завершенные» термины и один «сделать» термин. Например, если вы введете «Майкл Джек», то
    Майкл завершен (заканчивается пробелом), и Джек должен быть завершен
  • установите термин запроса старого запроса в майкл и добавьте facet.prefix = jack
  • установить ограничение по фасету до 10
  • Прочитайте 10 предложений из фасетного поля, но исключите уже завершенные термины.

Реализация для jetwick , который использует Apache Wicket доступен в SearchBox исходный файл , который использует MyAutoCompleteTextField и метод getQueryChoices из SolrTweetSearch . Но перед тем, как реализовать автозаполнение с помощью фасетов, ознакомьтесь с этой документацией . А если вы не хотите использовать wicket, то есть библиотека автозаполнения jquery, особенно для solr — слой пользовательского интерфейса не требуется.

3. Актуальные ключевые слова или ссылки

Как и при автозаполнении, вам понадобится поле тега или ссылки в вашем индексе. Затем используйте фасеты как показатель того, насколько важен термин. Если вы сейчас сделаете запрос, например, solr, вы получите ключевые слова и ссылки в зависимости от фильтров. Например, вы можете выбрать разные дни, чтобы увидеть изменения:

Панель ключевых слов реализована в TagCloudPanel, а список ссылок доступен как UrlTrendPanel .

Конечно, было бы неплохо, если бы мы получили суммарный балл по каждой ссылке вместо простого «подсчета», чтобы спаммеры не могли попасть в этот список. Для этого загляните в эту проблему JIRA и в StatsComponent . Как я объяснил в проблеме JIRA, эту замечательную функцию можно смоделировать с помощью функции группировки результатов .

4. RSS каналы

Если вы войдете на jetwick.com, вы увидите, как эта идея реализована. Каждый пользователь может иметь разные сохраненные поиски . Например, у меня один поиск по «apache solr» и один по «wikileaks». Каждый поиск может содержать дополнительные фильтры, такие как только немецкий язык или сортировать по ретвитам. Теперь задача состоит в том, чтобы преобразовать этот запрос в запрос фасета:

  • вставить AND между запросом и всем запросом фильтра
  • удалить все фильтры даты
  • добавить один фильтр даты с датой последнего обработанного поиска («последняя дата»)

Затем вы увидите, сколько новых твитов доступно для каждого сохраненного поиска:

Обновление : не нужно нажимать кнопку «Обновить», чтобы увидеть счет. Обновление счетчика выполняется в фоновом режиме через JavaScript.

Вывод

Существует множество приложений для граненого поиска. Их очень удобно использовать. Хорошо, «взлом локальных параметров» немного пугающий, но эй: он работает:-)

Приятно, что я могу указывать разные фасеты для каждого запроса в Solr, с помощью этой функции вы можете создавать персонализированные фасеты, как это было объяснено в разделе «RSS-каналы».

Одним из улучшений для аспектов, реализованных в Solr, может быть функция, которая не рассчитывает количество. Вместо этого он суммирует fieldA для документов с тем же значением в fieldB или даже возвращает оценку для фасета или запроса фасета. Улучшить вариант использования «Тенденции ключевых слов или ссылок».

 

От http://karussell.wordpress.com/2010/12/08/use-cases-of-faceted-search-for-apache-solr/