Copied to clipboard

Flag this post as spam?

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


  • Mike Chambers 635 posts 1252 karma points c-trib
    Jan 08, 2018 @ 12:11
    Mike Chambers
    0

    Slow examine queries on azure, and odd examine results corrected by index rebuild

    Our site (7.7.7) is currently ~200 pages with dummy content so very small

    We have implemented a typeahead search using examine index via an umbracoapicontroller.... locally this runs fine, moving to azure we get a pregnant pause.

    All the azure specific config settings are applied

    <add name="ExternalIndexer" type="UmbracoExamine.UmbracoContentIndexer, UmbracoExamine" directoryFactory="Examine.LuceneEngine.Directories.SyncTempEnvDirectoryFactory,Examine" />
    <add name="ExternalSearcher" type="UmbracoExamine.UmbracoExamineSearcher, UmbracoExamine" directoryFactory="Examine.LuceneEngine.Directories.SyncTempEnvDirectoryFactory,Examine" />
    

    the examine query is like this..

    using System;
    using System.Collections.Generic;
    using Umbraco.Web.Mvc;
    using System.Web.Mvc;
    using Examine;
    using UmbracoExamine;
    using Examine.LuceneEngine.SearchCriteria;
    using Examine.SearchCriteria;
    using Umbraco.Web.WebApi;
    using SYP.Umbraco.Models;
    using System.Text.RegularExpressions;
    
    namespace SYP.Umbraco
    {
        /// <summary>
        /// Summary description for Search
        /// </summary>
        public class SearchController : UmbracoApiController
        {
            public SearchController()
            {
    
            }
    
            public Results GetCategorised(string terms, bool full = false, int limit = 0)
            {
                IList<Result> notCategorisedResults = GetResults(terms, full, limit);
    
                Results results = new Results
                {
                    News = new List<Result>(),
                    General = new List<Result>()
                };
    
                foreach (var item in notCategorisedResults)
                {
                    switch (item.Type)
                    {
                        case "faqsPage":
                            results.Faqs.Add(item);
                            break;
                        case "newsPage":
                            results.News.Add(item);
                            break;
                        default:
                            results.General.Add(item);
                            break;
                    }
                }
    
                return results;
            }
    
            public IList<Result> GetResults(string terms, bool full = false, int limit = 0)
            {
                IList<Result> results = new List<Result>();
    
                if (!string.IsNullOrEmpty(terms))
                {
                    // the default provider is the ExternalSearcher
                    var searchProvider = ExamineManager.Instance.DefaultSearchProvider;
                    // limit to content and default is or
                    var criteria = searchProvider.CreateSearchCriteria(IndexTypes.Content, BooleanOperation.Or);
                    // set up a filter to query the index
                    Examine.SearchCriteria.IBooleanOperation filter = null;
                    // exact phrase match - case sensitive (this does check for term in each of the fields)
                    filter = criteria.GroupedOr(new[] { "gridContent", "nodeName", "searchableContentTags" }, terms.Boost(8));
                    // split on words and allow wildcard plurals etc
                    foreach (var t in terms.Split(' ')) { if (t.Length > 2) { filter.Or().GroupedOr(new[] { "gridContent", "nodeName", "searchableContentTags" }, (t.MultipleCharacterWildcard())); } }
                    // split on words fuzy extends
                    foreach (var t in terms.Split(' ')) { if (t.Length > 2) { filter.Or().GroupedOr(new[] { "gridContent", "nodeName", "searchableContentTags" }, t.Fuzzy(0.5f)); } }
    
    
    
                    // exclude by HideFromSearch
                    filter.Not().GroupedAnd(new[] { "hideFromSearch" }, "1");
    
                    // get our results
                    ISearchResults SearchResults;
                    if (limit > 0)
                    {
                        SearchResults = searchProvider.Search(filter.Compile(), limit);
                    }
                    else
                    {
                        SearchResults = searchProvider.Search(filter.Compile());
                    }
    
                    foreach (SearchResult sr in SearchResults)
                    {
                        Result result = new Result
                        {
                            Id = sr.Id,
                            Type = sr.Fields["nodeTypeAlias"]
                        };
                        try
                        {
                            var umbNode = Umbraco.TypedContent(sr.Id);
                            // fudge for pages that are only displayed dynamically on a list page say (but not newsItems)
                            // include but direct to parent
                            if (sr.Fields["hideInNavigation"] == "1" && umbNode.Parent.DocumentTypeAlias == "list" && sr.Fields["nodeTypeAlias"] != "newsPage")
                            {
                                result.Url = umbNode.Parent.Url;//sr.Fields["urlName"];
                                                                // incase the parent is already included make name unique in search results
                                                                // could even direct to there with #anchor?
                                result.Name = String.Format("{0} ({1})", umbNode.Parent.Name, sr.Fields["nodeName"]);
                            }
                            else
                            {
                                result.Url = umbNode.Url;//sr.Fields["urlName"];
                                result.Name = sr.Fields["nodeName"];
                            }
                        }
                        catch { }
    
    
                        if (full)
                        {
                            try
                            {
                                result.Tags = sr.Fields["searchableContentTags"].ToString();
                            }
                            catch
                            {
    
                            }
                            try
                            {
    
                                //ExtResult extResult = (ExtResult)result;
                                result.Score = (int)Math.Min(sr.Score * 100, 100);
                                try
                                {
                                    var gridContent = sr.Fields["gridContent"];
                                    // Logger.Info(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, System.Text.RegularExpressions.Regex.Replace(gridContent, @"\n+", ""));
    
                                    if (System.Text.RegularExpressions.Regex.Replace(gridContent, @"\n+", "") != @"{  ""name"": ""1 column layout"",  ""sections"": [    {      ""grid"": 12,      ""rows"": []    }  ]}")
                                    {
                                        result.Text = gridContent.Replace("\r", " ").Replace("\n", " ").Trim();
                                        //result.Text = result.Text.Substring(0, Math.Min(result.Text.Length, 200));
    
                                        // if we have a match return words around it.
                                        Regex regex = new Regex(String.Format(@"(?:\w+\W+){{0,15}}{0}.*?(?:\w+\W+){{1,15}}", terms), RegexOptions.IgnoreCase);
                                        Regex regexFromStart = new Regex(@"^.*?(?:\w+\W+){0,20}");
                                        Match match = regex.Match(result.Text);
                                        if (match.Success)
                                        {
                                            result.Text = match.Value;
                                        }
                                        else
                                        {
                                            Match matchStart = regexFromStart.Match(result.Text);
                                            if (matchStart.Success)
                                            {
                                                result.Text = matchStart.Value;
                                            }
                                        }
                                    }
                                }
                                catch { }
                                if (!String.IsNullOrWhiteSpace(result.Url))
                                {
                                    results.Add(result);
                                }
                            }
                            catch (Exception e)
                            {
                                Result resulte = new Result()
                                {
                                    Id = 0,
                                    Text = e.Message,
                                    Name = terms
                                };
                                results.Add(resulte);
                            }
                        }
                        else
                        {
                            if (!String.IsNullOrWhiteSpace(result.Url))
                            {
                                results.Add(result);
                            }
                        }
    
                    }
    
                    if (System.Web.HttpContext.Current.IsDebuggingEnabled)
                    {
                        // reveal the lucene raw query for debugging
                        string stringToParse = criteria.ToString();
                        int indexOfPropertyValue = stringToParse.IndexOf("LuceneQuery:") + 12;
                        string rawQuery = stringToParse.Substring(indexOfPropertyValue).TrimEnd('}');
                        Result result1 = new Result()
                        {
                            Id = 0,
                            Text = rawQuery,
                            Name = terms
                        };
                        results.Add(result1);
                    }
                }
                else
                {
                    //return Json("Search term not found " + terms);
                }
    
                return results;
    
            }
        }
    }
    

    and the SearchViewModel

    using System.ComponentModel.DataAnnotations;
    using System.Runtime.Serialization;
    using System.Xml;
    using Newtonsoft.Json;
    using System.Collections.Generic;
    
    namespace SYP.Umbraco.Models
    {
        /// <summary>
        /// Summary description for SearchFormViewModel
        /// </summary>
        public class SearchViewModel
        {
            [Required(ErrorMessage = "!")]
            public string Query { get; set; }
    
            public SearchViewModel()
            {
                //
                // TODO: Add constructor logic here
                //
            }
        }
    
        [DataContract]
        public class Results
        {
            [DataMember (Name = "news")]
            public IList<Result> News { get; set; }
    
            [DataMember(Name = "general")]
            public IList<Result> General { get; set; }
    
            [DataMember(Name = "faqs")]
            public IList<Result> Faqs { get; set; }
    
        }
    
        [DataContract]
        public class Result
        {        
    
            [DataMember (Name="id")]
            public int Id { get; set; }
    
            [DataMember(Name = "url")]
            public string Url { get; set; }
    
            [DataMember(Name = "name")]
            public string Name { get; set; }
    
            [DataMember(Name = "tags")]        
            public string Tags { get; set; }
    
            [DataMember(Name="text")]//, EmitDefaultValue = false)]
            public string Text { get; set; }
    
            [DataMember(Name="score")]//, EmitDefaultValue = false)]
            public int Score { get; set; }
    
            public string Type { get; set; }
    
            [OnDeserializing]
            private void OnDeserializing(StreamingContext context)
            {
                SetDefaults();
            }
    
            public Result()
            {
                SetDefaults();
            }
    
            private void SetDefaults()
            {
                // set the string defaults rather than returning a null
                Text = string.Empty;
                Tags = string.Empty;
            }
    
        }   
    }
    

    Testing the raw query with Luke, it doesn't appear to be the query...

    Also occasionally we are finding that the umbraco native backend search stops returning results, and the search query returns json content... a rebuild of the internal and external indexes via the developer dashboard resolves that....

    Anyone have any ideas?

Please Sign in or register to post replies

Write your reply to:

Draft