Как: Рейтинг результатов поиска - PullRequest
9 голосов
/ 06 сентября 2008

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

постановка задачи:

  • пользователь вводит несколько ключевых слов / токенов
  • приложение ищет совпадения с токенами
  • нужен один результат для каждого токена
    • то есть, если в записи 3 токена, мне нужен идентификатор записи 3 раза
  • ранжировать результаты
    • назначить X очков за совпадение токена
    • сортировка идентификаторов записей по точкам
    • если значения точек совпадают, используйте дату для сортировки результатов

Что я хочу сделать, но не понял, это отправить 1 запрос, который возвращает что-то похожее на результаты in (), но возвращает дублированный идентификатор записи для каждого совпадения токена для каждого идентификатора записи. проверено.

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

редактировать
Я уже разбил токены на записи, так что, например, «see spot run» имеет идентификатор записи 1 и три токена, «see», «spot», «run», и они находятся в отдельной таблице токенов, с соответствующими им идентификаторами записей, поэтому таблица может выглядеть так:

'see', 1 
'spot', 1 
'run', 1 
'run', 2 
'spot', 3 

Ответы [ 4 ]

6 голосов
/ 07 сентября 2008

Вы можете достичь этого за один запрос, используя 'UNION ALL' в MySQL.

Просто переберите токены в PHP, создав UNION ALL для каждого токена:

например, если токены 'x', 'y' и 'z', ваш запрос может выглядеть примерно так

SELECT * FROM `entries` 
WHERE token like "%x%" union all 
    SELECT * FROM `entries` 
    WHERE token like "%y%" union all 
        SELECT * FROM `entries` 
        WHERE token like "%z%" ORDER BY score ect...

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

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

3 голосов
/ 08 сентября 2008

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

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

Смотрите здесь: http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

1 голос
/ 07 сентября 2008

Если вы используете шаблон UNION ALL, вы также можете включить в свой запрос следующие части:

SELECT COUNT(*) AS C
...
GROUP BY ID
ORDER BY c DESC

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

0 голосов
/ 08 сентября 2008

Вероятно, вы получите гораздо лучшую производительность, если будете использовать структуру данных, предназначенную для задач поиска, а не базу данных. Например, вы можете попытаться создать инвертированный индекс . Однако, вместо того, чтобы писать это самостоятельно, вы можете захотеть взглянуть на что-то вроде Lucene , которое выполняет большую часть работы за вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...