Firebird нечеткий поиск. А как ищете вы? [РЕШЕНО]

Модератор: Модераторы

Firebird нечеткий поиск. А как ищете вы? [РЕШЕНО]

Сообщение wofs » 19.10.2017 19:50:45

Доброго дня!
Продолжаю писать свою утилитку и по ходу возник вопрос - а как искать то?
Что я подразумеваю под "нечетким" поиском.
Имеется таблица несколько 200-300 тыс записей.
Необходимо произвести поиск по полю VARCHAR(300).

В ней есть строка:
Код: Выделить всё
Тюль красная с цветами на кольцах высота 2,5м [УльтраКолор]

Я хочу получить эту (и другие, подходящие под условие поиска) строку следующими запросами:
Код: Выделить всё
1. Тюль с цветами
2. Тюль высота 2,5м
3. Красная тюль
4. Тюль с цветами красная

Варианты 1 и 2 - решаются просто стандартным LIKE.
Варианты 3 и 4 пока для меня темный лес.

Поиск по сети выдал решения Sphinx и Lucene.
Но мне они кажутся излишне громоздкими для поставленной задачи.
А как ищете в FireBird вы?
Последний раз редактировалось wofs 30.03.2018 22:56:21, всего редактировалось 1 раз.
Аватара пользователя
wofs
постоялец
 
Сообщения: 375
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение olegy123 » 19.10.2017 20:39:20

Код: Выделить всё
SELECT * FROM table where text='*тюль*'

"*" - любые буквы..

Добавлено спустя 1 минуту 31 секунду:
Но заметь - еще нужно свести все буквы в нужный регистр.

Добавлено спустя 57 секунд:
UPPER/LOWER

Добавлено спустя 47 секунд:
Код: Выделить всё
SELECT * FROM table where LOWER(text)='*тюль*'
olegy123
энтузиаст
 
Сообщения: 1040
Зарегистрирован: 25.02.2016 12:10:20

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение Vadim » 20.10.2017 10:21:24

Ещё можно присобачить полнотекстный индекс. В FB по умолчанию его нету, а вот в RedBase он уже подключён в комплекте.
Vadim
долгожитель
 
Сообщения: 2828
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение wofs » 20.10.2017 10:25:32

olegy123 писал(а):"*" - любые буквы..

Строка (для наглядности).
Код: Выделить всё
Тюль красная с цветами на кольцах высота 2,5м [УльтраКолор]

Так я ищу, только через LIKE
Код: Выделить всё
SELECT * FROM table where UPPER(text) LIKE UPPER('%тюль%');

Могу искать и так:
Код: Выделить всё
SELECT * FROM table where UPPER(text) LIKE UPPER('%Тюль%высота%2,5м%');

Это не проблема, проблема в том, что запрос
Код: Выделить всё
SELECT * FROM table where UPPER(text) LIKE UPPER('%Тюль%с%цветами%красная%');

не даст результата.
Это задача, которую я пытаюсь решить.

Возникла идея (все одно LIKE заставляет сервер перебирать все записи) написать UDF модуль для FireBird, который будет реализовывать один из алгоритмов нечеткого поиска (расстояние Левенштейна, шинглы и т.п.), если разорбаться с построением нужного индекса в БД и научиться его использовать, то может получиться не сильно медленнее, чем LIKE (так как LIKE %text%, если верить руководству по языку FireBird - не использует индексы).

Но прежде хотелось бы услышать кто как ищет, если это не тайна конечно :)

Добавлено спустя 3 минуты 4 секунды:
Vadim писал(а):Ещё можно присобачить полнотекстный индекс. В FB по умолчанию его нету, а вот в RedBase он уже подключён в комплекте.

Читал, там он на Lucene основан. Имхо громоздко как-то - еще и Java машину тащить с собой. Чай не корпоративный сервер, а всего-лишь небольшая утилитка для личного пользования.

Добавлено спустя 5 минут 4 секунды:
Мне не нужна морфология и прочие плюшки. На данном этапе мне нужно лишь искать слова в разнобой.

Добавлено спустя 2 минуты 28 секунд:
Для полноценного поиска соответствий я думаю о модуле UDF (ибо меня очень устраивал (кроме скорости) алгоритм шинглов). Но не хотелось бы использовать такое ресурсоемкое решение для обычного поиска. Возможно, что я чего-то недопонимаю в SQL и поиск с перестановкой слов можно организовать малой кровью.
Последний раз редактировалось wofs 20.10.2017 10:50:09, всего редактировалось 1 раз.
Аватара пользователя
wofs
постоялец
 
Сообщения: 375
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение olegy123 » 20.10.2017 10:39:23

Ах, да "%" в FB. Извините, это в других принято "*"..

Добавлено спустя 3 минуты 5 секунд:
Для поддержки регулярных выражений добавлен новый предикат SIMILAR TO
http://firebirdsql.su/doku.php?id=similar_to
olegy123
энтузиаст
 
Сообщения: 1040
Зарегистрирован: 25.02.2016 12:10:20

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение wofs » 20.10.2017 10:49:31

olegy123 писал(а):Для поддержки регулярных выражений добавлен новый предикат SIMILAR TO
http://firebirdsql.su/doku.php?id=similar_to

Спасибо, видел, но как то не под тем углом смотрел.
Аватара пользователя
wofs
постоялец
 
Сообщения: 375
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение olegy123 » 20.10.2017 11:02:25

wofs писал(а):Так я ищу, только через LIKE
Код: Выделить всё
SELECT * FROM table where UPPER(text) LIKE UPPER('%тюль%');


Еще можно так:
Код: Выделить всё
SELECT * FROM table where UPPER(text) IN (UPPER('%тюль%'),UPPER('%ткань%'),UPPER(''%Тюль%с%цветами%красная%'));
olegy123
энтузиаст
 
Сообщения: 1040
Зарегистрирован: 25.02.2016 12:10:20

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение wofs » 20.10.2017 11:36:33

Хм... а SIMILAR вроде то, что нужно для этой задачи.
Запрос вида
Код: Выделить всё
SELECT NAME FROM table WHERE
LOWER(text) SIMILAR TO LOWER('%тюль%')
AND
LOWER(text) SIMILAR TO LOWER('%с%')
AND
LOWER(text) SIMILAR TO LOWER('%цветами%')
AND
LOWER(text) SIMILAR TO LOWER('%красная%')

теряет во времени выполнения порядка 60%, по сравнению с
Код: Выделить всё
SELECT * FROM table where UPPER(text) LIKE UPPER('%Тюль%красная%с%цветами%');

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

Добавлено спустя 1 минуту 45 секунд:
olegy123 писал(а):Еще можно так:
Код: Выделить всё
SELECT * FROM table where UPPER(text) IN (UPPER('%тюль%'),UPPER('%ткань%'),UPPER(''%Тюль%с%цветами%красная%'));

У меня не вышло получить ничего, отличное от null. :(
Аватара пользователя
wofs
постоялец
 
Сообщения: 375
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение tema » 20.10.2017 11:40:36

Религия не позволяет использовать and?
Для "Тюль с цветами красная", например
Код: Выделить всё
select * from table where LOWER(text) LIKE LOWER('%Тюль%') and LOWER(text) LIKE LOWER('%с%') and LOWER(text) LIKE LOWER('%цветами%') and LOWER(text) LIKE LOWER('%красная%') and
tema
постоялец
 
Сообщения: 360
Зарегистрирован: 24.03.2011 20:19:27

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение olegy123 » 20.10.2017 11:43:57

IN - это пересечения.. им можно объединить несколько условий.
Хотя (UPPER('%тюль%'),UPPER('%ткань%'),UPPER(''%Тюль%с%цветами%красная%')) - неправильно..
Блин совсем забыл я SQL

Добавлено спустя 1 минуту 16 секунд:
tema писал(а):Для "Тюль с цветами красная", например

А если строка не однозначная? Что то выпадает из условия?
olegy123
энтузиаст
 
Сообщения: 1040
Зарегистрирован: 25.02.2016 12:10:20

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение wofs » 20.10.2017 11:48:59

tema писал(а):Религия не позволяет использовать and?

Точно!

Добавлено спустя 1 минуту 10 секунд:
olegy123 писал(а):А если строка не однозначная? Что то выпадает из условия?

Выпадет, но в данном контексте это не важно.
Спасибо всем, развел на пустом месте демагогию :)

Добавлено спустя 56 секунд:
olegy123 писал(а):IN - это пересечения.. им можно объединить несколько условий.

Я почитаю поподробнее, сдается есть вариант использовать для другого.
Аватара пользователя
wofs
постоялец
 
Сообщения: 375
Зарегистрирован: 05.10.2009 10:16:55
Откуда: Астрахань

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение tema » 20.10.2017 12:08:35

olegy123 писал(а):
tema писал(а):Для "Тюль с цветами красная", например

А если строка не однозначная? Что то выпадает из условия?

В смысле? Перебрать циклом все слова запроса и составить такой select, который я написал
tema
постоялец
 
Сообщения: 360
Зарегистрирован: 24.03.2011 20:19:27

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение WAYFARER » 20.10.2017 20:28:13

http://www.textolution.com/ftsib.asp - в каком состоянии проект - неизвестно
Или использовать сфинкса (https://www.firebirdsql.org/en/sphinx-full-text-search/ )
Или как вариант перенести БД на Ред (http://www.red-soft.ru/ru/main_products.html#rbd)

Добавлено спустя 3 минуты 59 секунд:
Код: Выделить всё
select * from table where LOWER(text) LIKE LOWER('%Тюль%') and LOWER(text) LIKE LOWER('%с%') and LOWER(text) LIKE LOWER('%цветами%') and LOWER(text) LIKE LOWER('%красная%')

Таким запросом найдется именно "тюль с цветами красная", но не найдется просто "красная тюль" или "тюль с цветами".

Добавлено спустя 6 минут 20 секунд:
Еще как вариант вообще отказаться от использования FireBird.
Для каждого проекта нужно подбирать СУБД согласно потребностям.
Аватара пользователя
WAYFARER
постоялец
 
Сообщения: 431
Зарегистрирован: 09.10.2009 00:00:04
Откуда: г. Курган

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение Mirage » 20.10.2017 23:10:06

Для этого используется Sphynx или Elastic search. Последний есть обертка на Lucene.
Что они делают - индексируют указанные поля, строят индекс и по этому индексу быстро обрабатывают поисковые запросы. Указанные варианты легко настраиваются.
У PostgreSQL есть встроенный поиск, который вроде бы тоже позволяет такой поиск сделать.
Другое дело, что если записей так мало (300K), то это как из пушки по воробьям бить. Так что имеет смысл попробовать получить требуемое с помощью LIKE/SIMILAR TO.
Хотя можно на PostgreSQL перелезть, полезно будет в любом случае.
Mirage
энтузиаст
 
Сообщения: 829
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Firebird нечеткий поиск. А как ищете вы?

Сообщение tema » 20.10.2017 23:51:49

WAYFARER писал(а):Добавлено спустя 3 минуты 59 секунд:
Код: Выделить всё
select * from table where LOWER(text) LIKE LOWER('%Тюль%') and LOWER(text) LIKE LOWER('%с%') and LOWER(text) LIKE LOWER('%цветами%') and LOWER(text) LIKE LOWER('%красная%')

Таким запросом найдется именно "тюль с цветами красная", но не найдется просто "красная тюль" или "тюль с цветами".

Запрос составляется программно. И будет составлен по конкретному запросу с помощью цикла по всем словам.
Для других запросов составится по их словам:
WAYFARER писал(а):но не найдется просто "красная тюль" или "тюль с цветами".

Код: Выделить всё
select * from table where LOWER(text) LIKE LOWER('%тюль%') and LOWER(text) LIKE LOWER('%с%') and LOWER(text) LIKE LOWER('%цветами%')

Код: Выделить всё
select * from table where LOWER(text) LIKE LOWER('%красная%') and  LOWER(text) LIKE LOWER('%тюль%')
tema
постоялец
 
Сообщения: 360
Зарегистрирован: 24.03.2011 20:19:27

След.

Вернуться в Базы данных

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6

Рейтинг@Mail.ru