SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 20.07.2008 21:20:28

sito-corito
Завсегдатай
Зарегистрирован: 13.07.2008
Сообщений: 53

Как составить нужное регулярное выражение в MySQL

Кто знает про регулярные выражения, помогите пожалуйста.
Делаю поиск по сайту. Нужно составить регулярное выражение для поиска слова , например "Москва". Если в тексте встречается выражение типа "г.Москва, где я живу", то единственный способ найти это слово, это запрос вида:

like '%word%', где word - любое слово, в т.числе Москва.

Но запрос не подходит, так как если в поиске будет короткое слово, запрос будет очень много ненужных вариантов выдавать. Ищу, допустим, слово "кот", а MYSQL мне и слово "который" выдаст и другие ненужные слова.  Как с помощью регулярных выражений задать символы точек, запятых, двоеточий и тире, чтобы составить более корректный запрос?

Неактивен

 

#2 20.07.2008 22:40:49

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Как составить нужное регулярное выражение в MySQL

запросы с регулярными выражениями в общем случае не используют индексы (так же как и LIKE %word%) и использовать их для вашей цели думаю не стоит...

Посмотрите в сторону полнотекстового поиска (kw: fulltext)

Неактивен

 

#3 21.07.2008 15:30:35

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Как составить нужное регулярное выражение в MySQL

По поводу индекса согласен с Shopen, однако, на первый вопрос тоже отвечу -
Вы можете использовать регулярные выражения, если будете писать не LIKE, а
RLIKE, например, RLIKE '[[:<:]]кот[[:>:]]'.

http://dev.mysql.com/doc/refman/5.1/en/regexp.html

Неактивен

 

#4 21.07.2008 23:02:40

sito-corito
Завсегдатай
Зарегистрирован: 13.07.2008
Сообщений: 53

Re: Как составить нужное регулярное выражение в MySQL

Спасибо за ссылку, почитаю.
Правда не понял, при чём здесь индексы?

Неактивен

 

#5 22.07.2008 12:53:37

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Как составить нужное регулярное выражение в MySQL

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

Неактивен

 

#6 22.07.2008 19:13:09

sito-corito
Завсегдатай
Зарегистрирован: 13.07.2008
Сообщений: 53

Re: Как составить нужное регулярное выражение в MySQL

Очень полезная статья. Правда, после того, как её перевёл на русский, надо понять что к чему в ней, что за команды или не команды там такие. Очень хорошее рег. выражение. По сути оно очень упрощает поиск.
Только вот у меня возникла проблема.Когда я ищу RLIKE '[[:<:]]кот[[:>:]]', то база выдаёт мне слова только с маленькой буквы (хотя есть строки со значением "Кот" с большой буквы. Когда я задаю такое рег. выражение
RLIKE '[[:<:]]Кот[[:>:]]'
то он всё ищет нормально, как с маленькой так и с большой буквы. У меня с кодировкой проблемы или это особенность регулярного выражения? Использовал для тестирования phpmyadmin. Вроде collation настроил. Использовал utf8_unicode_ci. В запросе также пробовал конструкцию collation, но это ничего не изменило.

Отредактированно sito-corito (22.07.2008 19:15:09)

Неактивен

 

#7 22.07.2008 19:55:03

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Как составить нужное регулярное выражение в MySQL

Да, похоже, это бага. В cp1251 отрабатывает правильно с учетом кодировки, в UTF8
рассматривает как бинарную sad

P.S. У меня с большой буквы не ищет маленькие в том числе.

Неактивен

 

#8 24.07.2008 02:47:04

sito-corito
Завсегдатай
Зарегистрирован: 13.07.2008
Сообщений: 53

Re: Как составить нужное регулярное выражение в MySQL

Хотелось бы уточнить, что подобная конструкция регулярного выражения, наверное, единственный нормальный способ поиска слова в базе. А всякие там like '%слово_%' c символами подчёркивания (для "изображения" любого символа, в том числе запятых и точек) только усложняют задачу.

Неактивен

 

#9 24.07.2008 12:17:28

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Как составить нужное регулярное выражение в MySQL

Нет, правильный способ всё-таки, полнотекстовый поиск. По указанным уже выше причинам.

http://dev.mysql.com/doc/refman/5.1/en/ … earch.html

Неактивен

 

#10 24.07.2008 12:55:19

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Как составить нужное регулярное выражение в MySQL

sito-corito написал:

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

не изобретайте велосипед. Вашу задачу давно решили - красиво, удобно и быстро.
Регулярные выражения в SQL  - это очень редко встречаемая задача - некрасивая (посмотрите на ваш пример), не удобная (потому что не PCRE а POSIX) и ОЧЕНЬ медленная на большинстве задач. Медленнее только левый LIKE %...%. и то не всегда.

На моей практике использовать REGEXP (==RLIKE) понадобилось один раз - когда в базе была таблица, в которой был столбец с регулярными выражениями и через него шло объединение, типа такого (по памяти):

Код:

SELECT tWords.word FROM tWords JOIN tRegexp ON tWords.word REGEXP CONCAT(tRegexp.rule, '$') WHERE ...

тут просто некуда было деться, но работало быстро, так как в tWords.word лежали слова, да и регулярки были наипростейшими, по сути набор символьных классов. Если бы там был текст - мне страшно представить, сколько бы на эти запросы уходило времени (~миллион слов, ~500 регулярок).

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

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

Отредактированно Shopen (24.07.2008 13:00:45)

Неактивен

 

#11 26.07.2008 01:08:44

sito-corito
Завсегдатай
Зарегистрирован: 13.07.2008
Сообщений: 53

Re: Как составить нужное регулярное выражение в MySQL

Не могу согласится с тем, что полнотекстовый поиск идеально подходит для задачи поиска. По крайней мере для меня. Прочитал кое-что про такой поиск. Данные в моей таблице могут быть как очень короткими, так и длинными. Полнотекстовый поиск имеет ограничения на длину искомых слов, сам определяет релевантность и иногда не выдаёт результат, даже если слово есть в базе. И как изменить параметры такого поиска на сервере я даже представить не могу. А я бы хотел более прогнозируемый результат.
Индексировать поле, в котором я произвожу поиск, наверное смысла нет. У меня там будут не фамилии и имена, а какой-то текст.
Не имею практического опыта и хотелось бы приблизительно оценить, сколько уходит времени для поиска с помощью регулярных выражений в таблице с приблизительно миллион или более строк с текстом в два-три предложения (без индексов, а имено поиск в каждой строке). Если у кого-то есть такие данные? Сколько секунд запрос обрабатывается? Был бы признателен за информацию smile А то я собираюсь делать поиск с использованием регулярного выражения, в котором есть подзапрос where с ещё одним регулярным выражением.

Отредактированно sito-corito (26.07.2008 01:14:36)

Неактивен

 

#12 26.07.2008 16:33:52

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3878

Re: Как составить нужное регулярное выражение в MySQL

Некоторые параметры FULLTEXT можно настраивать, в частности минимальную длину слова http://dev.mysql.com/doc/refman/5.1/en/ … uning.html
Посмотрите также BOOLEAN MODE http://dev.mysql.com/doc/refman/5.1/en/ … olean.html

Как более мощная альтернатива, поддерживающая русский язык, Вам может подойти Sphinx.

Самый простой способ узнать время выполнения запроса - создать тестовую таблицу, внести в нее миллион записей и выполнить запрос.

Неактивен

 

#13 27.07.2008 16:47:43

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Как составить нужное регулярное выражение в MySQL

sito-corito написал:

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

расскажите чем конкретно не подходит?

sito-corito написал:

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

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

sito-corito написал:

Индексировать поле, в котором я произвожу поиск, наверное смысла нет. У меня там будут не фамилии и имена, а какой-то текст.

А какая разница что в поле фамилии или слова? Если поле по которому ищете не будет проиндексировано - то тормоза будут по любому (при ваших ожидаемых объемах особенно).
Индексировать можно либо воспользовавшись fulltext, либо сделав свою таблицу индекс (наиболее гибкий путь, но и наиболее затратный) либо воспользовавшись каким то существующим движком, типа сфинкса (он тоже создаст разумеется индекс где то для себя), который вам посоветовал rgbeast

sito-corito написал:

Не имею практического опыта и хотелось бы приблизительно оценить, сколько уходит времени для поиска с помощью регулярных выражений в таблице с приблизительно миллион или более строк с текстом в два-три предложения (без индексов, а имено поиск в каждой строке). Если у кого-то есть такие данные? Сколько секунд запрос обрабатывается? Был бы признателен за информацию smile А то я собираюсь делать поиск с использованием регулярного выражения, в котором есть подзапрос where с ещё одним регулярным выражением.

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

если вам очень нужна гибкость - сделайте свой поиск, но только не на регулярных выражениях. Примерный алгоритм такой:
- Текстовые поля разбиваете на слова, может быть выкидываете короткие (предлоги,союзы...)
- Полученные слова пропускаете через морфологический анализ (если нужна морфология)
- Полученные нормальные формы слов или слова - заносите в таблицу (tWordIndex) попутно сохраняя в еще одну таблицу (tWordRelations) id слова + id записи откуда слово  + количество раз, которое оно в этой записи встречалось (или словоформа) + еще какие то данные, которые вам нужны, например вы можете тут высчитывать вес слова в записи, на основе своих собственных параметров (*3 если внутри <h1>слово</h1>, например)
- Делаете нужные индесы в таблицах

При поиске ищете так (это схематичный запрос):

Код:

SELECT tSource.text 
JOIN tWordIndex JOIN tWordRelations
WHERE tWordIndex IN 'слова_из_формы_поиска,разбитые_по_разделителям'
ORDER BY 'поле_с_весами_слов'

перед этим приводите поисковый запрос к нормальной морфологической форме (если требуется)

Это только примерная схема, тут есть что и додумать и дооптимизировать

Неактивен

 

#14 27.07.2008 21:37:44

sito-corito
Завсегдатай
Зарегистрирован: 13.07.2008
Сообщений: 53

Re: Как составить нужное регулярное выражение в MySQL

- Текстовые поля разбиваете на слова, может быть выкидываете короткие (предлоги,союзы...)
- Полученные слова пропускаете через морфологический анализ (если нужна морфология)
- Полученные нормальные формы слов или слова - заносите в таблицу (tWordIndex) попутно сохраняя в еще одну таблицу (tWordRelations) id слова + id записи откуда слово  + количество раз, которое оно в этой записи встречалось (или словоформа) + еще какие то данные, которые вам нужны, например вы можете тут высчитывать вес слова в записи, на основе своих собственных параметров (*3 если внутри <h1>слово</h1>, например)
- Делаете нужные индесы в таблицах

Вот примерно такой поиск я и делаю.
Яндекс и Гугл и другие поисковики обзавидуются, наверное.

Неактивен

 

#15 27.07.2008 21:55:25

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Как составить нужное регулярное выражение в MySQL

sito-corito написал:

Вот примерно такой поиск я и делаю.

тогда непонятно - а зачем вам понадобились регулярные выражения?

sito-corito написал:

Яндекс и Гугл и другие поисковики обзавидуются, наверное.

Сомневаюсь

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson