2016-07-08 17 views
5

Я Sitecore страниц/Lucene документы со следующими полями:Sitecore Поиск Predicate Builder множественный поиск ключевых слов с повышения не работает по желанию

  • Название
  • Имя файла
  • Содержание
  • Содержимое файла

Я создаю их поиск и предъявляю следующие требования:

  • Хиты, содержащие всю фразу в заголовке поле должно быть возвращено сперва.
  • Хиты, содержащие всю фразу в filename Поле должно быть возвращено во-вторых.
  • Hits, содержащий всю фразу в содержании должен быть возвращен третьим
  • Hits, содержащего всю фразу в содержании файла должен быть возвращен четвёртой
  • Хитов содержащих все ключевых слов (в любом порядке) в поле заголовка должен быть возвращен пятым
  • Хитов содержащих все ключевых слов (в любом порядке), в поле имени файла должно быть возвращено шестой
  • Хиты, содержащие все ключевых слов (в любом порядке) в содержание должно быть возвращено седьмое.
  • Хиты, содержащие все ключевых слов (в любом порядке) в содержание файла должно быть возвращено восьмое.

Вот что я получил:

public static Expression<Func<T, bool>> GetSearchTermPredicate<T>(string searchTerm) 
     where T : ISearchableItem 
    { 
     var actualPhrasePredicate = PredicateBuilder.True<T>() 
      .Or(r => r.Title.Contains(searchTerm).Boost(2f)) 
      .Or(r => r.FileName.Contains(searchTerm).Boost(1.5f)) 
      .Or(r => r.Content.Contains(searchTerm)) 
      .Or(r => r.DocumentContents.Contains(searchTerm)); 

     var individualWordsPredicate = PredicateBuilder.False<T>(); 

     foreach (var term in searchTerm.Split(' ')) 
     { 
      individualWordsPredicate 
       = individualWordsPredicate.And(r => 
        r.Title.Contains(term).Boost(2f) 
       || r.FileName.Contains(term).Boost(1.5f) 
       || r.Content.Contains(term) 
       || r.DocumentContents.Contains(term)); 
     } 

     return PredicateBuilder.Or(actualPhrasePredicate.Boost(2f), 
      individualWordsPredicate); 
    } 

Реальная фраза часть кажется, работает хорошо. Сначала возвращаются хиты с полной фразой в заголовке. Однако, если я удаляю слово из середины фразы, результаты не возвращаются.

У меня есть страница с заголовком «Футбольная команда Англии ужасна», но когда я ищу «Футбольная команда ужасна», она не находит страницу.

Примечание: страницы могут иметь прикрепленные к ним документы, поэтому я хочу также увеличить имена файлов, но не так сильно, как заголовок страницы.

ответ

4

мне удалось получить эту работу со следующим:

public static Expression<Func<T, bool>> GetSearchTermPredicate<T>(string searchTerm) 
     where T : ISearchableItem 
    { 
     var actualPhraseInTitlePredicate = PredicateBuilder.True<T>() 
      .And(r => r.Title.Contains(searchTerm)); 

     var actualPhraseInFileNamePredicate = PredicateBuilder.True<T>() 
      .And(r => r.FileName.Contains(searchTerm)); 

     var actualPhraseInContentPredicate = PredicateBuilder.True<T>() 
      .And(r => r.Content.Contains(searchTerm)); 

     var actualPhraseInDocumentPredicate = PredicateBuilder.True<T>() 
      .And(r => r.DocumentContents.Contains(searchTerm)); 

     var terms = searchTerm.Split(' '); 

     var titleContainsAllTermsPredicate = PredicateBuilder.True<T>(); 

     foreach (var term in terms) 
      titleContainsAllTermsPredicate 
       = titleContainsAllTermsPredicate.And(r => r.Title.Contains(term).Boost(2f)); 

     var fileNameAllTermsContains = PredicateBuilder.True<T>(); 

     foreach (var term in terms) 
      fileNameAllTermsContains 
       = fileNameAllTermsContains.And(r => r.FileName.Contains(term)); 

     var contentContainsAllTermsPredicate = PredicateBuilder.True<T>(); 

     foreach (var term in terms) 
      contentContainsAllTermsPredicate 
       = contentContainsAllTermsPredicate.And(r => r.Content.Contains(term)); 

     var documentContainsAllTermsPredicate = PredicateBuilder.True<T>(); 

     foreach (var term in terms) 
      documentContainsAllTermsPredicate 
       = documentContainsAllTermsPredicate.And(r => r.DocumentContents.Contains(term)); 


     var predicate = actualPhraseInTitlePredicate.Boost(3f) 
      .Or(actualPhraseInFileNamePredicate.Boost(2.5f)) 
      .Or(actualPhraseInContentPredicate.Boost(2f)) 
      .Or(actualPhraseInDocumentPredicate.Boost(1.5f)) 
      .Or(titleContainsAllTermsPredicate.Boost(1.2f)) 
      .Or(fileNameAllTermsContains.Boost(1.2f)) 
      .Or(contentContainsAllTermsPredicate) 
      .Or(documentContainsAllTermsPredicate); 

     return predicate; 
    } 

Это, очевидно, совсем немного больше кода, но я думаю, отделяя предикаты имеет смысл для повышения эффективной работы.

Основная проблема с предыдущим кодом был два раза:

  1. PredicateBuilder.Or(actualPhrasePredicate.Boost(2f), individualWordsPredicate), кажется, не включает предикат OR-нут. При выполнении .ToString() на результирующее присоединился предикат, выражение не содержит ничего для individualWordsPredicate
  2. После фиксации, что она по-прежнему не работает, и это потому, что я использовал PredicateBuilder.False<T>() для individualWordsPredicate. Рассматривая выражение, он в основном производил (False AND Field.Contains(keyword)), который, конечно же, никогда не будет оценен как истинный. С помощью .True<T>() исправлено это.

 Смежные вопросы

  • Нет связанных вопросов^_^