Как быстро искать названия книг? - PullRequest
8 голосов
/ 08 мая 2011

У меня есть база данных около 200 тыс. Книг.Я хочу, чтобы мои пользователи могли быстро найти книгу по названию.Теперь некоторые заголовки могут иметь префикс, например, A, THE и т. Д., А также могут иметь номера в заголовке, поэтому поиск 12 должен соответствовать книгам с «12», «двенадцать» и «дюжина» в заголовке.Это будет работать через AJAX, поэтому мне нужно убедиться, что запрос к базе данных действительно быстрый.

Я предполагаю, что большинство пользователей будут пытаться искать, используя некоторые слова из названия, поэтому я думаю разделить всеназвания в слова и создать отдельную таблицу базы данных, которая будет отображать слова в названия.Тем не менее, я боюсь, что это может не дать лучших результатов.Например, название книги может состоять из 2 или 3 часто используемых слов, и я могу получить список книг с более длинными названиями, которые содержат все 2-3 слова, и ту, которую я ищу, потерянную, как иголка в стоге сена.Кроме того, поиск книги с большим количеством слов в заголовке может замедлить запрос из-за большого количества предложений OR.

В основном я ищу способ:

  • быстро находите результаты
  • сортируйте их по релевантности.

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

PS В настоящее время я использую MySQL, но при необходимости могу переключиться на что угодно.

Ответы [ 5 ]

1 голос
/ 08 мая 2011

Apache Lucene с Solr , безусловно, очень хороший вариант для вашей проблемы

Вы можете напрямую связать Solr / Lucene для прямой индексации базы данных MySQL.Вот простое руководство о том, как связать базу данных MySQL с Lucene / Solr: http://www.cabotsolutions.com/2009/05/using-solr-lucene-for-full-text-search-with-mysql-db/

Вот преимущества и недостатки использования Lucene-Solr вместо полнотекстового поиска MySQL: http://jayant7k.blogspot.com/2006/05/mysql-fulltext-search-versus-lucene.html

1 голос
/ 08 мая 2011

Использование SOUNDEX - лучший способ, как мне кажется.

SELECT
  id,
  title
FROM products AS p
WHERE p.title SOUNDS LIKE 'Shaw'

// This will match 'Saw' etc.

Для лучшей производительности базы данных вы можете наилучшим образом рассчитать значение SOUNDEX для ваших заголовков и поместить его в новый столбец. Вы можете рассчитать soundex с помощью SOUNDEX («Привет»).

Пример использования:

UPDATE `books` SET `soundex_title` = SOUNDEX(title);
1 голос
/ 08 мая 2011

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

ключевое слово: набор названий книг

Redisуже есть встроенный набор типа данных, который вы можете использовать.

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

Все сделано вобъем памяти;поэтому время отклика очень быстрое.Кроме того, если вы хотите сохранить свой индекс, в Redis есть несколько различных механизмов сохранения / кэширования.

1 голос
/ 08 мая 2011

Возможно, вы захотите взглянуть на Apache Lucene . Это высокопроизводительная система поиска информации на основе Java.
Вы хотели бы создать IndexWriter и проиндексировать все ваши заголовки, а также можете добавить параметры (взгляните на класс), ссылающиеся на реальную книгу.
при поиске вам понадобятся IndexReader и IndexSearcher, и используйте опцию search () для них.
посмотрите на образец по адресу: src / demo и в: http://lucene.apache.org/java/2_4_0/demo2.html
использование методов поиска информации делает индексацию более длительной, но при каждом поиске не требуется проходить большинство заголовков, и в целом можно ожидать более высокую производительность поиска.
также, выбор хорошего Analyzer позволяет игнорировать такие слова, как "the", "a" ...

1 голос
/ 08 мая 2011

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

И просто придумал другую идею. Вы говорите, что некоторые слова можно интерпретировать по-разному. Как 12, двенадцать, дюжина. Вместо того, чтобы создавать запрос с разными интерпретациями, почему бы не сохранить разные интерпретации заголовков в отдельной таблице с одним ко многим для книг. Затем вы можете GROUP BY book_id, чтобы получить уникальные названия книг.

Скажите книгу "Десяток в дюжине". В таблице книг это будет:

book_id=356
book_title='A dime in a dozen'

В таблице заголовков будут храниться:

titles_id=123
titles_book_id=356
titles_title='A dime in a dozen'
--
titles_id=124
titles_book_id=356
titles_title='A dime in a 12'
--
titles_id=125
titles_book_id=356
titles_title='A dime in a twelve'

Запрос для этого: ВЫБЕРИТЕ b.book_id, b.book_title ОТ книг b ПРИСОЕДИНЯЙТЕСЬ к заголовкам t на b.book_id = t.titles_book_id ГДЕ t.titles_title = '% двенадцать%' GROUP BY b.book_id

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

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