2009-10-27 2 views
7

Я выводит список результатов поиска для заданной строки ключевых слов, и я хочу, чтобы любые соответствующие ключевые слова в моих результатах поиска были выделены. Каждое слово должно быть завернуто в промежуток или аналогично. Я ищу эффективную функцию для этого.Поиск ключевого слова highlight в ASP.Net

E.g.

Ключевые слова: "Lorem Ipsum"

Результат: "Какой-то текст, содержащий Lorem Ipsum и"

Желаемая вывод HTML: "Some text containing <span class="hit">lorem</span> and <span class="hit">ipsum</span>"

Мои результаты не чувствительны к регистру.

ответ

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

+0

Спасибо Ричарду - хороший совет для char, я знал, что должен быть лучший способ, но он не нажал. RE частичные совпадения, вот что мне нужно в этот случай, поскольку поиск использует подстановочные знаки (отсюда необходимость сделать вещи более ясными с подсветкой). – TimS

+0

спасибо! это сработало для меня. –

1

попытка фломастер из Lucene.Net

http://incubator.apache.org/lucene.net/docs/2.0/Highlighter.Net/Lucene.Net.Highlight.html

Как использовать:

http://davidpodhola.blogspot.com/2008/02/how-to-highlight-phrase-on-results-from.html

EDIT: Пока Lucene.net фломастер не подходит здесь новая ссылка:

http://mhinze.com/archive/search-term-highlighter-httpmodule/

+0

Выглядит хорошо, но должен ли я использовать Lucene.Net для моих результатов поиска, чтобы использовать функции Luclél highhigher? Я на самом деле просто использую простую хранимую процедуру (данные находятся только в одной таблице, поэтому я не хочу создавать и поддерживать отдельный индекс Lucene). – TimS

+0

Здесь вы можете найти источники https://svn.apache.org/repos/asf/incubator/lucene.net/trunk/C%23/contrib/Highlighter.Net/Highlighter.Net/. Возможно, это поможет вам принять решение. –

+0

Хмм. Похоже, вы можете использовать его только с Lucene. ((Но может быть, вы можете использовать какой-то код из этого проекта ... –

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

0

У меня есть аналогичное требование делать в ASP.NET. Вот мое решение написано на C# для выделения ключевого слова.

Алго используется алгоритм наивного поиска.

  • Поддержание хэш-таблицы для хранения матчей.
  • Применить теги в строке, где есть соответствие по ключевому слову.

    область Подчеркивая

    /// <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; 
         } 
        } 
    

** Резюме Подпрограммы:

  • Поиск Термин и применение тегов.
  • Храните уникальные теги в хэш-таблице.
  • Замените метки с Span отблеска. **
+1

spanvalue = {0} Maddy

+0

Любые предложения по моему подходу ??? – Maddy

0

пристройка к выше ответа. (не имеют достаточной репутации, чтобы комментировать)

Чтобы избежать перерыва от замены, когда критерии поиска были [span pan a a], найденное слово было заменено на что-то другое, кроме замены назад ... не очень эффективно, хотя ...

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; 
} 
Смежные вопросы