Практическое руководство: ранжирование результатов поиска

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

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

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

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

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

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

'see', 1 
'spot', 1 
'run', 1 
'run', 2 
'spot', 3 
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
10
0
4 255
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

вы можете добиться этого за один запрос, используя «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 и получением результатов. С помощью этого метода это происходит только один раз, а не один раз на токен, поэтому производительность увеличится, я просто не знаю, будет ли этого достаточно.

@rmbarnes - должно быть, именно здесь те операции UNION, которые я видел в db basics много лет назад, внезапно обретают смысл; Я обязательно проверим его производительность, чтобы увидеть, как он сравнивается с общей скоростью.

warren 05.11.2009 09:49

Просто не забудьте использовать UNION ALL, а не только UNION, иначе я не думаю, что вы получите несколько строк, возвращенных с тем же идентификатором, как вы хотите. - rmbarnes 06 сен.

warren 05.11.2009 09:50

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

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

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

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

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

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

Глянь сюда: http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

Другие вопросы по теме