У меня много документов, текстовых файлов, в которых я хочу найти релевантный контент. Я видел инструмент поиска, не могу вспомнить где, который реализовал хороший метод, как я описываю в моем требовании ниже.
Мое требование следующее:
Возможный подход к решению, которое я придумал, следующий: Я создаю базу данных (скорее всего, используя mysql) с тремя таблицами: «Документы», «Слова» и «Word_Docs».
Затем функция вызывается с содержимым поля редактирования при каждом нажатии клавиши (кроме пробела):
Затем отображается возвращенное содержимое списка:
например: вызывается с помощью: "seq sta cod" отображает:
sequence - start - code - Counting Sequences [file://docs/sample/con_seq.txt]
- stop - code - Counting Sequences [file://docs/sample/con_seq.txt]
sequential - statement - code - SQL intro [file://somewhere/sql_intro.doc]
(и так далее)
Это оптимальный способ сделать это? Функция должна быть быстрой или ее следует вызывать только при попадании в пробел? Должен ли он предлагать завершение слов? (Есть слова в базе данных) По крайней мере, это предотвратит бесполезные вызовы функции для слов, которых не существует. Если слово-завершение: как это будет реализовано?
(Может быть, SO также может использовать этот тип поискового решения для просмотра тегов? (В правом верхнем углу главной страницы))





Не уверен в синтаксисе (это синтаксис sql server), но:
-- N is the number of elements in the list
SELECT idDoc, COUNT(1)
FROM Word_Docs wd INNER JOIN Words w on w.idWord = wd.idWord
WHERE w.Word IN ('word1', ..., 'wordN')
GROUP BY wd.idDoc
HAVING COUNT(1) = N
То есть без использования лайков. С подобными дела обстоят НАМНОГО сложнее.
Самый быстрый способ - это вообще не использовать базу данных, поскольку, если вы выполняете поиск вручную с оптимизированными данными, вы можете легко превзойти производительность выборочного поиска. Самый быстрый способ, при условии, что документы не меняются очень часто, - это создать индексные файлы и использовать их для поиска ключевых слов. Индексный файл создается следующим образом:
Найдите все уникальные слова в текстовом файле. Это разбивает текстовый файл пробелами на слова и добавляет каждое слово в список, если оно еще не найдено в этом списке.
Возьмите все найденные слова и отсортируйте их в алфавитном порядке; Самый быстрый способ сделать это - использовать Трехсторонняя Radix QuickSort. Этот алгоритм трудно превзойти по производительности при сортировке строк.
Запишите отсортированный список на диск, по одному слову в строке.
Теперь, когда вы хотите выполнить поиск в файле документа, полностью игнорируйте его, вместо этого загрузите индексный файл в память и используйте двоичный поиск, чтобы узнать, есть ли слово в индексном файле или нет. При поиске в больших отсортированных списках сложно превзойти двоичный поиск.
В качестве альтернативы вы можете объединить шаг (1) и шаг (2) в один шаг. Если вы используете InsertionSort (который использует двоичный поиск, чтобы найти правильную позицию вставки для вставки нового элемента в уже отсортированный список), у вас не только есть быстрый алгоритм, чтобы узнать, есть ли слово уже в списке или нет, на случай это не так, вы сразу получаете правильную позицию для вставки, и если вы всегда вставляете новые, такие как это, у вас автоматически будет отсортированный список, когда вы дойдете до шага (3).
Проблема в том, что вам нужно обновлять индекс всякий раз, когда документ изменяется ... однако разве это не относится и к решению для базы данных? С другой стороны, решение для базы данных дает вам некоторые преимущества: вы можете использовать его, даже если документы содержат так много слов, что индексные файлы больше не помещаются в памяти (маловероятно, поскольку даже список всех английских слов будет поместится в память любого обычного пользовательского ПК); однако, если вам нужно загрузить индексные файлы огромного количества документов, тогда память может стать проблемой. Хорошо, вы можете обойти это, используя хитрые приемы (например, поиск непосредственно в файлах, которые вы сопоставили с памятью с помощью mmap и т. д.), Но это те же приемы, которые базы данных уже используют для выполнения быстрого поиска, поэтому зачем изобретать заново колесо? Кроме того, вы также можете предотвратить проблемы с блокировкой между поиском слов и обновлением индексов при изменении документа (то есть, если база данных может выполнять блокировку за вас или может выполнять обновление или обновления как атомарную операцию). Для веб-решения с вызовами AJAX для обновления списка использование базы данных, вероятно, является лучшим решением (мое первое решение вполне подходит, если это локально работающее приложение, написанное на языке низкого уровня, например C).
Если вам хочется сделать все это за один вызов select (что может быть неоптимальным, но когда вы динамически обновляете веб-контент с помощью AJAX, это обычно оказывается решением, вызывающим наименьшую головную боль), вам необходимо СОЕДИНЯТЬ все три таблицы вместе. Возможно, SQL немного ржавый, но я попробую:
SELECT COUNT(Document.idDoc) AS NumOfHits, Documents.Name AS Name, Documents.Location AS Location
FROM Documents INNER JOIN Word_Docs ON Word_Docs.idDoc=Documents.idDoc
INNER JOIN Words ON Words.idWord=Words_Docs.idWord
WHERE Words.Word IN ('Word1', 'Word2', 'Word3', ..., 'WordX')
GROUP BY Document.idDoc HAVING NumOfHits=X
Ладно, возможно, это не самый быстрый выбор ... Думаю, это можно сделать быстрее. В любом случае, он найдет все совпадающие документы, содержащие хотя бы одно слово, затем сгруппирует все равные документы вместе по идентификатору, посчитает, сколько их было сгруппировано в togetehr, и, наконец, покажет только результаты, где NumOfHits (количество слов, найденных в инструкции IN) равно количеству слов в операторе IN (если вы ищете 10 слов, X равно 10).
Google Desktop Search или аналогичный инструмент может удовлетворить ваши требования.
То, о чем вы говорите, известно как инвертированный индекс, или список сообщений, и действует аналогично тому, что вы предлагаете, и тому, что предлагает Меки. Об инвертированных индексах написано много; статья в Википедии - хорошее место для начала.
Лучше, чем пытаться построить его самостоятельно, использовать существующую реализацию инвертированного индекса. И MySQL, и последние версии PostgreSQL по умолчанию имеют полнотекстовую индексацию. Вы также можете проверить Lucene для независимого решения. При написании инвертированного индекса хорошо необходимо учитывать множество вещей, включая токенизацию, стемминг, многословные запросы и т. д. И т. Д., И готовое решение сделает все это за вас.
Контент документа статичен (не изменится); файлов больше 1 гигабайта, и он, вероятно, будет расти. Придется изучить остальной ваш ответ.