在Linq/ODataController中使用全文搜索
本文关键字:文搜索 搜索 Linq ODataController | 更新日期: 2023-09-27 18:27:14
我正在开发一个通过OData提供数据的应用程序。我使用ASP.Net和ODataControllers通过EF进行查询——数据由SQLServer数据库支持。
在可视化这些数据的前端网站上,用户可以搜索结果——在前端动态创建$过滤器,并发送OData请求(允许服务器端过滤)。
在支持最终通过OData提供的数据的数据库表上,启用了全文搜索,但它出现在管道OData filter->Linq query->SQL query中,使用LIKE搜索而不是全文Contains()方法。
有没有任何人知道的方法可以以一种相当优雅的方式使用全文功能?
据推测,我可以使用自定义IODataPathHandler
和/或IODataPathTemplateHandler
和/或其他一些东西来拦截管道中的点,但如果可能的话,我宁愿尽量避免这种情况。
有什么建议吗?
contains
函数用于执行简单的子字符串匹配。OData规范定义了用于全文搜索的$search
查询选项,但Web API当前不支持$search
。(这是一个悬而未决的问题。)
您的最佳选择可能是自定义查询选项(例如,/Customers?fulltextsearch=contains(Name, 'Arianne')
),但您必须编写所有代码来解析该选项,等等。
如果您决定将OData contains
映射到T-SQL CONTAINS
,那么您将需要截取Linq到实体的转换。查看现有ContainsTranslator的源代码并进行反向工作。
为此使用拦截器和自定义EnableQueryAttribute:
- 如本文所述定义一个
FtsInterceptor
类,并将其添加到您的上下文DbInterception.Add(new FtsInterceptor())
中 定义
EnableQueryAttribute
类的子类,并覆盖ApplyQuery
方法,为OData contains函数的所有参数添加FullTextPrefix(-FTSPREFIX-):public class FullTextSearchAttribute : EnableQueryAttribute { public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions) { if (queryOptions.Filter == null) return queryOptions.ApplyTo(queryable); const string pattern = "contains''([%20]*[^%27]*[%20]*,[%20]*%27(?<Value>[^%27]*)"; var matchEvaluator = new MatchEvaluator(match => { var value = match.Groups["Value"].Value; return match.Value.Replace($"%27{value}", $"%27-FTSPREFIX-{value}"); }); var request = new HttpRequestMessage(HttpMethod.Get, Regex.Replace(queryOptions.Request.RequestUri.AbsoluteUri, pattern, matchEvaluator, RegexOptions.IgnoreCase)); return new ODataQueryOptions(queryOptions.Context, request).ApplyTo(queryable); } }
使用代码中的属性:
[FullTextSearchAttribute] public IQueryable<YourDomainClass> Get() { //Query }