Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Алгоритм поиска.
 
 автор: Гость   (09.04.2008 в 20:03)   письмо автору
 
 

Вообщем есть таблица в ней - 15 тысяч наименований. У нас есть какой-то тектс на 50-100 слов нужно найти совпадающие слова с наименованиями..
1) какой можно сделать оптимизированный алгоритм поиска, что бы это дело вертелось быстрее?
2) Вообще ставит меня в тупик - кужно найти слова похожите на те что есть в таблице - тоесть написанные с ошибкой, ошибка - одна неверная буква.. тут я вообще стопорюсь... видимо получаем массив таблицы, потом с помощью регулярки заменяем в слове поочереди каждую букву на '.' сравниваем с массивом? Сколько же это тогда будет все обрабатываться- представить сложно.

   
 
 автор: Киналь   (09.04.2008 в 21:49)   письмо автору
 
   для: Гость   (09.04.2008 в 20:03)
 

По первому пункту - думаю. проще всего по каждому слову отдельно делать полнотекстовый поиск средствами БД.

   
 
 автор: mechanic   (09.04.2008 в 21:51)   письмо автору
 
   для: Гость   (09.04.2008 в 20:03)
 

задачка довольно интересная..
я бы не стал делать такое по принципу "запускается каждый раз при загрузке страницы", а сделал бы однократный запуск с записью результата..
думаю здесь будет уместно использовать полнотесктовый поиск
делаем запрос (предполагается что полнотекстовый индекс уже сделан)
select `id` from `naimenovaniya` where match(title) against('our big text about acer notebook')

в итоге получаем ID-шки позиций, заголовки которых найдены в нашем тексте
далее возможны 2 варианта:
либо записать эти ID-шки куда то, и при каждом формировании страницы выбирать все title по этим ID-шкам и выделять совпадения в тексте,
либо изменить 1 раз текст и сохранить его копию

вот как то так

а с п.2 действительно придется подумать..

   
 
 автор: DEM   (09.04.2008 в 21:53)   письмо автору
 
   для: Гость   (09.04.2008 в 20:03)
 

Сделал бы как Киналь :) Разбить текст на слова (регулярными выражениями или простым explode(); ), а потом цикл и полнотекстовый поиск )))

   
 
 автор: mechanic   (09.04.2008 в 22:13)   письмо автору
 
   для: DEM   (09.04.2008 в 21:53)
 

зачем разбивать?

mysql> select col1 from shit where match(col1) against ('our big text about Acer note vs acorp');
+-----------+
| col1      |
+-----------+
| acer W32  |
| acer W32  |
| acer W32  |
| acorp GTX |
| acorp GTX |
| acorp GTX |
| acorp GTX |
+-----------+
7 rows in set (0.01 sec)

как видишь, находятся заголовки, в которых любое слово встречено в заданном тексте..

а если, как ты говоришь, разбить по словам, то зачем тогда полнотекстовый поиск? хватит и like '%word%', только вот количество запросов в твоем случае будет 50-100 (по кол-ву слов в тексте), а в моем - 1

   
 
 автор: vitali   (10.04.2008 в 07:40)   письмо автору
 
   для: mechanic   (09.04.2008 в 22:13)
 

Недавно на форуме была такая тема, посмотрите man на PHP-функцию:
levenshtein() --Вычисляет расстояние Левенштейна между двумя строками.
Расстояние Левенштейна - это минимальное количество вставок, замен и удалений символов, необходимое для преобразования str1 в str2.
Возможно это то, что вам надо.

   
 
 автор: Гость   (14.04.2008 в 19:06)   письмо автору
 
   для: Гость   (09.04.2008 в 20:03)
 

Всем спасибо. Первый этап прошел, теперь загвоздка. Заключается в том что имена в таблице могут состоять из двух и даже из трех слов.
Итак таблица table - id|name
в ней три записи
1|test
2|play
3|play test
Я делаю запрос

SELECT `id` 
FROM table
WHERE MATCH (
name
)
AGAINST (
'play test'
IN BOOLEAN
MODE 
)
LIMIT 0 , 30

И получаю два ключа - 1 и 3-тий. Вопрос - как бы получить в этом случае только третий ключ?

PS: только что заметил что порядок слов в AGAINST не имеет значения, впрочем логично, тоесть если у нас в начале текста встретится play а под конец где-то далеко test то все равно нам вернется id 3, впрочем это вполне решаемо, неприятно другое - Кроме того таким образом он не ищет нэймы из трех слов. Есть какое--то еще решение? myAdmin предложил такой запрос:

SQL-запрос: 
SELECT * 
FROM `table` 
WHERE (
`name` LIKE '%play%'
)
OR (
`name` LIKE '%test%'
)
LIMIT 0 , 30

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

   
 
 автор: Гость   (15.04.2008 в 11:06)   письмо автору
 
   для: Гость   (14.04.2008 в 19:06)
 

идей нет? Нехочется делать "медленный вариант" но видимо придется использовать его

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования