如何使用 PredicateBuilder、EF Core 5 和 Postgresql 10+ 执行不区分大小写和重音的 LIKE(子字符串)查询?
Posted
技术标签:
【中文标题】如何使用 PredicateBuilder、EF Core 5 和 Postgresql 10+ 执行不区分大小写和重音的 LIKE(子字符串)查询?【英文标题】:How can I perform a case- and accent- insensitive LIKE (substring) query using PredicateBuilder, EF Core 5, and Postgresql 10+? 【发布时间】:2021-04-30 02:26:03 【问题描述】:在 SQL Server 中,使用 EF Core 5 和 PredicateBuilder 创建不区分大小写、不区分重音、LIKE
查询相对简单。
例如:
用户正在尝试使用标准北美键盘在数据库中查找客户(即重音很难键入)。 搜索helene
应该匹配Mme. Hélène Laurendeau
。重要的是我们可以匹配 子字符串 而不仅仅是前缀或后缀。
假设我们有一个实体Customer
,其属性为Name
,则以下 sn-p 将按预期工作:
var predicate = PredicateBuilder
.New<Customer>(c => EF.Functions.Collate(c.Name,
"Latin1_general_CI_AI")
.Contains("helen"));
var customers = context.Customers.AsExpandable().Where(predicate);
我们如何在 PostgreSQL(10 或更高版本)中执行相同的查询?
我们刚刚从 SQL Server 进行了一次快速(基本上是 1:1)迁移,并正在尝试更新我们的代码以确保可以进行一般迁移。此问题没有考虑可能的查询速度问题(请参阅此处的链接以获取更多信息。)
【问题讨论】:
【参考方案1】:假设您新创建的 Postgres 数据库是 UTF8(我相信它是默认的)
-
确保已安装
unaccent
。如果没有,CREATE EXTENSION unaccent;
更新您的predicate
如下:
var predicate = PredicateBuilder
.New<Customer>(c => EF.Functions.ILike(EF.Functions.Unaccent(c.Name),
"%helen%"));
-
利润! :)
注意:可以整理关于 SO 和其他来源的各种问题的答案以得出这个结论,但我一直无法找到一个有意义的地方发表评论很容易找到的解决方案。另外,我不认为引入全文搜索是这个问题的答案,但如果我弄错了,我很乐意更新它。
This answer 是迄今为止我见过的最好、最完整的一个,并强烈鼓励人们在有时间的时候深入研究它。如果你想从 SQL Server 迁移到但是,作为原型的 Postgres,这个答案应该可以为您节省很多痛苦和时间:)
一些答案建议在列的 lowercase
/ unaccent
-ed 版本上创建索引,但这不能直接工作,因为 unaccent
不是 IMMUTABLE
。您可以根据需要包装它们,然后将它们编入索引(链接中的示例。)
此外,尝试通过EF.Functions
直接传递排序规则(在服务器上创建它之后)似乎也不起作用,但也许我在那里缺少关于 Postgres 的一些东西。
可能可以tweak individual column collations。
一些相关问题包括:
PostgreSQL accent + case insensitive search Query PostgreSQL with Npgsql and Entity Framework using unaccent Does PostgreSQL support "accent insensitive" collations?其他来源:
https://github.com/dotnet/efcore/issues/8813 https://docs.microsoft.com/en-us/ef/core/miscellaneous/collations-and-case-sensitivity http://www.albahari.com/nutshell/predicatebuilder.aspx【讨论】:
以上是关于如何使用 PredicateBuilder、EF Core 5 和 Postgresql 10+ 执行不区分大小写和重音的 LIKE(子字符串)查询?的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法将 PredicateBuilder 与 Azure 表存储一起使用?
Entity Framework 4.1 Code First - 使用 LinqKit PredicateBuilder 时忽略包含