2009-10-27 434 views
7

我輸出給定字符串關鍵字的搜索結果列表,並且我希望突出顯示搜索結果中的任何匹配關鍵字。每個單詞應該用一個跨度或類似的方式包裝。我正在尋找一個有效的功能來做到這一點。ASP.Net中的搜索關鍵字突出顯示

E.g.

關鍵詞: 「Lorem存有」

結果:

所需的HTML輸出 「含LOREM和存有一些文」: 「Some text containing <span class="hit">lorem</span> and <span class="hit">ipsum</span>

我的結果是不區分大小寫。從Lucene.net

回答

13

這是我決定的。一個擴展功能,我可以調用我的頁面/我的頁面內的相關字符串:

public static string HighlightKeywords(this string input, string keywords) 
{ 
    if (input == string.Empty || keywords == string.Empty) 
    { 
     return input; 
    } 

    string[] sKeywords = keywords.Split(' '); 
    foreach (string sKeyword in sKeywords) 
    { 
     try 
     { 
      input = Regex.Replace(input, sKeyword, string.Format("<span class=\"hit\">{0}</span>", "$0"), RegexOptions.IgnoreCase); 
     } 
     catch 
     { 
      // 
     } 
    } 
    return input; 
} 

任何進一步的建議或意見?

+0

首先,這是怎麼回事的話中承認部分匹配。您的正則僅需要做整個單詞替換。其次,你可以輸入'」「',而不是'Convert.ToChar(」「)' – Richard 2009-10-27 14:52:26

+0

感謝理查德 - 很好的提示字符,我知道必須有一個更好的方式,但它並沒有點擊RE部分匹配,這就是我在後。這種情況下,因爲搜索使用通配符(因此需要使事情更清晰並突出顯示)。 – TimS 2009-10-27 15:32:28

+0

謝謝!這對我很好。 – 2010-04-15 23:58:49

1
+0

看起來不錯,但是我必須使用Lucene.Net來爲我的搜索結果使用Lucene高級功能嗎?我實際上只是使用一個簡單的存儲過程(數據只在一個表中,所以我不想構建和維護單獨的Lucene索引)。 – TimS 2009-10-27 10:59:09

+0

在這裏你可以找到來源https://svn.apache.org/repos/asf/incubator/lucene.net/trunk/C%23/contrib/Highlighter.Net/Highlighter.Net/。可能它會幫助你做出決定 – 2009-10-27 11:08:11

+0

嗯。看起來你只能在Lucene中使用它。 ((但可能是你可以使用一些代碼從這個項目...... – 2009-10-27 11:10:15

1

使用jQuery高亮插件。

對於在服務器端突出顯示

protected override void Render(HtmlTextWriter writer) 
{ 
    StringBuilder html = new StringBuilder(); 
    HtmlTextWriter w = new HtmlTextWriter(new StringWriter(html)); 

    base.Render(w); 

    html.Replace("lorem", "<span class=\"hit\">lorem</span>"); 

    writer.Write(html.ToString()); 
} 

您可以使用正則表達式高級文本替換。

您也可以將上面的代碼寫入HttpModule,以便可以在其他應用程序中使用它。

+0

謝謝永久鏈接 - 在這種情況下,我試圖做到這一點的服務器端,因爲它需要對各種非JavaScript的設備上工作。 – TimS 2009-10-27 10:54:52

0

我在ASP.NET中得到了類似的要求。這裏是我用C#編寫的用於突出顯示關鍵字的解決方案。

Algo使用的是Naive搜索算法。

  • 維護一個散列表來存儲匹配。
  • 在存在關鍵字匹配的字符串上應用標籤。

    區域突出的例程

    /// <summary> 
        /// Higlight the search term. 
        /// </summary> 
        /// <param name="currentString"></param> 
        /// <returns></returns> 
        private string Highlight(string currentString) 
        { 
         try 
         { 
          var termValue = _helperRequest.SearchText; 
          if (!string.IsNullOrEmpty(currentString) && !string.IsNullOrEmpty(termValue)) 
          { 
           currentString = termValue.Trim().Split(Constants.Separator) 
                   .ToList().Where(x => x.Length >1) 
                   .Distinct() 
                   .OrderByDescending(x => x.Length) 
                   .Aggregate(currentString, (current, keyWord) => 
                   TagIndexers(new SearchHelperRequest() { SearchString = current, SearchTerm = keyWord, HightlightCss = _helperRequest.HightlightCss, Comparison = StringComparison.InvariantCultureIgnoreCase, TagIdentifier = GetRandomKey() })); 
          } 
         } 
         catch (Exception ex) 
         { 
          Logger.WriteError(string.Format("Highlight Error : {0}", ex.Message)); 
         } 
         finally 
         { 
          //Replace tags with highlight terms. 
          if (_helperRequest != null) 
          { 
           if (_helperRequest.TagKeyLookup.Keys.Count > 0) 
           { 
            foreach (string tagKey in _helperRequest.TagKeyLookup.Keys) 
            { 
             if (!string.IsNullOrEmpty(currentString)) 
              currentString = currentString.Replace(tagKey, _helperRequest.TagKeyLookup[tagKey]); 
            } 
    
            //clear the key list. 
            _helperRequest.TagKeyLookup.Clear(); 
           } 
          } 
         } 
         return HttpUtility.JavaScriptStringEncode(currentString); 
        } 
        /// <summary> 
        /// Generate a randome key from lookup table. Recurrsive in nature. 
        /// </summary> 
        /// <returns></returns> 
        private string GetRandomKey() 
        { 
         //config your key length 
         var charBuffer = new char[4]; 
         lock (charBuffer) 
         { 
          for (var iCounter = 0; iCounter < charBuffer.Length; iCounter++) 
          { 
           charBuffer[iCounter] = CharacterLookup 
            [new Random().Next(CharacterLookup.Length)]; 
          } 
         } 
         //Recurssion to generate random. 
         return _helperRequest.TagKeyLookup. 
          ContainsKey(new String(charBuffer)) 
          ? GetRandomKey() : new String(charBuffer); 
        } 
        /// <summary> 
        /// Replace the term with identifiers 
        /// </summary> 
        /// <param name="searchRequest"></param> 
        /// <returns></returns> 
        private string TagIndexers(SearchHelperRequest searchRequest) 
        { 
         try 
         { 
          var highlightBulder = new StringBuilder(); 
          string spanValue = string.Empty; 
          if (!string.IsNullOrEmpty(searchRequest.SearchString) && !string.IsNullOrEmpty(searchRequest.SearchTerm)) 
          { 
           int previousIndex = 0; 
           int currentIndex = searchRequest.SearchString.IndexOf(searchRequest.SearchTerm, searchRequest.Comparison); 
           while (currentIndex != -1) 
           { 
            highlightBulder.Append(searchRequest.SearchString.Substring(previousIndex, currentIndex - previousIndex)); 
            spanValue = string.Format(searchRequest.HightlightCss, searchRequest.SearchString.Substring(currentIndex, searchRequest.SearchTerm.Length)); 
            highlightBulder.Append(searchRequest.TagIdentifier); 
            currentIndex += searchRequest.SearchTerm.Length; 
            previousIndex = currentIndex; 
            currentIndex = searchRequest.SearchString.IndexOf(searchRequest.SearchTerm, currentIndex, searchRequest.Comparison); 
           } 
           if (!_helperRequest.TagKeyLookup.ContainsKey(searchRequest.TagIdentifier) && 
            !string.IsNullOrEmpty(spanValue)) 
           { 
            _helperRequest.TagKeyLookup.Add(searchRequest.TagIdentifier, spanValue); 
           } 
           highlightBulder.Append(searchRequest.SearchString.Substring(previousIndex)); 
          } 
          return highlightBulder.ToString(); 
         } 
         catch (Exception ex) 
         { 
          throw ex; 
         } 
        } 
        #endregion 
    private static char[] _characterLookup = null; 
        public char[] CharacterLookup 
        { 
         get 
         { 
          if (_characterLookup == null) 
          { 
           _characterLookup = new char[36]; 
    
           lock (_characterLookup) 
           { 
            int indexer = 0; 
            //build the table. 
            for (char c = '0'; c <= '9'; c++) _characterLookup[indexer++] = c; 
            for (char c = 'A'; c <= 'Z'; c++) _characterLookup[indexer++] = c; 
           } 
          } 
          return _characterLookup; 
         } 
        } 
    

**摘要:

  • 搜尋期限和應用標籤。
  • 將唯一標籤存儲在散列表中。
  • 替換跨度亮點的標籤。**
+1

spanvalue = {0} Maddy 2012-03-30 12:59:07

+0

對我的方法有任何建議??? – Maddy 2012-04-28 12:28:36

0

的擴展,上述問題的答案。 (沒有足夠的口碑給評論)

爲了避免跨度被替換時,搜索標準爲[跨度潘安一],找到的詞替換爲別的東西不是替換回來......不是很有效,雖然...

public string Highlight(string input) 
{ 
    if (input == string.Empty || searchQuery == string.Empty) 
    { 
     return input; 
    } 

    string[] sKeywords = searchQuery.Replace("~",String.Empty).Replace(" "," ").Trim().Split(' '); 
    int totalCount = sKeywords.Length + 1; 
    string[] sHighlights = new string[totalCount]; 
    int count = 0; 

    input = Regex.Replace(input, Regex.Escape(searchQuery.Trim()), string.Format("~{0}~", count), RegexOptions.IgnoreCase); 
    sHighlights[count] = string.Format("<span class=\"highlight\">{0}</span>", searchQuery); 
    foreach (string sKeyword in sKeywords.OrderByDescending(s => s.Length)) 
    { 
     count++; 
     input = Regex.Replace(input, Regex.Escape(sKeyword), string.Format("~{0}~", count), RegexOptions.IgnoreCase); 
     sHighlights[count] = string.Format("<span class=\"highlight\">{0}</span>", sKeyword); 
    } 

    for (int i = totalCount - 1; i >= 0; i--) 
    { 
     input = Regex.Replace(input, "\\~" + i + "\\~", sHighlights[i], RegexOptions.IgnoreCase); 
    } 

    return input; 
} 
相關問題