2016-07-08 49 views
5

我已經Sitecore的具有以下字段頁/ Lucene的文件不工作:Sitecore的搜索謂詞建設者促進多關鍵字搜索根據需要

  • 標題
  • 內容
  • 文件內容

我正在爲這些創建搜索並具有以下要求:

  • 點擊包含標題中的全部短語字段應該先返回。
  • 點擊包含文件名字段中的全部短語應返回第二位。
  • 包含在內容整個短語命中應返回一個包含在文件內容的整個短語第三
  • 命中應返回第四容納關鍵字的所有
  • 命中(以任意順序)在標題字段應在文件名域返回第五包含關鍵字的所有(以任何次序
  • 點擊率)應該退回第六
  • 點擊包含所有的關鍵字(任何順序)在內容應返回第七。
  • 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); 
    } 

實際的短語部分似乎運作良好。首先返回標題中的完整詞組。但是,如果從短語中間刪除單詞,則不會返回任何結果。

即我有一個標題爲「英格蘭足球隊可怕」的頁面,但是當我搜索「The football team is dreadful」時,它沒有找到頁面。

注意:頁面可以附加文檔,所以我想提高文件名,但不是頁面標題的高度。

回答

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>()修復了這個問題。