Copied to clipboard

Flag this post as spam?

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


  • Adriano Fabri 383 posts 1280 karma points
    Oct 16, 2019 @ 14:06
    Adriano Fabri
    0

    How to sort search result with a custom index

    Hi, I need to order search result by a date field (desc).

    This is my custom Examine Index file (with Component, Composer and IndexCreator classes):

    /// <summary>
    /// AF Examine Index Creator
    /// </summary>
    public class AFExamineIndexCreator : LuceneIndexCreator, IUmbracoIndexesCreator
    {
        /// <summary>_profilingLogger</summary>
        private readonly IProfilingLogger _profilingLogger;
        /// <summary>_localizationService</summary>
        private readonly ILocalizationService _localizationService;
        /// <summary>_publicAccessService</summary>
        private readonly IPublicAccessService _publicAccessService;
    
        /// <summary>
        /// AFExamineIndexCreator
        /// </summary>
        /// <param name="profilingLogger"></param>
        /// <param name="localizationService"></param>
        /// <param name="publicAccessService"></param>
        public AFExamineIndexCreator(IProfilingLogger profilingLogger, ILocalizationService localizationService, IPublicAccessService publicAccessService)
        {
            _profilingLogger = profilingLogger;
            _localizationService = localizationService;
            _publicAccessService = publicAccessService;
        }
    
        /// <summary>
        /// Create
        /// </summary>
        /// <returns>IEnumerable(IIndex)</returns>
        public override IEnumerable<IIndex> Create()
        {
            var index = new UmbracoContentIndex("AFExamineRepositoryIndex", // Name of the Indexer
                CreateFileSystemLuceneDirectory("AFExamineRepositoryIndex"), // File System Index
                new FieldDefinitionCollection(
                    new FieldDefinition("date", FieldDefinitionTypes.DateTime), 
                    new FieldDefinition("title", FieldDefinitionTypes.FullText),
                    new FieldDefinition("docCategory", FieldDefinitionTypes.FullText),
                    new FieldDefinition("bodyText", FieldDefinitionTypes.FullText),
                    new FieldDefinition("docFile", FieldDefinitionTypes.FullText)),
                new StandardAnalyzer(Version.LUCENE_30),
                _profilingLogger,
                _localizationService,
                new ContentValueSetValidator(true, includeItemTypes: new string[] { "doc" },  excludeItemTypes: new string[] { "homepage", "docFolder", "ricerca" })
                );
    
            return new[] { index };
        }
    }
    
    /// <summary>
    /// AF Examine Composer
    /// </summary>
    [RuntimeLevel(MinLevel = RuntimeLevel.Run)]
    public class AFExamineComposer : IUserComposer
    {
        /// <summary>
        /// Compose
        /// </summary>
        /// <param name="composition"></param>
        public void Compose(Composition composition)
        {
            composition.Components().Append<AFExamineComponent>();
            composition.RegisterUnique<AFExamineIndexCreator>();
        }
    }
    
    /// <summary>
    /// AF Examine Component
    /// </summary>
    public class AFExamineComponent : IComponent
    {
        /// <summary>_examineManager</summary>
        private readonly IExamineManager _examineManager;
        /// <summary>_afExamineIndexCreator</summary>
        private readonly AFExamineIndexCreator _afExamineIndexCreator;
    
        /// <summary>
        /// AFExamineComponent
        /// </summary>
        /// <param name="examineManager"></param>
        /// <param name="afExamineIndexCreator"></param>
        public AFExamineComponent(IExamineManager examineManager, AFExamineIndexCreator afExamineIndexCreator)
        {
            _examineManager = examineManager;
            _afExamineIndexCreator = afExamineIndexCreator;
        }
    
        /// <summary>
        /// Initialize
        /// </summary>
        public void Initialize()
        {
            // Because the Create method returns a collection of indexes,
            // we have to loop through them.
            foreach (var index in _afExamineIndexCreator.Create())
            {
                _examineManager.AddIndex(index);
            }
        }
    
        /// <summary>
        /// Initialize
        /// </summary>
        public void Terminate() { }
    }
    

    The result view:

    @inherits Umbraco.Web.Mvc.UmbracoViewPage
    @using AFStarterKit.AFBusinessLogic;
    @{
        // Get query param
        string searchTerm = (string.IsNullOrEmpty(Request["query"])) ? string.Empty : Request["query"];
    
        if (!string.IsNullOrEmpty(searchTerm))
        {
            // Perform the search
            if(ExamineManager.Instance.TryGetIndex("AFExamineRepositoryIndex", out var index))
            {
                // Get Searcher
                var searcher = index.GetSearcher();
    
                // Get Results
                var results = searcher.Search(searchTerm, int.MaxValue).OrderByDescending(x => x.Score); // Here I want to orderbydescending by field date
    
                // Show results
                if (!results.Any())
                {
                    <div class="alert alert-info" role="alert">
                        No results with query "<strong><i>@searchTerm</i></strong>"
                    </div>
                }
                else
                {
                    <div class="alert alert-success" role="alert">
                        @{ string resultMessage = (@results.Count() == 1) ? "result"  : "results"; }
    
                        <p>Find <strong><i>@results.Count()</i></strong> @resultMessage with query <strong><i>@searchTerm</i></strong></p>
                    </div>
    
                    <ul>
                        @foreach (var result in results)
                        {
                            if (result.Id != null)
                            {
                                var node = Umbraco.Content(result.Id);
    
                                <li>
                                    <a href="@node.Url">@node.Name</a>
                                </li>
                            }
                        }
                    </ul>
                }
            }
        }
        else
        {
            <div class="alert alert-warning" role="alert">
                Insert at least one word to start search
            </div>
        }
    }
    

    I would to modify (in search view) the code to show results ordered by "date" field (descending)

    Can anyone help me?

  • Erik Eelman 26 posts 100 karma points
    Oct 16, 2019 @ 15:36
    Erik Eelman
    0

    Hi Adriano,

    I believe you can use something like this in your view:

       var criteria = searcher.CreateQuery(IndexTypes.Content, BooleanOperation.Or);
        var examineQuery = criteria.Field("fieldToSearch", searchTerm);
    
        examineQuery.OrderByDescending(new SortableField("date"));
        var results = examineQuery.Execute();
    

    Kind regards, Erik

  • Adriano Fabri 383 posts 1280 karma points
    Oct 17, 2019 @ 09:11
    Adriano Fabri
    0

    Thank you, but I already specified the fields in the "AFExamineIndexCreator" class

    So...in the view I must only launch the search with the command

    var results = searcher.Search(searchTerm, int.MaxValue).OrderByDescending(x => x.Score).OrderBy(new SortableField("date", SortType.Long));
    

    I think that it is heare that I must specify my OrderByDescending by date...but I don't know how.

    I tried this code but it don't function:

    var results = searcher.Search(searchTerm, int.MaxValue).OrderByDescending(x => x.Score)
    var nodes = results.OrderByDescending(new SortableField("date"));
    

    But I receive this error message:

    Compiler Error Message: CS0246: The type or namespace name 'SortableField' could not be found
    
  • Erik Eelman 26 posts 100 karma points
    Oct 17, 2019 @ 09:32
    Erik Eelman
    0

    You are missing a using at the top of your page (below @using AFStarterKit.AFBusinessLogic;)

    @using Examine.Search
    

    And like Ismail said, you don't need the Order by score since it is the default sorting order. Can you try this:

    var results = searcher.Search(searchTerm, int.MaxValue).OrderByDescending(new SortableField("date"));
    
  • Adriano Fabri 383 posts 1280 karma points
    Oct 17, 2019 @ 12:43
    Adriano Fabri
    0

    Found the solution...thank you!

  • Ismail Mayat 4511 posts 10059 karma points MVP 2x admin c-trib
    Oct 16, 2019 @ 16:12
    Ismail Mayat
    1

    Just as fyi I see alot of .OrderByDescending(x => x.Score); there is no need to order by score as that is the default ordering.

  • Adriano Fabri 383 posts 1280 karma points
    Oct 17, 2019 @ 09:11
    Adriano Fabri
    0

    Thank you

  • Adriano Fabri 383 posts 1280 karma points
    Oct 17, 2019 @ 12:41
    Adriano Fabri
    0

    Finally, I found the solution.

    This is the right code tested in my view:

    var results = searcher.Search(searchTerm, int.MaxValue)
                          .OrderByDescending(f => f.Values["date"])
                          .ThenBy(f => f.Values["title"]) 
    

    Many thanks to all for the support

    Adriano

  • Ismail Mayat 4511 posts 10059 karma points MVP 2x admin c-trib
    Oct 17, 2019 @ 13:19
    Ismail Mayat
    0

    Adriano,

    You are sorting in memory using linq, which will work but as you are pulling back all results if you match alot it will start to run slow and if load hits that search results page it will run even slower.

    Ideally you need to get lucene to sort for you.

  • Adriano Fabri 383 posts 1280 karma points
    Oct 17, 2019 @ 14:06
    Adriano Fabri
    0

    ok Ismail.

    Can you give me an example about that?

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies