Что нового в PostgreSQL 11: встроенный веб-поиск



    Продолжая тему интересных возможностей грядущего релиза PostgreSQL 11, я хотел бы рассказать про новую встроенную функцию websearch_to_tsquery. Соответствующий патч разработали Виктор Дробный и Дмитрий Иванов, с правками от Федора Сигаева. Давайте же разберемся, что реализовано в этом патче.

    Казалось бы, полнотекстовый поиск есть в PostgreSQL уже давно, и он очень даже неплохо работает. Что тут еще можно было добавить?

    Представьте, что вы делаете интернет-магазин на базе PostgreSQL и вам нужен поиск по товарам. Вот вам прилетела форма с поисковым запросом. Для поиска по базе из этого запроса нужно как-то построить tsvector. Можно сделать это с помощью функции to_tsquery. Но to_tsquery ожидает, что строка будет в определенном формате:

    =# select to_tsquery('foo bar baz');
    ERROR: syntax error in tsquery: "foo bar baz"

    =# select to_tsquery('foo & bar & baz');
    to_tsquery
    -----------------------
    'foo' & 'bar' & 'baz'

    Другими словами, в этом случае придется написать функцию, преобразующую запрос пользователя в запрос, понятный to_tsquery. Неудобно. Отчасти эту проблему решают функции plainto_tsquery и phraseto_tsquery:

    =# select plainto_tsquery('foo bar baz');
    plainto_tsquery
    -----------------------
    'foo' & 'bar' & 'baz'

    =# select phraseto_tsquery('foo bar baz');
    phraseto_tsquery
    ---------------------------
    'foo' <-> 'bar' <-> 'baz'

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

    =# select plainto_tsquery('"foo bar" -baz or qux');
    plainto_tsquery
    -------------------------------
    'foo' & 'bar' & 'baz' & 'qux'

    Все сломалось! Ой. Неужели все-таки придется писать свой парсер?

    Вот чтобы его не приходилось писать с нуля для каждого приложения, начиная с PostgreSQL 11 соответствующий парсер теперь будет прямо в СУБД:

    =# select websearch_to_tsquery('"foo bar" -baz or qux');
    websearch_to_tsquery
    ----------------------------------
    'foo' <-> 'bar' & !'baz' | 'qux'

    Помимо того, что websearch_to_tsquery понимает кавычки, знак минус и булевы операторы, он интересен тем, что игнорирует любые попытки сделать синтаксическую ошибку. То есть, вы никогда не получите ошибку, на выходе всегда будет какой-то tsquery:

    =# select websearch_to_tsquery('-"foo bar" ((( baz or or qux !@#$%^&*_+-=');
    websearch_to_tsquery
    --------------------------------------
    !( 'foo' <-> 'bar' ) & 'baz' | 'qux'

    Еще из особенностей функции следует отметить тот факт, что она игнорирует любые скобки. То есть, вот так не прокатит:

    =# select websearch_to_tsquery('foo and (bar or baz)');
    websearch_to_tsquery
    -----------------------
    'foo' & 'bar' | 'baz'

    Данное поведение было выбрано из соображений, что нормальные люди (не айтишники :trollface:) на практике скобочки все равно не используют. Просто игнорируя их, мы существенно упрощаем реализацию фичи «сделать так, чтобы функция никогда не завершалась с ошибкой», да и разбор запроса будет работать быстрее. Возможно, флаг, включающий поддержку скобочек, появится в будущих версиях.

    Такая вот несложная, но полезная функция. Как минимум, она делает полнотекстовый поиск в PostgreSQL не хуже, чем он был до этого, и позволяет разработчикам упростить код своих приложений.

    Postgres Professional

    212,87

    Российский вендор PostgreSQL

    Поделиться публикацией
    Комментарии 11
      +1
      Здорово!
        0

        Здорово, конечно, но со скобочками они погорячились! Не так сложно было и сделать их.


        На моей памяти никто из обычных пользователей просто так кавычки не вставляет.

          +1

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


          Например в одном магазине нашёл нужный ноут, пошел искать в другом: 15.6 LED " / 3840x2160 (Матрица TFT IPS) / Intel Core i7 7820HQ

          +2

          Круто, реально хорошо, уже сталкивался с предыдущими методами))


          Но название нового метода не самое удачное, имхо
          Десктоп разработчики просто из-за названия могут пропустить этот метод, а у них тоже бывают поля для поиска)


          auto_to_tsquery, чуть более подходит и в будущем само название нормально позволяет добавлять возможностей))

            +1
            Но название нового метода не самое удачное

            +1
            Может search_term_to_tsquery
              0

              Или даже что-то вроде any_to_tsquery

            +1
            Спасибо, ждал такую фичу!
              0

              Сделали бы shared_ispell включенным по умолчанию лучше. Вообще не понимаю зачем делать было, чтобы каждое соединение больше 500мс тратилось на считывание словарей.

                –2

                Спасибо за Вашу работу но хотелось бы чтобы


                1. была минимальная альтернатива MARIADB — Медиавики нормально с PostgreSQL не работает, форумные движки и CMS в основной массе тоже тоже, https://www.mediawiki.org/wiki/Manual:PostgreSQL Самоя простая корпоративная сеть начинается с корпоративной базы знаний на mediawiki — нельзя поставить PostgreSQL — ставим мариюДБ, раз уже использовали мариюДБ — значит и всё остальное будет на ней.
                2. Хотелось бы видеть на Вашем сайте Wiki на PostgreSQL + демоверсии основных CMS + бенчмарки. + сделайте примеры в стиле Установка Mediawiki (CMS) на LAPgP, LNgnixPgP, на ALTLinux (Для школоты и преподов информатики), AstraLinux для админов с зарплатой 20-25 т.р. госконтор. Затрат по времени для ваших инженеров будет 1-2 человеко дня, а количество установок и соответственно поток баг-отчётов возрастёт в разы.

                PS я как вы поняли несколько раз повёлся на ваши статьи и пытался использовать PostgreSQL но не получилось :( Энтузиазм ещё не угас.
                Окончательно… :).
                Удачи. Порвите ср-й MySQL с бекдорами АНБ!
                Снами Сноуден! MySQL будет разбит! Победа будет за PostgreSQL !

                  0
                  А почему эту функцию не выпустить раньше релиза?
                    0
                    Релизный цикл не так работает и не для этого придуман. Желающие могут собрать PostgreSQL с этим патчем самостоятельно.

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

                  Самое читаемое