我使用postgres的tsquery函数来搜索可能包含多种语言的字母和数字的字段。似乎在任何情况下,搜索都会工作到搜索短语的一部分,并停止工作,直到你写出完整的短语。
例如:当搜索项为"15339"时,搜索名称"15339"会输出右侧行,但如果是"153"则不会。
搜索Al Alamya时,如果单词是"Al-",它会起作用并返回行,但在之后添加字母,例如,"Al-alam"在我写完全名("Al-Alamya"(之前不会返回。
我的查询:
SELECT *
FROM (SELECT DISTINCT ON ("consumer_api_spot"."id") "consumer_api_spot"."id",
"consumer_api_spot"."name",
FROM "consumer_api_spot"
INNER JOIN "consumer_api_account" ON ("consumer_api_spot"."account_id" = "consumer_api_account"."id")
INNER JOIN "users_user" ON ("consumer_api_account"."id" = "users_user"."account_id")
WHERE (
users_user.id = 53 AND consumer_api_spot.active
AND
"consumer_api_spot"."vectorized_name" @@ tsquery('153')
)
GROUP BY "consumer_api_spot"."id"
) AS "Q"
LIMIT 50 OFFSET 0
如果查看文档,您会发现有关可以指定为tsquery
的内容的更多信息。它们支持分组,使用布尔运算进行组合,还支持前缀,这可能是您想要的。文档中的一个示例:
此外,
tsquery
中的词法可以用*
标记,以指定前缀匹配:SELECT 'super:*'::tsquery;
此查询将匹配
tsvector
中以"super"开头的任何单词。
因此,在查询中,您应该将tsquery('153')
的部分修改为tsquery('153:*')
。
Btw。我不知道您是如何构建数据库模式的,但您可以使用GIN索引为列添加tsvector
索引。我假设您从"consumer_api_spot"."name"
列生成"consumer_api_spot"."vectorized_name"
列。如果是这种情况,您可以为该列创建一个tsvector
索引,如下所示:
CREATE INDEX gin_name on consumer_api_spot using gin (to_tsvector('english',name))
然后你可以更改这个查询:
"consumer_api_spot"."vectorized_name" @@ tsquery('153')
进入这个:
to_tsvector('english', "consumer_api_spot"."name") @@ to_tsquery('english', '153:*')
并获得潜在的速度优势,因为查询将使用索引。
关于'english'
的注意事项:创建索引时不能省略语言,但它不会对其他语言的查询或带数字的查询产生影响。但是,请注意,创建索引和执行查询的语言必须相同,才能使PostgreSQL使用索引。