Lucens лучший способ начать работу с запросов

Я хочу иметь возможность выполнять следующие типы запросов:

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

Пример:

Для документов:

  • Video1Title = Море синее
  • Video2Title = Дикое море
  • Video3Title = Дикое море
  • Video4Title = Все, что угодно на берегу моря

Если я ищу "море", я хочу получить

  • "Video1Title = Море синее"

сначала следуют все остальные документы, содержащие слово «море» в названии, но не в начале.

Если я ищу "Дикое море", я хочу получить

  • Video2Title = Дикое море
  • Video3Title = Дикое море

сначала следуют все другие документы, в названии которых есть «Дикое» или «Море», но нет префикса «Дикое море».

Если я ищу «Seasi», я ничего не хочу получать (мне все равно на токенизацию ключевых слов и префиксные запросы).

Теперь, AFAIKS, нет реального способа сказать Lucene «найди мне документы, в которых слово1, слово2 и т. д. находятся на позициях 1, 2, 3 и т. д.».

Существуют «обходные пути» для имитации такого поведения:

  • Проиндексируйте поле дважды. В field1 у вас есть токенизированные слова (возможно, с использованием StandardAnalyzer), а в field2 все они собраны в один элемент (с использованием KeywordAnalyzer). Затем, если вы ищете что-то вроде:

    +(поле1:слово1 слово2 слово3) (поле2:"слово1 слово2 слово3*")

эффективно сообщая Lucene: «Документы должны содержать слово1, слово2 или слово3 в заголовке, и, кроме того, те, которые соответствуют «заголовок начинается с >слова1 слово2 слово3‹», лучше (получают более высокий балл).

  • Добавьте «lucene_start_token» в начало поля при их индексации, чтобы Video2Title = Wild sea индексировалось как «title:lucene_start_token Wild sea» и так далее для остальных.

Затем выполните запрос, чтобы:

+(название:море) (название:"lucene_start_token море")

и заставить Lucene вернуть все документы, которые содержат мое поисковое слово (слова) в заголовке, а также дать более высокий балл тем, кто соответствует «lucene_start_token + поисковые слова»

Мой вопрос в том, действительно ли существуют лучшие способы сделать это (возможно, используя PhraseQuery и Термин position)? Если нет, то что из вышеперечисленного лучше с точки зрения производительности?


person Shivan Dragon    schedule 21.02.2013    source источник


Ответы (2)


Для этого вы можете использовать Lucene Payloads. Вы можете дать собственное повышение для каждого члена значения поля.

Итак, когда вы индексируете свои заголовки, вы можете начать использовать коэффициент повышения 3 (например):

title: дикий|3.0 существа|2.5 синий|2.0 море|1.5

title: море|3.0 существа|2.5

Индексируя таким образом, вы повышаете ближайшие термины к началу заголовка.

Основная проблема при использовании этого подхода заключается в том, что вам нужно токенизировать самостоятельно и добавлять всю эту информацию о повышении «вручную», поскольку анализатору нужен текст, структурированный таким образом (term1|1.1 term2|3.0 term3).

person Samuel García    schedule 26.02.2013
comment
Это отличный способ сделать это. Это правда, что это усложняет запрос по сравнению с другими подходами, но я думаю, что это наиболее эффективно (без дополнительных полей, тяжелая работа выполняется во время индексации, а не во время запроса). Единственное потенциальное падение, которое я вижу, это когда вы начинаете с уже сложного запроса. Сбалансировать это с новыми запросами, добавленными этим подходом, может быть сложно. - person Shivan Dragon; 26.02.2013
comment
Почему бы не полагаться на позиции и не использовать SpanFirstQuery как предложено заголовок/">здесь? Он полностью соответствует вашим требованиям? - person javanna; 02.03.2013

Что вы можете сделать, так это проиндексировать заголовок и каждый токен отдельно, например. текст wild deep blue endless sea будет проиндексирован следующим образом:

title: wild deep blue endless sea
t1: wild
t2: deep
t3: blue
t4: endless
t5: sea

Затем, если кто-то запрашивает «дикие глубины», запрос будет переписан в

title:"wild deep" OR (t1:wild AND t2:deep)

Таким образом, вы всегда найдете все совпадающие документы (если они соответствуют title), но совпадающие t1..tN токены повысят оценку соответствующих документов.

person mindas    schedule 25.02.2013
comment
спасибо, это хорошая идея. И таким образом я могу сопоставлять только целые слова, только если захочу (в отличие от моего 1 дополнительного поля, которое анализируется по ключевому слову и которое затем используется для запроса префикса (оканчивающегося на *), где я никогда не знаю, соответствует ли оно целому слово или нет в конце). Мне просто нужно использовать те же анализаторы, которые я использую для поля заголовка, чтобы получить все токены, а затем переиндексировать каждый из них в отдельном поле. Правильно? :) - person Shivan Dragon; 26.02.2013
comment
Да, вы правы - вы должны использовать один и тот же анализатор. Я должен был, вероятно, упомянуть об этом в своем ответе. - person mindas; 26.02.2013
comment
Это отличный подход, лучше тех, которые я нашел сам (упомянутых в вопросе). В конечном итоге у вас будет много полей, и это может привести к проблемам, если размер индекса уже очень большой (индекс разбивается чаще и/или требуется больше памяти кучи). Однако для управляемого размера индекса этот подход представляет собой отличный баланс простоты реализации и точности результатов. - person Shivan Dragon; 26.02.2013