Проверьте сходство в строке, используя Postgres - PullRequest
0 голосов
/ 07 мая 2020

Я не могу раскрыть фактические данные, поэтому использую только пример. У меня есть две таблицы, одна из которых - таблица словаря, в которой есть идентификаторы для заголовков. Вторая таблица - это новые данные, которые поступают в базу данных и не имеют идентификаторов. Мне нужно обновить идентификатор для новых данных, проверив в таблице словаря, есть ли у меня что-то подобное уже там, или обновить словарь новым значением. и получите для него новый идентификатор и обновите его для новых данных. Я ожидаю, что они будут обновлены в столбце Expected ID во второй таблице.

ID  Title

--  ------------------------

1   Aliens
2   The Hunger Games
3   John Wick
4   Alien vs Predator



ID  Title                                         Expected ID

----------------------------------------------------------------

null   The Hunger Games: Mockingjay Part I        2
null   The Hunger Games: Mockingjay Part II       2
null   John Wick (2014)                           3
null   John Wick Chapter 2                        3
null   Alien                                      1
null   Aliens                                     1
null   Alien 3                                    1
null   Lord of the Rings                          5 (New ID generated)

1 Ответ

0 голосов
/ 07 мая 2020

Это похоже на задачу для pg_trgm . Он предоставляет вам оператор %, который возвращает истину, если две строки «достаточно близки». Вы можете настроить, что означает «достаточно близко», изменив pg_trgm.similarity_threshold. Вы можете создать индекс, чтобы ускорить эту операцию. Чем выше значение Similarity_threshold, тем большего ускорения вы, вероятно, достигнете.

Если я возьму вам сначала показанную таблицу как foo1, а все отдельные заголовки из желаемого результата как foo2, тогда этот запрос даст разумные результаты:

select *, foo1.title <-> foo2.title as distance from foo2 left join foo1 on foo1.title % foo2.title;

                title                 |   id   |       title       | distance  
--------------------------------------+--------+-------------------+-----------
 The Hunger Games: Mockingjay Part I  |      2 | The Hunger Games  | 0.5142857
 The Hunger Games: Mockingjay Part II |      2 | The Hunger Games  | 0.5277778
 John Wick (2014)                     |      3 | John Wick         | 0.3333333
 John Wick Chapter 2                  |      3 | John Wick         |       0.5
 Alien                                |      1 | Aliens            |     0.375
 Alien                                |      4 | Alien vs Predator | 0.6666666
 Aliens                               |      1 | Aliens            |         0
 Alien 3                              |      1 | Aliens            |       0.5
 Alien 3                              |      4 | Alien vs Predator |       0.7
 Lord of the Rings                    | (null) | (null)            |    (null)

Если вам нужна одна выходная строка для каждого foo2, показывающая только «лучшее» совпадение, тогда вы должны использовать LEFT JOIN LATERAL:

select *, a.title <-> foo2.title as distance from foo2 left join lateral 
    (select * from foo1 where foo1.title % foo2.title order by foo1.title <-> foo2.title limit 1) a
    on true;
                title                 |   id   |      title       | distance  
--------------------------------------+--------+------------------+-----------
 The Hunger Games: Mockingjay Part I  |      2 | The Hunger Games | 0.5142857
 The Hunger Games: Mockingjay Part II |      2 | The Hunger Games | 0.5277778
 John Wick (2014)                     |      3 | John Wick        | 0.3333333
 John Wick Chapter 2                  |      3 | John Wick        |       0.5
 Alien                                |      1 | Aliens           |     0.375
 Aliens                               |      1 | Aliens           |         0
 Alien 3                              |      1 | Aliens           |       0.5
 Lord of the Rings                    | (null) | (null)           |    (null)

Как заменить NULL в столбце «id» (где нет достаточно близких совпадений) с вновь созданным идентификатором - это отдельный вопрос, и вам следует задавать отдельные вопросы отдельно.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...