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

Объяснение

Вложенная группа автоматически не приводит к катастрофическому обратному отскоку. В вашем случае это связано с тем, что ваше регулярное выражение вырождается в классический пример катастрофического обратного отсчета (a*)*.

Поскольку \s в необязательном в ^([a-zA-Z0-9'-]+\s?)*$, на входе без каких-либо пробелов, но имеет символы вне разрешенных list, регулярное выражение просто вырождается до ^([a-zA-Z0-9'-]+)*$.

Вы также можете думать о расширении исходного регулярного выражения:

[a-zA-Z0-9'-]+\s?[a-zA-Z0-9'-]+\s?[a-zA-Z0-9'-]+\s?[a-zA-Z0-9'-]+\s?...

Поскольку \s является необязательным, мы можем удалите его:

[a-zA-Z0-9'-]+[a-zA-Z0-9'-]+[a-zA-Z0-9'-]+[a-zA-Z0-9'-]+...

И мы получили серию последовательных [a-zA-Z0-9'-]+, которые будут пытаться распространять символы между собой и взорвать сложность.

Решение

Стандартный способ записи регулярного выражения в соответствие с token delimiter token ... delimiter token - token (delimiter token)*. Хотя можно переписать регулярное выражение, не повторять token, я бы рекомендовал против него, так как это сложно сделать правильно. Чтобы избежать повторения, вы можете захотеть создать регулярное выражение путем конкатенации строк.

Следуя рецепту выше:

^[a-zA-Z0-9'-]+(\s[a-zA-Z0-9'-]+)*$

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

[a-zA-Z0-9'-]+\s[a-zA-Z0-9'-]+\s[a-zA-Z0-9'-]+\s[a-zA-Z0-9'-]+...

И \s и [a-zA-Z0-9'-] взаимно исключают друг друга - есть только один способ сопоставления любой строки.

2
задан Matt Weber 27 June 2019 в 19:35
поделиться

1 ответ

Короткий ответ - то, что можно использовать функциональность полнотекстового поиска Пост-ГРЭС со специализированной поисковой конфигурацией.

Начиная с Вашего контакта с названиями места, Ваш, вероятно, не хотят происходить, таким образом, можно использовать простую конфигурацию в качестве начальной точки. Можно также добавить стоп-слова, которые имеют смысл для названий места (с примерами выше, можно, вероятно, рассмотреть "Св.", "Святого" и "del" как стоп-слова).

А довольно основная схема установки Вашего специализированного ниже:

  1. Создают файл стоп-слов и помещают его в Ваш $SHAREDIR/tsearch_data каталог Postgres. См. https://www.postgresql.org/docs/9.1/static/textsearch-dictionaries.html#TEXTSEARCH-STOPWORDS.
  2. Создают словарь, который использует этот список стоп-слов (можно, вероятно, использовать pg_catalog.simple в качестве шаблонного словаря). См. https://www.postgresql.org/docs/9.1/static/textsearch-dictionaries.html#TEXTSEARCH-SIMPLE-DICTIONARY.
  3. Создают поисковую конфигурацию для названий места. См. https://www.postgresql.org/docs/9.1/static/textsearch-configuration.html .
  4. Изменяют Вашу поисковую конфигурацию для использования словаря, который Вы создали на Шаге 2 (cf. ссылка выше).

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

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

SELECT cities."id"
FROM cities
    INNER JOIN "state" ON "state".id = cities.state_id
WHERE
    "state".short_name = 'CA'
    AND TO_TSVECTOR('places', cities.name) @@ TO_TSQUERY('places', 'Los & Angeles')
1
ответ дан Zack 3 July 2019 в 04:10
поделиться
  • 1
    Трудно сказать - there' s jsperf, хотя один want' s для измерения его. OTOH эти два оператора имеют полное различное значение. Только требуя числа (и не целое число) ' + ' так или иначе один символ короче. – Aki Suihkonen 1 March 2013 в 06:58
Другие вопросы по тегам:

Похожие вопросы: