Поиск по огромным газетным статьям

Роберт

Аналитик
Поиск по огромным газетным статьям

Может кому приходилось делать что-то подобное - есть огромное количество больших текстовых фрагментов (в моём случае газетные статьи) которые хранятся в базе и по которым необходимо производить поиск. Но поиск спецефический - не просто такак в поисковике по любому слову , а по Имени и Фамилии!
Что бы народ понял разницу - приведу пример:

Вчера троя собутыльников: Сергей Иванов, Дмитрий Петров и Андрей Сидоров совершили преступление и напились.

Если в простой базе данных запросить Дмитрий Иванов - то она найдёт эту статью , а ведь на самом деле в этой статье нету такого человека! Просто система заметила:
...троя собутыльников: Сергей Иванов, Дмитрий Петров и Андрей...
Тоесть фамилия и имя взяты совершенно от разных людей.
Вот в чём фишка!

Я расскажу как делается сейчас у меня. Я разбиваю статьи на две таблицы. В одной таблице записана сама статья и всякая дополнительная информация , типа: дата выхода , в какой газете печаталось , какому региону относится газета , рубрика (Спорт или Криминальная хроника) и т.д. А во сторую таблицу закидываю этуже статью , но уже разбитую по кусочкам (разделителями являются все знаки припинания ".,!?()- , а также " и " (пробел И пробел). И каждый из этих фрагментиков имеет индекс той статьи из которой он брался. Так например данный примерчик будет разбит на три части:
1) Вчера троя собутыльников: Сергей Иванов
2) Дмитрий Петров
3) Андрей Сидоров совершили преступление и напились.
И когда кто-то ищит по фамилии и имени - поиск происходит во второй таблице , а как результат поиска - на экран выводится первая таблица с полным текстом.

Может кто-то занимался такими же задачами или видил какие-то статьи на эту тему? Подскажите , а то очень много закавырок...

Например в статье может быть написано:
Братья Андрей и Денис Ивановы построили...
В этом случае при поиске по Андрею Иванову система не найдёт его , ведь в базу попадут:
1) Братья Андрей
2) Денис Иванов построили...

Может кто-то может подсказать что-то по поводу склонений имён и фамилий? Пока я просто стараюсь во второй таблице (где разбитые фразы) приводить все имена и фамилии к именительному падежу (как вы это наверно уже заметили в предыдущем примере , где в статье было:
Денис Ивановы построили...
а в базу попало:
Денис Иванов построили...
Это очень помогает , но в тоже время когда выводится текст на экране - я не могу сделать корректную подсветку если искали по критерию "Иванов" , база нашла во сторой таблице это слово (потому что оно там подправлено) , а в первой таблице и сиходной статьёй был не "Иванов" , а "Ивановы". Приходится отнимать 1-2 буквы искать через регулярные выражения по вхождению Иван(.+?) , чтобы подсветить это (а как следствие попадпются и Ивановны , и город Иваново , и Иванчинко , и тому подобное...

Но бог с ними - склонениями. Есть ещё огромное количество вопросов. Например - как правильно производить сам поиск в базе данных? Через FULLTEXT индексы? Или есть ещё более быстрые методы поиска? Или это вообще надо делать не в базе данных а есть какие-то другие средства?

И очень интересно - каким образом можно находить опечатки? Когда вводится допустим Наталья вместо Наталия или путаюстя буквы местами? (может кто-нибудь меня ткнёт в сылку по этой теме?)

Если у кого-то были подобные задачи или может что-то посоветовать или видел где обсуждение - поделитесь информацией...
 

440hz

php.ru
ты сначаля для себя самого сформулируй что такое Фамилия Имя и как их формализовать.

напримр: Два слова начинающихся с заглавной буквы и разделенных пробеллом.

просклонять Фамилию и Имя не особо сложная задача.

на вскидку
 

Роберт

Аналитик
440hz
Да , я не написал об этом , чтобы не перегружать информацией - раньше я разбивал тексти и по двум радомстояшим словам написанным с большой буквы.
Но , посмотри уже приведённый пример:
Братья Андрей и Денис Ивановы построили...
Получается что Братья Андрей это распознается как имя и фамилия. А если будет:
Друзья Андрей Ивановы и Сергей Иванов...
Тогда он посчитает "Друзья Андрей" именем и фамилией (кодификатор всех имён сделать не получилось - их столькооооо , а про фамилии и речи не может быть)

Я когда-то пытался записывать вообще все рядом стоящие слова с большой буквы в отдельные блоки , но тоже были проблемы :(

И самое главное - я всеравно не смогу найти Андрея Иванова в записи:
Братья Андрей и Денис Ивановы построили...
 

440hz

php.ru
Автор оригинала: Роберт
И самое главное - я всеравно не смогу найти Андрея Иванова в записи:
Братья Андрей и Денис Ивановы построили...
мдя ... засада ... тады пас
 

alexhemp

Новичок
Роберт

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

Роберт

Аналитик
alexhemp
Да я смирился с этим... Сам пытаюсь по немногу придумать всякие решения.
Хотелось просто концептуально чтобы кто-то может чего-то посоветовал бы. Может какие-то идеи. Может кто-то через регулярные выражения делал в MySQL'е или однозначно FULLTEXT индексы самый быстрый вариант поиска?

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

alexhemp

Новичок
Роберт

Концептуально я могу посоветовать одно - попробовать формализовать условия твоей задачи.

Пока у тебя есть только примеры. Попробуй посмотреть десяток другой текстов и написать основные правила записи фамилий

На практике я бы попробовал вот так, если бы у меня стояла такая задча

1. Примем что человек вводит у нас имя-фамилию в поиск (максимум 3 слова), причем порядок обычно Фамилия-Имя, падеж именительный. Вообще это отдельная задача - распознование что имя и что фамилия.
Для русских имен и фамилий - существует всего несколько распостаненных окончаний фамилии - "ов", "ев", "ин" покрывают вроде 99%. С женским родом то-же самое + "а".
C именами может помочь словарный вариант, отчества можно гененировать по словарю имен и тоже проверять.
С буквами все просто - если имя из одной буквы - то это инициал.

Например человек ввел Иванов Василий.

2. Вычислим все падежи для Имени и Фамилии инициалы и составим из них список. Сперва самые частые падежи - какие нужно смотреть по текстам.

3. Далее строим инвертированный индекс всех текстов - как делает поисковая машина - разбиваем все на слова, строим таблицу - "id текста", "номер слова", "id слова".

4. Далее ищем по таблице тексты в которых встречаются заданные слова, причем расстояние между ними стремится к 0.
Степень совпадения со вводом юзера (можно оценить по построенному списку слов) и расстояние между словами - это релевантность (нужно будет поподбирать коэффициенты для рассчета одной величины) - сортируешь по ним.

В любом случае простой систему не назовешь. :) Но вполне можно сделать, взяв за основу какой-нить mnogosearch или aspseek или dmsearch и конструируя сложный запрос к ним (там вроде в языке есть учет расстояния между словами).

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

Более того, mnogoseach просто результаты даст лучше, он учитывает расстояния между словами при подсчете релевантности.
 

FiW

Новичок
imho, не стоит даже пытаться выявлять фамилию и имя, а учитывая что возможны опечатки и вольный ситль написания статьи то... сам понимаешь ;)

imho, тебе лучше сделать морфологический поиск с релевантностью.
 

Роберт

Аналитик
alexhemp
По правде говоря - я когда впервые прочитал о mnogoseach , подумал - "Во! Это именно то что мне надо!!!" , но потом понял что растояние между словами - это только для обычных поисковиков , а в моём случа - даже нулевое расстояние может дать абсолютно неправильный результат.
Помнишь я приводил пример:
...троя собутыльников: Сергей Иванов, Дмитрий Петров и Андрей...
тут между словами Иванов Дмитрий расстояние ноль , но такого человека не существует.

Или возьмём более сложный пример с точкой:
...сказал нам Дмитрий. Иванов стоявший рядом с...
и
...сказал нам Д. Иванов стоявший рядом с...
В первом случае Дмитрий и Иванов- это разные персоны , а во втором случае Д. Иванов - это конкретный человек и может быть именно тот кто нам нужен , и его можно отмечать как правильный ответ при поиске Дмитрия Иванова или Диниса Иванова (правда релевантность меньше так как не факт что это именно тот кто надо).

Программе mnogoseach я ни как не смогу обьяснить что в случае если точка стоит после слова длинной более двух символов - то это разделитель который означает что эта фраза на 100% НЕверный ответ! А в случае если первое слово состоит из одной-двух букв и при этом первая буква большая и совпадает с началом одного из наших поисковых слов , а после него идёт нужное нам оставшееся слово целиком - то это правильный ответ но релевантность ниже...

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

-~{}~ 22.09.05 19:46:

FiW
А что ты имел в виду? Ты хочешь сказать - я сам могу разработать правила морфологии и релевантности для MySQL? Или ты предлагаешь отказаться от базы данных и проводить поиск самостоятельно?
 

alexhemp

Новичок
Я предлагаю не использовать встроенные возможности mySQL по полнотекстовому поиску.

Попробуй использовать индексатор от mnogoSearch а потом опрашивай индекс самостоятельно.

И опять-же - ФОРМАЛИЗУЙ ЗАДАЧУ.
Приводя примеры - ты ничего не добъешься.

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

Напиши тупо правила

Слово Слово = Имя Фамилия
Слово. Слово - не подходит
и т.п.

А точно индексатор mnogoSearch выкидывает знаки препинания? Поизучай готовый индекс.
 

Long

Новичок
MySQL для этой задачи подходит только если рассматривать ее в качестве склада, откуда выбирается результат. а логику работы не получится реализовать на уровне этой базы, в этом случае лучше смотреть в сторону PostgreSQL, в которой есть возможность определять пользовательские функции (в том числе была возможность определить функцию на РНР, подробнее может тебе рассказать/посоветовать Sad Spirit).
что касается mnogoSearch и прочих вариантов использования обычных поисковиков, имхо, они в чистом виде не подойдут - у них другие задачи, поэтому запятые и точки им учитывать (по крайней мере в той мере, которая нужна тебе) нет нужды.
решением могло бы стать написание собственного индексатора. морфология для имени берется из того же ispel'а. для фамилии - тебе подсказали путь.
 

Фанат

oncle terrible
Команда форума
Я разбиваю статьи на две таблицы. В одной таблице записана сама статья и всякая дополнительная информация , типа: дата выхода , в какой газете печаталось , какому региону относится газета , рубрика (Спорт или Криминальная хроника) и т.д. А во сторую таблицу закидываю этуже статью , но уже разбитую по кусочкам
и это при том, ха-ха, что во вторую таблицу надо закладывать только имена, в статье встечающиеся.
 

antson

Новичок
Партнер клуба
Роберт
А интересны ли посетителям сайта отвлеченные собутыльники?
По моему мнению лучше вести персоналии значительных
личностей по тематике сайта. При вбивании статьи
нужно просто выставлять соответствия.

Автор статьи -> персоналии
Интервью с -> персоналии
Упоминаються по тексту ->персоналии.

Значимых людей по статьям будем теперь находить 100%
Ну а тем кто попал в статью для фона хватит простого поиска.

Иванов Иван Иванович может быть и сантехником и директором фирмы. А мне нужно только про директора.

-~{}~ 23.09.05 11:00:

а из базы персоналей -> обратные ссылки
 

alexhemp

Новичок
antson
Это уже ручное составление индекса ;-)

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

Фанат
Я бы предложил обойтись малой кровью. Использовать уже готовый индексатор (может быть чуть его подправив убрав из списка стоп-слов знаки препинания).
Сделать поиск обратившись к индексу напрямую, ручками, учитывая только имена и фамилии.

Параллельно можно и обычный поиск замутить :)
 
Сверху