Внедрение схемы сравнения ключевых слов (обратный поиск)

У меня постоянно растущая база ключевых слов. Мне нужно проанализировать входящие текстовые вводы (статьи, каналы и т. д.) И найти, какие ключевые слова из базы данных присутствуют в тексте. База ключевых слов намного больше текста.

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

Самой наивной реализацией было бы создание простого запроса SELECT к таблице ключевых слов с гигантским предложением IN, перечисляющим все найденные ключевые слова.

SELECT user_id,keyword FROM keywords WHERE keyword IN ('keyword1','keyword2',...,'keywordN');

Другой подход - создать хеш-таблицу в памяти (используя что-то вроде memcache) и таким же образом проверить ее.

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

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

David Raznick 03.01.2009 05:23

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

Eran Galperin 03.01.2009 05:50

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

David Raznick 03.01.2009 06:34

это тоже может быть полезно - я наблюдаю аналогичную проблему: stackoverflow.com/questions/47762/how-to-ranking-search-resu‌ lts

warren 04.03.2009 12:26
Стоит ли изучать 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 и хотите разрабатывать...
3
4
1 414
6

Ответы 6

Я не на 100% понимаю, о чем вы спрашиваете, но, может быть, вы ищете инвертированный индекс?

Обновлять:

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

Разделите новый документ на токены и вставьте токены в паре с идентификатором документа в инвертированную индексную таблицу. Таблица инвертированного индекса (скорее денормализованная):

inverted_index
-----
document_id keyword

Если вы ищете 3 ключевых слова вручную:

select document_id, count(*) from inverted_index
  where keyword in (keyword1, keyword2, keyword3)
  group by document_id 
  having count(*) = 3

Если у вас есть таблица ключевых слов, которые вам нужны, просто используйте внутреннее соединение, а не операцию in ():

keyword_table
----
keyword othercols

select keyword_table.keyword, keyword_table.othercols from inverted_index 
   inner join keyword_table on keyword_table.keyword=inverted_index.keyword
   where inverted_index.document_id=id_of_some_new_document

это ближе к тому, что вы хотите?

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

Nick Gerakines 02.01.2009 23:54

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

Eran Galperin 03.01.2009 00:11

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

Eran Galperin 03.01.2009 01:29

Я бы предположил, что если вы правильно проиндексируете это, это действительно будет довольно эффективно.

ʞɔıu 03.01.2009 03:06

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

Eran Galperin 03.01.2009 03:22

Я бы сделал здесь 2 вещи.

Во-первых (и это не имеет прямого отношения к вопросу) я бы разбил ключевые слова пользователей по пользователям. Наличие большего количества таблиц с меньшим количеством данных, в идеале на разных серверах для распределенного поиска, где срезы или диапазоны пользователей существуют на разных срезах. Ака, все данные usera существуют на первом срезе, userb - на втором и т. д.

Во-вторых, у меня была бы какая-то хеш-таблица в памяти для определения наличия ключевых слов. Скорее всего, это тоже будет федеративным, чтобы распространять поисковые запросы. Для n серверов с существованием ключевого слова хешируйте ключевое слово и измените его на n, а затем распределите диапазоны этих ключей по всем серверам memcached. Этот быстрый способ позволяет вам сказать, что ключевое слово x отслеживается, хешировать его и определить, на каком сервере находится было бы. Затем выполните поиск и соберите / объедините отслеживаемые ключевые слова.

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

Вкратце: SQL здесь не идеальное решение.

Разделение таблицы ключевых слов по пользователям может быть не очень хорошей идеей - у каждого пользователя есть только 4-5 ключевых слов, а пользователей много - в результате получится много таблиц. Как вы сказали, я склоняюсь к решению, отличному от SQL.

Eran Galperin 03.01.2009 00:08

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

Nick Gerakines 03.01.2009 00:11

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

Eran Galperin 03.01.2009 07:49

В общем,

  1. разбить текст на слова

    б. преобразовать слова обратно в каноническую корневую форму

    c. отбросить общие союзные слова

    d. удалить дубликаты

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

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

Есть ли опыт работы с таблицей в памяти по сравнению с массивом кэша памяти? Я бы подумал, что доступ к массиву будет быстрее?

Eran Galperin 03.01.2009 00:09

Проще выполнить JOIN с таблицей с использованием механизма хранения MEMORY, чем с memcached.

Bill Karwin 03.01.2009 01:37

Думали ли вы о переходе на полнотекстовое решение, такое как Сфинкс?

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

Вот блог об использовании Sphinx в качестве решения для полнотекстового поиска в MySQL.

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

Eran Galperin 03.01.2009 01:48

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

Вы можете найти реализацию в fgrep. Более того, Престон Бриггс написал довольно хорошую реализацию на C, которая выполняет именно тот поиск по ключевым словам, о котором вы говорите. (Он ищет в программах вхождения «интересных» идентификаторов.) Реализация Preston распространяется как часть Инструмент грамотного программирования Noweb. Вы можете найти способ вызвать этот код из PHP или переписать его на PHP - само распознавание составляет около 220 строк C, а основная программа - еще 135 строк.

Все предлагаемые решения в том числе Aho-Corasick имеют следующие общие свойства:

  • Этап предварительной обработки, который занимает время и пространство, пропорциональное количеству ключевых слов в базе данных.

  • Шаг поиска, который занимает время и пространство, пропорциональное длине текста плюс количеству найденных ключевых слов.

Aho-Corasick предлагает значительно лучшие константы пропорциональности на этапе поиска, но если ваши тексты небольшие, это не имеет значения. Фактически, если ваши тексты маленькие, а ваша база данных большая, вы, вероятно, захотите минимизировать объем памяти, используемый на этапе предварительной обработки. Структура данных DAWG Эндрю Аппеля из самая быстрая программа скрэббла в мире, вероятно, поможет.

Я не ищу слова в тексте - я превращаю текст в слова, а затем сравниваю их с базой данных слов.

Eran Galperin 03.01.2009 02:03

Код Престона делает именно то, что вы хотите. Он объединяет токенизацию и поиск за один шаг. Вы предоставляете список ключевых слов, строите автомат, а затем нажимаете на строку автоматом.

Norman Ramsey 03.01.2009 02:19

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

Eran Galperin 03.01.2009 02:28

Хорошо, с добавлением этой важной информации любой простой шаг предварительной обработки в базе данных подойдет - добавит все ключевые слова в хеш-таблицу. Затем разметьте свой небольшой текст, найдите каждое слово в хеш-таблице, и все готово. Aho-Corasick тоже подойдет, но вам не нужны сложности.

Norman Ramsey 03.01.2009 02:35

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

Eran Galperin 03.01.2009 02:45

Похоже, у вас уже есть подход, который работает, поэтому вам не нужна новая идея.

Norman Ramsey 03.01.2009 06:20

Мой подход работает, но я знаю только его. Просто проверяю, знают ли люди что-нибудь получше - поскольку здесь проблема с производительностью.

Eran Galperin 03.01.2009 07:47

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

Norman Ramsey 03.01.2009 23:03

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

Eran Galperin 04.01.2009 00:22

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

http://www.gtoal.com/wordgames/spell/multiscan.c.html

Один друг сделал несколько хаков в моем коде после того, как я впервые разместил его в списке рассылки программистов wordgame, и его версия, вероятно, более эффективна:

http://www.gtoal.com/wordgames/spell/multidawg.c.html

Хорошо масштабируется ...

грамм

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