2012-04-14 2 views
3

Привет, stackoverflow people,Как получить рейтинг поиска по нескольким факторам в сфинксе?

Мы получили проект Rails, который растет и растет, и теперь мы получаем первые проблемы с производительностью при поиске, потому что мы не знаем, как правильно использовать sphinx для наших нужд. У нас есть поисковые запросы, такие как «Java PHP Software developer». Наша проблема заключается в том, что рейтинг должен работать с несколькими вещами.

В качестве полей поиска у нас есть список тегов, описание и заголовок. Если одно из условий находится внутри одного из полей, оно должно получить, например, 2 балла. Больше очков, если оно больше в нескольких полях, но не в нескольких точках, если оно находится в одном поле более одного раза. Следующая проблема. У меня есть большой файл с синонимами, для которого также нужно проверить. Это выглядит следующим образом:

Java > Java 
Java-EE > Java 
... 

Так что, если Java-EE будет найден, он должен получить некоторые моменты тоже, но со штрафом для того, чтобы быть синонимом.

Максимальное количество очков будет 5, как в 5 звездах, которые будут отображаться. Любое быстрое решение было бы приятным, потому что на данный момент это сделано в обычном рубине, и оно замедляется, потому что мы не можем правильно ранга в сфинксе.

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

Заранее благодарим за все усилия. Все исправления и вопросы для исправления вопроса приветствуются.

ответ

1

Эта проблема с производительностью является проблемой алгоритма.

Если вы не можете выразить проблему способом использования бэкэнд-инструмента, такого как сфинкс или механизм базы данных, то вы выполняете обработку в рубине, и это легко справится с проблемой производительности.

Прежде всего, сделайте как можно больше с помощью sphinx (или любой другой поисковой системы) и базы данных, как вы можете. Чем больше предварительно перераспределены данные, поступающие в рубин, тем меньше вам нужно делать в рубиновом коде, и это, скорее всего, будет быстрее, поскольку базы данных были сильно оптимизированы за последние полвека.

Так, например, запустите сфинкс по ключевым словам. Также используйте sphinx для синонимов. Ограничьте все ответы на верхние результаты и объедините результаты. Таким образом, ваш рубиновый код будет ограничен вероятными высокими результатами вместо того, чтобы рассматривать всю базу данных записей.

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

Как вы обрабатываете исходные данные, если вы держите верхние результаты в массиве и пытаетесь сортировать или сканировать массив, у вас будет порядок N-квадратов. То есть ваш заказ будет продуктом количества необработанных записей и количества элементов, которые вы храните в своем массиве.

Лучшие алгоритмы для вашей проблемы - это очередь приоритетов, реализованная кучным контейнером или деревом b. Оба имеют порядок N-log-N (N раз журнал N), или количество необработанных данных записывает время в журнал количества элементов, которые вы будете хранить в своем контейнере.

Куча - это двоичное дерево, где каждый узел в дереве (а не только листья, но каждый узел) имеет номинальную запись. Узлы ниже каждой записи имеют более низкие ранги. Это называется условием кучи.

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

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

Теперь для записи 101 и после сравните свой ранг с корнем. Если новая запись оценивается выше, используйте алгоритм удаления, чтобы уменьшить кучу до 99 узлов (что приведет к удалению записи с наименьшим рангом в куче) и добавит новую запись в кучу.

После того, как вы просмотрите все свои записи, вы получите 100 лучших результатов. Алгоритм удаления кучи вытащит их в обратном порядке.

2

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

В качестве примера я использую поле «title», но логика может быть реплицирована для всех полей.

Индексация

Добавить два поля сфинкса ("название" и "title_synonyms"). Для каждой записи в базе данных необходимо выполнить следующие действия: -

  • Выполните DISTINCT на словах, чтобы удалить дубликаты («Рубин Разработчик/Java Developer» станет «Рубин Developer/Java» Это остановит записи от получения. две оценки для дубликатов при поиске. Это относится к «title»

  • Возьмите заголовок DISTINCT сверху и ЗАМЕНИТЕ все слова с их расширенными эквивалентами синонимов. Я бы предложил поместить синонимы в БД, чтобы упростить расширение Затем текст станет «Ruby Developer/Java-EE». Каждое слово должно быть заменено на все синонимы. Если Java имеет два синонима, они оба должны быть в поле. Это относится к «title_sy» nonyms»

Поиск

Поскольку в настоящее время существует два поля в сфинкса мы можем дать каждому из них разный вес; «title» может получить вес «10» и «title_synonyms» весом «3». Это означает, что запись должна соответствовать 4 синонимам, прежде чем она окажется выше единицы с исходным названием. Вы можете поиграть с весами в соответствии с вашими потребностями.

Предполагается, что пользователь ищет "Java Developer".Для поиска фразы необходимо выполнить следующие действия: -

  • Удалить дубликаты слов
  • Получить синонимы для каждого слова в поисковой фразе
  • Set Mode Matching в Сфинксом SPH_MATCH_EXTENDED

Вышеуказанные правила означает, что поиск в сфинксе выглядит следующим образом: -

@title "Java Developer" | @title_synonyms "Java-EE"

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

@title ("Java Developer" | "= Java = Developer") | @title_synonyms ("Java-EE" | "= Java-EE")

Для обеспечения нормальной работы вам необходимо использовать SPH_RANK_PROXIMITY_BM25 или SPH_RANK_SPH04.

Рейтинг

Вы можете попробовать любой из встроенных алгоритмов ранжирования, чтобы увидеть, что результаты выглядят. Я рекомендую SPH_RANK_MATCHANY или SPH_RANK_WORDCOUNT как начало.

Для близости и точного соответствия рейтинга используйте SPH_RANK_PROXIMITY_BM25, SPH_RANK_SPH04 или SPH_RANK_EXPR, где вы можете использовать свой собственный алгоритм.

Заключение

Теперь вы должны иметь поиск, который одновременно является быстрым и точным. Ваше небольшое приложение должно быть выполнено с помощью вашего приложения Ruby, и большая часть работы выполняется внутри sphinx (где это должно быть).

Надеюсь, что это поможет ...

+0

Спасибо за ваш ответ, мы попробуем! – outsmartin

Смежные вопросы