Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Andrew Waegel 126 posts 126 karma points
    Oct 14, 2010 @ 17:49
    Andrew Waegel
    0

    Umbraco Examine Search Results Highlighting

    Has anyone been able to add search result excerpting and highlighting to Umbraco Examine results, like described here? I will give it a try but any input from you lucene wizards out there would be great.

    Thanks,
    - Andrew

     

     

  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    Oct 14, 2010 @ 18:15
    Ismail Mayat
    5

    Andrew,

    Here is how i did it. Download highlighter.net its in contrib dir of lucene.net source and build it to give you the dll. Add reference to it in your search results project. Create class like

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Text;
    using System.Web;
    using System.Web.UI;
    using Examine;
    using Lucene.Net.Analysis;
    using Lucene.Net.Analysis.Standard;
    using Lucene.Net.Highlight;
    using Lucene.Net.QueryParsers;
    using Lucene.Net.Search;
    using umbraco.cms.businesslogic.media;
    using umbraco.presentation.nodeFactory;
    
    namespace Umbraco_Site_Extensions.automation
    {
        public static class ExtensionMethods
        {
    
            private const string SearchDirectory = "ExamineIndexes";
    
    
    
            /// <summary>
            /// 
            /// </summary>
            /// <param name="IndexField"></param>
            /// <param name="LuceneIndex"></param>
            /// <param name="searchQuery"></param>
            /// <returns></returns>
            public static string GetHighlight(string IndexField,string LuceneIndex,string searchQuery,string highlightField)
            {
                string hightlightText = string.Empty;
    
                var formatter = new SimpleHTMLFormatter("<span class=\"umbSearchHighlight\">", "</span>");
    
                var highlighter = new Highlighter(formatter, FragmentScorer(searchQuery, highlightField, LuceneIndex));
                var tokenStream = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29).TokenStream(highlightField, new StringReader(IndexField));
    
                string tmp = highlighter.GetBestFragments(tokenStream, IndexField, 3,"...");
                if (tmp.Length > 0)
                    hightlightText = tmp +"...";
    
                return hightlightText;
            }
    
            private static QueryScorer FragmentScorer(string searchQuery, string highlightField, string Collection)
            {
                return new QueryScorer(GetLuceneQueryObject(searchQuery, highlightField).Rewrite(GetIndexSearcher(Collection).GetIndexReader()));
            }
    
            private static Query GetLuceneQueryObject(string q,string field)
            {
    
                var qt = new QueryParser(field, new StandardAnalyzer((Lucene.Net.Util.Version.LUCENE_29)));
                return qt.Parse(q);
    
            }
    
            private static  IndexSearcher GetIndexSearcher(string collectionName)
            {
                string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_data", SearchDirectory,
                                           collectionName,"Index");
                return new IndexSearcher(path,true);
            }
    
        }
    }

    In your repeater have call like 

    <%#GetSearchResultHighlight(Container)%>

     

    And the method in your ascx code behind:

    protected const string GeneratedQuery = "+(+bodyText:{0}) +__IndexType:content";        
            protected string GetSearchResultHighlight(RepeaterItem rptItem)
            {
    
                string searchHiglight = string.Empty;
                var sr = (SearchResult)rptItem.DataItem;
    
                if (sr.Fields.ContainsKey("bodyText"))
                {
                    searchHiglight = ExtensionMethods.GetHighlight(sr.Fields["bodyText"], LuceneIndex,
                                                                   string.Format(GeneratedQuery,
                                                                                 Request.QueryString["search"]),"bodyText");
                }
    
                return searchHiglight;
            }

    Regards

    Ismail

  • Andrew Waegel 126 posts 126 karma points
    Oct 14, 2010 @ 18:19
    Andrew Waegel
    0

    Amazing response, thanks. I'll give this a try.

  • Andrew Waegel 126 posts 126 karma points
    Oct 14, 2010 @ 23:52
    Andrew Waegel
    0

    I'll be darned, it worked. High five.

  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    Oct 18, 2010 @ 10:08
    Ismail Mayat
    1

    Andrew,

    One thing I have just noticed with this is i have on my project made the searching wildcard search which all works however the highlight stops working. Very strange as I have used wildcard search and syntax highlight in the past although it was with older version of lucene.  Going to dig around and little and see if i can get to the bottom of it.

    Regards

    Ismail

  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    Oct 18, 2010 @ 12:27
    Ismail Mayat
    2

    Andrew,

    Quick update if you are doing wild card searches then the code needs to change slightly,

     protected const string GeneratedQuery = "+bodyText:{0}*";

    and

            private static Query GetLuceneQueryObject(string q,string field)
            {
    
                var qt = new QueryParser(field, new StandardAnalyzer((Lucene.Net.Util.Version.LUCENE_29)));
                qt.SetMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);
                return qt.Parse(q);
    
            }

    the main change is the setmultitermrewritemethod if you dont have this then for wildcard queries it wont highlight.

    Regards

    Ismail

  • Henrik Madsen 9 posts 29 karma points
    Jan 19, 2011 @ 12:49
    Henrik Madsen
    0

    Hey.. I tryed to use the example, but I can't get the repeater to call the GetSearchResultHighlight method? Any suggestions to what I'm doing wrong? The only thing I have changed in the example is the LUCENEINDEX.

  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    Jan 19, 2011 @ 13:06
    Ismail Mayat
    1

    Henrik,

    I take it you are getting some search results? Also what happens when you step through after adding break point on the method does it get called?

    Regards

    Ismail

  • Henrik Madsen 9 posts 29 karma points
    Jan 19, 2011 @ 13:38
    Henrik Madsen
    0

    Thanks for your time. I got it to work now, made a stupid mistake :(

  • d Thomas 13 posts 33 karma points
    Mar 25, 2013 @ 18:06
    d Thomas
    0

    @ Ismail, 

     

    I have  search results with examineUmbraco pdf, but the razor script does not render the link to the files. 

    can you help? 

    here is my razor: 

    Thanks.

    @using Examine
    @using Examine.SearchCriteria
    @using UmbracoExamine
    @using UmbracoExamine.PDF
    @using umbraco.MacroEngines
    @using System.Xml.Linq
    @using umbraco.presentation.nodeFactory
    @using umbraco.cms
    @using umbraco.cms.businesslogic.media;
    @inherits umbraco.MacroEngines.DynamicNodeContext

    @{
          var searchString = Request["searchstring"];
          if (!String.IsNullOrEmpty(searchString))
      {          
        var searchResults = ExamineManager.Instance.SearchProviderCollection["PDFSearcher"].Search(searchString, true);
        foreach (var c in searchResults)
        {    
        <div>
            
    <p><a href="http://localhost:22841/Media/@c.Fields[@"__NodeId"]">@c.Fields[@"__NodeId"]</a></p>
             
            
        

            
            @if(c.Fields.Keys.Contains("FileTextContent"))
            {
              var bodyText = c.Fields["FileTextContent"];
              <p>@Html.Raw(bodyText.Substring(0,100))</p>
            }
          </div>
              
        }
       
      }

    }

  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    Mar 25, 2013 @ 18:16
    Ismail Mayat
    0

    The node id is not the media folder id so it wont work.  You need to get the media item using node id then get url I have an extension method for it

            /// <summary>
            /// returns result url depending on type
            /// </summary>
            /// <param name="s">object searchresult</param>
            /// <returns>full url of object</returns>
            public static string FullUrl(this SearchResult s)
            {
                string url = umbraco.library.NiceUrl(s.Id);
                if(url==string.Empty)
                {
                    var m=new Media(s.Id);
                    url = m.getProperty("umbracoFile").Value.ToString();
                }
    
                return url;
    
            }

     

    Regards

     

    Ismail

  • d Thomas 13 posts 33 karma points
    Mar 26, 2013 @ 12:45
    d Thomas
    0

    @ Ismail

     

    Thanks for this. 

    I have not used extension methods in umbraco before. Do I need to place this code in App_Code and call the method in razor script? 

    Could you offer a bit of guidance on extension methods in Umbraco? 

    I am using umbraco 4.11 and the examples on extension methods that I have  found out are not working for my umbraco version. 

    Thanks 

    D

  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    Mar 26, 2013 @ 13:19
    Ismail Mayat
    0

    take a look at http://msdn.microsoft.com/en-gb/library/vstudio/bb383977.aspx

    you can put in app_code or your own dll

  • Pradeep Ippa 1 post 21 karma points
    Apr 06, 2013 @ 00:53
    Pradeep Ippa
    0

    What text needs to be passed for the parameter LuceneIndex? Is it the IndexSet name that I have in my ExamineIndex.Config?

    ExtensionMethods.GetHighlight(sr.Fields["bodyText"],LuceneIndex,
                                                                   
    string.Format(GeneratedQuery,
                                                                                 
    Request.QueryString["search"]),"bodyText");
  • Umair Hafeez Mughal 5 posts 25 karma points
    Apr 29, 2013 @ 15:31
    Umair Hafeez Mughal
    0

    Dear Ismail, Thank you so much for the great article.

    I am a newbee to Examine. I have implemented the search and got the highlighted text by using your code. But how can I find inside words? Like if I search for "is", my search should also return all the words which contain "is" at any position.

    Any help would be appreciated.

  • Ismail Mayat 4511 posts 10092 karma points MVP 2x admin c-trib
    Apr 29, 2013 @ 16:31
    Ismail Mayat
    0

    Umair,

    I am assuming you are referring to the post above by Pradeep? If so then LuceneIndex parameter is the index you are looking at.  To get the generated query you do criteria.ToString() see http://thecogworks.co.uk/blog/posts/2012/november/examiness-hints-and-tips-from-the-trenches-part-1/

    Regards

    Ismail

  • Umair Hafeez Mughal 5 posts 25 karma points
    Apr 29, 2013 @ 16:36
    Umair Hafeez Mughal
    0

    Dear Ismail, I got it working. Thanks. I have updated my question. Please help me in that too.

Please Sign in or register to post replies

Write your reply to:

Draft