如何在PostgreSQL中将单词列表与句子列表进行比较?

4

我有一个用于存储单词的PostgreSQL表:

CREATE TABLE IF NOT EXISTS words
(
    id bigint NOT NULL DEFAULT nextval('processed_words_id_seq'::regclass),
    keyword character varying(300) COLLATE pg_catalog."default",
)

insert into words (words)
VALUES ('while swam is interesting');

CREATE TABLE IF NOT EXISTS trademarks
(
   id bigint NOT NULL DEFAULT nextval('trademarks_id_seq'::regclass),
   trademark character varying(300) COLLATE pg_catalog."default",
)

在表格trademarks中,我将有数千个注册商标名称。 我想要比较存储在words表格中的单词,关键字是否匹配,不仅对于一个单词,还包括一组单词中的单词。例如:

我有一个关键字while swam is interesting存储在words.keyword中。我还有一个商标swam位于trademarks.trademark中,我有一个单词匹配,所以我想使用SQL检测这个。我该如何实现?


有了一个好的服务器,您可以跨越两个表并尝试类似的方法,即使使用全文搜索也会遇到相同的问题,您可以使用动态SQL并构建正则表达式。 - nbk
3个回答

2

看起来这是一个全文搜索数据类型和函数的任务,大概会像这样:

select w.id, w.keyword, t.trademark 
from words w
inner join trademarks t on w.keyword::tsvector @@ t.trademark::tsquery;

这里有一个工作示例

在文档中

如果商标字段包含多个单词,则使用更灵活的查询

select w.id, w.keyword, t.trademark 
from words w
inner join trademarks t on w.keyword::tsvector @@ 
regexp_replace(t.trademark, '\s', ' | ', 'g' )::tsquery;

管道符号表示逻辑“或”,根据您的需求可以替换为其他操作数 此处示例。 当然,需要进行索引以加快搜索速度, 检查 文本搜索索引创建。

另一个例子是避免在tsquery中使用一些特殊字符(在这种情况下是括号)和尾随空格,并考虑到多个单词的可能性,如评论中指出

select w.id, w.keyword, t.trademark 
from words w
inner join trademarks t on regexp_replace(w.keyword,'\(|\)', ' ', 'g' )::tsvector 
@@ regexp_replace(regexp_replace(trim(t.trademark),'\(|\)', ' ', 'g' )
, '\s+?(?=[a-zA-z])', ' | ', 'g' )::tsquery;    

需要注意的是,tsquery是一种逻辑句子,其中有一些特殊字符需要避免使用。请查看 tsquery的官方文档。


我想在源表中的生成的tsvector列上通过GIN/GiST索引添加有关聚类的内容,但事实证明它已经几乎逐字地出现在您提供的文档中。因此,我将留下一个赞,并重申它非常有用。 - Zegarek
我尝试了第二个例子,但是出现了错误:ERROR: no operand in tsquery: "Google | " CONTEXT: parallel worker SQL state: 42601 - Peter Penzov
我第一次尝试时遇到了错误:“tsquery中的语法错误:'Caterpillar(CAT)'”。SQL状态:42601。 - Peter Penzov
第二个例子通过操作符“or”将多个查询词(以空格分隔)拆分。因此,输入字段应该有多个单词。在查询词“Caterpillar(CAT)”的语法错误上,可能需要转义那些括号,我会检查一下。 - Pepe N O
添加了另一个查询,避免使用括号,但应考虑其他特殊字符,因为tsquery是一个逻辑语句。 - Pepe N O

0

要检查商标是否存在于单词表中的关键字列表中,您可以在SELECT语句中使用LIKE运算符。例如:

SELECT keyword
FROM words
WHERE keyword LIKE '%swam%';

这将返回包含单词“swam”的任何关键字,包括示例关键字“while swam is interesting”。

如果您想要在单词表中查找商标的精确匹配项,则可以使用=运算符而不是LIKE:

SELECT keyword
FROM words
WHERE keyword = 'swam';

这将仅返回完全为“swam”的关键字,没有任何其他单词在其前面或后面。

您还可以使用IN运算符来检查商标是否存在于单词表中:

SELECT keyword
FROM words
WHERE keyword IN ('swam');

这将返回所有确切为“swam”的关键字。

请注意,在所有这些示例中,都没有使用商标表。如果您想将单词表中的关键字与商标表中的商标进行比较,可以在SELECT语句中使用JOIN子句。例如:

SELECT w.keyword, t.trademark
FROM words w
JOIN trademarks t ON w.keyword = t.trademark;

这将返回一个关键词商标对的列表,其中关键词和商标相同。然后,您可以使用此列表来识别单词和商标表之间的任何匹配项。


-1

PostgreSQL对正则表达式有很好的支持,应该能够提供解决方案。相关操作符在这里描述。例如,如果要求仅使用不区分大小写的匹配来匹配精确单词,则可以使用以下POSIX正则表达式匹配器:

w.keyword ~* CONCAT('([^[:word:]]|^)', t.trademark, '([^[:word:]]|$)')

这将查看正在匹配的单词(例如swam)之前和之后的单个字符(如果有),以确保两者都不是单词字符。因此,在示例while swam is interesting中,这两个字符都将是空格,因此它将匹配。

这里有一个演示,添加了一些进一步的数据以显示哪些行被匹配(t = 匹配,f = 不匹配)。

当然,还有其他可能的要求,例如部分词匹配和大小写敏感匹配——如果本答案没有提供好的解决方案,请在评论中让我知道。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接