2015-12-17 3 views
2

Я работаю над приложением, которое обслуживает данные через OData. Я использую ASP.Net и ODataControllers запрос через EF - данные поддерживаются базой данных SQLServer.Использование полнотекстового поиска в Linq/ODataController

На внешнем веб-сайте, который визуализирует эти данные, пользователь может выполнять поиск - на переднем конце динамически создается фильтр $ filter, и отправляется запрос OData (разрешая фильтрацию на стороне сервера).

В таблице базы данных, поддерживающей данные, которые в конечном итоге обслуживаются через OData, полнотекстовый поиск включен, но он отображается в конвейере. Фильтр OData -> Запрос Linq -> SQL, используется поиск LIKE вместо полнотекстовый метод Contains().

Есть ли способ, которым кто-либо знает, чтобы использовать полнотекстовые возможности в разумно элегантном стиле?

Предположительно, я могу много пообщаться с обычным IODataPathHandler и/или IODataPathTemplateHandler и/или некоторыми другими вещами, чтобы перехватить точки в конвейере, но я скорее попытаюсь избежать этого, если это возможно.

Любые советы?

ответ

1

Функция OData's contains предназначена для выполнения простого подстрочного соответствия. Спецификация OData определяет параметр запроса $search для полнотекстового поиска, но в настоящее время Web API не поддерживает $search. (Существует open issue.)

Лучше всего, вероятно, пользовательский вариант запроса (например, /Customers?fulltextsearch=contains(Name, 'Arianne')), но вы должны написать весь код для разбора опции и т.д.

Если вы определяются для сопоставления OData contains с T-SQL CONTAINS, тогда вам нужно будет перехватить перевод, выполняемый Linq в Entities. Посмотрите на исходный код для существующего ContainsTranslator и работайте в обратном направлении.

1

Используйте interceptor и обычай EnableQueryAttribute для этой цели:

  1. Определить FtsInterceptor класс, как описано в статье, и добавить его в свой контекст - DbInterception.Add(new FtsInterceptor()).
  2. Определить подкласс EnableQueryAttribute класса и переопределить метод ApplyQuery добавление FullTextPrefix (-FTSPREFIX-) для всех параметров функции OData contains:

    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. использовать атрибут в коде:

    [FullTextSearchAttribute] 
    public IQueryable<YourDomainClass> Get() 
    { 
        //Query 
    } 
    
Смежные вопросы