Статьи

Solr находит лучшее время для публикации вопросов на StackOverflow

Итак, скажем, у вас есть важный технический вопрос, на который просто нужно ответить:

«В чем разница между JavaScript и Java?»

Обычно вы размещаете его в StackOverflow и добавляете огромную награду, чтобы получить быстрый ответ  . Но вы отправили награду за последние 10 вопросов, и теперь ваша репутация переполнения стека равна 4.

Не беспокойтесь, возможно, если вы  правильно рассчитаете  время своего вопроса, вы сможете поймать всех тех программистов на Java / JavaScript, когда они отвечают на такие важные вопросы, как ваш. И как вы узнаете, когда наступит это волшебное время? Проще говоря, вы индексируете весь  дамп данных StackOverflow  в Solr и рассматриваете Solr как аналитический движок StackOverflow. (Эй, вы можете не знать разницу между Java и JavaScript, но вы не дураки, когда дело доходит до Solr!)

Так вот как это выглядит. Файл post.xml в дампе данных StackOverflow содержит все вопросы и ответы на сайте. Сообщения содержат следующие поля:

  • Id  — уникальный идентификатор для вопроса или ответа.
  • ParentId  — если этот пост является ответом, ParentId ссылается на соответствующий вопрос.
  • PostTypeId  — 1 для вопроса, 2 для ответа.
  • CreationDate  — по Гринвичу.
  • Тело  — Содержание поста.
  • Заголовок  — Вы догадались.
  • Теги  — список тем для этого вопроса.

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

  • CreationMonth  — с 1 по 12.
  • Час создания  — от 0 до 23.
  • CreationMinute  — от 0 до 60.
  • CreationDayOfWeek  — от 0 (понедельник) до 6.
  • CreationDayOfYear  — от 1 до 365.

Теперь все, что вам нужно сделать, чтобы узнать, что золотое время для того, чтобы задать вопрос, — это найти время, когда большинство людей отвечают на вопросы о Java и Javascript.

http://localhost:8983/solr/collection1/select?q=Tags:(java AND javascript)&fq=PostTypeId:2&facet=on
&facet.field=CreationDayOfYear&f.CreationDayOfYear.facet.limit=365&facet.field=CreationDayOfWeek&facet.field=CreationHour&facet.sort=index

Словом, запрос  q предназначен для всех вопросов, помеченных как java, так и javascript. Эти результаты фильтруются  fq так, что возвращаются только ответы. Остальные параметры включают отсортированные списки фасетов для времени года, недели и дня. Так что, как только вы получите запрос Solr, вы узнаете лучшие времена года, недели и дня, чтобы задать свои вопросы. Вы нажимаете Enter и  SNAP  нет результатов! Что дает?!

После небольшого исследования выясняется, что  поле имеют только  вопросы  ( PostTypeId=1), Tagsпоэтому очевидно, что вы не сможете получить количество  ответов,  помеченных тегом Java AND JavaScript. Так ты потонул? Нет ли способа узнать, когда вопросы о Java / JavaScript привлекают все внимание? Собираетесь ли вы сделать какую-то сумасшедшую работу по индексированию MapReduce, чтобы связать ответы с соответствующими тегами? Оказывается  нет !

Solr присоединиться к спасению

Это верно, функциональность  Solr Join  идеально подходит для этой конкретной проблемы. Давайте посмотрим, как это будет работать:

http://localhost:8983/solr/collection1/select
q={!join from=Id to=ParentId}Tags:(java AND javascript)&facet=on
&fq=PostTypeId:2&facet.field=CreationDayOfYear&f.CreationDayOfYear.facet.limit=365&facet.field=CreationDayOfWeek&facet.field=CreationDayOHour&facet.sort=index

Как видите, единственная разница здесь — странная запись в начале q параметра.

{!join from=Id to=ParentId}

Это нотация локальных параметров Solr  , и вот что говорит Solr: во-первых, у вас есть  join; на самом деле это синтаксический сахар только для первого параметра. Это то же самое, что сказать  type=join. Это означает, что вместо использования   режима запроса lucene или  dismaxмы будем использовать  join режим запроса. Далее у нас есть  from=Id. Чтобы выразить это в терминах SQL, это означает, что мы будем использовать Id в качестве первичного ключа. Наконец, мы имеем,  to=ParentId что, как вы уже догадались, подразумевает, что  ParentId будет использоваться в качестве внешнего ключа.

Когда мы выдаем запрос, Solr сначала получает список документов, соответствующих запросу  Tags:(java AND javascript). Затем для каждого документа в этом наборе результатов Solr извлекает набор документов, которые  ParentId соответствуют Ids в исходном наборе.

В мире SQL этот запрос будет выглядеть так:

SELECT * 
FROM collection1
WHERE ParentId IN (SELECT Id FROM collection1 whereTag="(Java and Javascript")

И  теперь,  как только вы выполните запрос, вы получите следующий ответ Solr:

<lstname="CreationDayOfYear"><intname="1">2</int><intname="2">4</int><intname="3">12</int><intname="4">5</int><intname="5">10</int><intname="6">8</int><intname="7">2</int><!--snip--><intname="362">9</int><intname="363">3</int><intname="364">4</int><intname="365">5</int></lst><lstname="CreationHour"><intname="1">63</int><intname="2">44</int><intname="3">122</int><intname="4">65</int><intname="5">120</int><intname="6">48</int><intname="7">62</int><!--snip--><intname="21">29</int><intname="22">63</int><intname="23">434</int></lst><lstname="CreationDayOfWeek"><intname="0">371</int><intname="1">390</int><intname="2">383</int><intname="3">422</int><intname="4">369</int><intname="5">266</int><intname="6">272</int></lst>

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

Также, если вам интересно играть с этим самим, проверьте  репо на GitHub .