Структура базы данных индекса слова документа? - PullRequest
2 голосов
/ 15 марта 2012

Скажем, я хочу распознать все вхождения слова на нескольких страницах документа (вероятно, около 500+ страниц).Я уже сделал работу по поиску, на каких страницах встречается слово.Так, например, я хочу перечислить все страницы, где встречается слово «компьютер».

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

Структура таблицы: varchar (30) WORD, blob PAGES

И иметь поле PAGES в виде списка разделенных запятыми всех страниц, где встречается словоа затем просто взорвите это и перечислите все страницы, когда запрос соответствует полю WORD.Мне интересно, есть ли более эффективный способ добиться этого, хотя?Скорее всего, я бы использовал MySQL и PHP / Zend только потому, что это то, с чем я больше всего знаком.Но если у вас есть идеи получше, я определенно готов их выслушать.

Таблица, вероятно, станет очень длинной, так как мне понадобится строка для каждого уникального слова в документе.Возможно, я бы установил ограничение не более чем на 3 или 4 символа, но все же я хотел бы представить более 10-20 тысяч слов.Могу ли я как-нибудь упростить на моем сервере баз данных, если я алфавитный список строк?(т.е. яблоко, яблоки, ветка в порядке возрастания?) Может ли MySQL справиться с этим?Может ли что-то еще лучше с этим справиться?

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

Ответы [ 3 ]

4 голосов
/ 15 марта 2012

Вам придется нормализовать вашу базу данных.

Первая таблица для хранения страниц

table pages (
  id unsigned integer auto_increment primary key,
  page blob,
  other_interesting_data_about_a_page )

Затем таблица для слов содержит

table wc (
  id unsigned integer auto_increment primary key
  word varchar(20) unique key,
  count unsigned integer default 1,
  other_interesting_data_about_a_word.... )

Затем таблица для связывания слов со страницами

table word_page (
  word_id unsigned integer,
  page_id unsiged integer,
  pos_in_page unsigned integer,  /*position*/
  primary key pk (word_id, page_id, pos_in_page) )

Теперь вы можете запросить количество слов на странице:

SELECT COUNT(*) 
FROM word_page 
WHERE page_id = 123

Или сколько раз слово «the» повторяется на странице.

SELECT COUNT(*)
FROM word_page wp 
INNER JOIN wc ON (wp.word_id = wc.id)
WHERE wp.page_id = 123 AND wc.word = 'the'

Слово предупреждения

И поле PAGES должно быть списком всех страниц, разделенных запятыми .....

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

3 голосов
/ 15 марта 2012

В отличие от нормализации, которая является хорошей практикой в ​​целом, но довольно неэффективной для этой конкретной проблемы, вы можете придерживаться своей структуры, но заменить список страниц в вашем двоичном объекте вектором битов (все еще внутри столбец blob), каждый бит представляет страницу. Преимущество состоит в том, что для 500 страниц максимальный размер этого вектора для одного слова составляет 63 байта, даже если это слово появляется на всех страницах (500/8 = 62,5).

Внутри битового поля каждая страница соответствует битовому номеру: если битовый номер N включен, это означает, что слово появляется на странице N, в противном случае оно не появляется на странице N. Эта структура в основном используется реализацией текстовой индексации SQL DBIx Биты пронумерованы справа налево, и несущественные 0 могут быть удалены.

Например, если слово «компьютер» присутствует на страницах 3,4 и 12, значение будет следующим: 100000001100 в двоичном формате (= 2060 в десятичном представлении).

Если оно появляется только на странице 400, это будет цифра 1, за которой следует 399 0's. Если он появляется на каждой странице, значение будет в 500 раз больше цифры 1.

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

1 голос
/ 15 марта 2012

для упрощения обслуживания и индексации, я бы создал таблицу сопоставления с вычисленным первичным ключом: id BIGINT AUTO_INCREMENT, word VARCHAR (30), page INT, ... и построил индекс для слова и страницы.Таким образом, вы более гибки, вам не нужно разбирать список и даже получать доступ к некоторой статистике (какие страницы используют больше уникальных слов и т. Д.).

MySQL (и любой другой механизм реляционных БД) создает егособственный внутренний индекс с использованием древовидных структур, нет необходимости предварительно сортировать ваши данные.

Эта таблица легко обрабатывается MySQL.могут быть и другие DB-движки, которые еще быстрее, но это нормально.

Конечно, вы можете добавить больше таблиц, например, word, other_word, distance, все зависит от вашей спецификации и того, что возможно с вашимparser.

если у вас есть время на просмотр, посмотрите, как поисковики, например solr / lucene, справляются с этим

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