在Linq / ODataController中使用全文搜索

4
我正在开发一个应用程序,通过OData提供数据。我使用ASP.Net和ODataControllers通过EF查询 - 数据由SQLServer数据库支持。
在可视化此数据的前端网站上,用户可以搜索结果,前端动态创建$filter,并发送OData请求(允许服务器端过滤)。
在最终通过OData提供服务的数据的数据库表上启用了全文搜索,但在管道中的OData filter -> Linq query -> SQL query中,使用的是LIKE搜索,而不是全文Contains()方法。
有没有人知道以合理优雅的方式利用全文本能力的方法?
可能我可以通过自定义IODataPathHandler和/或IODataPathTemplateHandler和/或其他一些东西来拦截管道中的点,但如果可能的话,我宁愿避免这样做。
有什么建议吗?
2个回答

1

使用拦截器和自定义EnableQueryAttribute来实现这个目的:

  1. Define a FtsInterceptor class as described in the article and add it to your context - DbInterception.Add(new FtsInterceptor()).
  2. Define a subclass of the EnableQueryAttribute class and override the ApplyQuery method adding FullTextPrefix (-FTSPREFIX-) for all parameters of the OData contains function:

    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);
        }
    }
    
  3. Use the attribute in your code:

    [FullTextSearchAttribute]
    public IQueryable<YourDomainClass> Get()
    {
        //Query 
    }
    

1

OData的contains函数是用于执行简单的子字符串匹配。OData规范为全文搜索定义了$search查询选项,但Web API目前不支持$search。(有一个未解决问题。)

你最好使用自定义查询选项(例如:/Customers?fulltextsearch=contains(Name,'Arianne')),但你需要编写所有解析选项的代码等。

如果你决定将OData的contains映射到T-SQL的CONTAINS,那么你需要拦截Linq to Entities所做的转换。查看现有ContainsTranslator的源代码并向后工作。


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