Copied to clipboard

Flag this post as spam?

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


  • Frederik T 242 posts 373 karma points
    Oct 07, 2024 @ 07:55
    Frederik T
    0

    Umbraco 13 - Examine searches all sites in a multisite setup

    At my workplace we have inherited an Umbraco website that I need to do some maintenance on. It consists of five websites, each in different languages. They all use the same templates, partial view etc.

    The problem is that it has a global search functionality that utilizes Examine, which searches across all sites, and not just the site you are on currently.

    I have tried, and tried, and tried again to do something about this with the limited knowledge of Examine I have but no solution in sight. One would think that this is a common problem since multi-sites is a cornerstone feature of Umbraco, but after hours of searching I have found nothing concrete or its for very old versions of Umbraco.

    Here is the code that does the searching with my feeble attempt at solving this. This is but one of many, many different methods I have tried. The point is that I supply the method with the ID of the sites home node, and then try to filter it out with the "__path" examine field which contains the home node id:

    public SearchResults SearchContent(string query, string culture = "da", int page = 1, int pageSize = 20, int rootNodeId = -1)
    {
        _variationContextAccessor.VariationContext = new VariationContext(culture);
        string[] SEARCHABLE_FIELDS = new[] { string.Format("nodeName_{0}", culture), string.Format("heading_{0}", culture), string.Format("sections_{0}", culture), string.Format("cSectionPageSections_{0}", culture) };
    
        IEnumerable<string> ids = Array.Empty<string>();
    
        if (!_examineManager.TryGetIndex(Constants.UmbracoIndexes.ExternalIndexName, out IIndex index))
        {
            throw new InvalidOperationException($"No index found by name {Constants.UmbracoIndexes.ExternalIndexName}");
        }
    
        if (string.IsNullOrEmpty(query) || query.Length < 3)
            throw new ArgumentNullException("Query is empty or less than 3");
    
        ISearcher searcher = index.Searcher;
        var criteria = searcher.CreateQuery(IndexTypes.Content, BooleanOperation.And);
        var examineQuery = criteria.GroupedOr(new string[] { "__NodeTypeAlias" }, SEARCHABLE_NODES);
        var terms = query.Split(' ').Where(x => !string.IsNullOrEmpty(x)).Select(x => x.ToSafeAlias(_shortStringHelper).MultipleCharacterWildcard()).ToArray();
        examineQuery.And().GroupedOr(SEARCHABLE_FIELDS, terms);
    
        // filter results by their home node id
        if (rootNodeId != -1)
        {
            examineQuery.And().Field("__Path", $"-1,{rootNodeId},-1");
        }
    
        // Execute the search
        int pageIndex = page - 1;
        QueryOptions queryOptions = new(pageIndex * pageSize, pageSize);
        ISearchResults searchResult = examineQuery.Execute(queryOptions);
        IEnumerable<ISearchResult> pagedResults = searchResult.Skip(pageIndex * pageSize).ToList();
        ids = pagedResults.Select(x => x.Id);
        int totalResults = Convert.ToInt32(searchResult.TotalItemCount);
    
        SearchResults results = new()
        {
            Results = TransformResults(ids),
            CurrentPage = page,
            TotalResults = totalResults,
            TotalPages = (totalResults + pageSize - 1) / pageSize
        };
    
        return results;
    }
    

    I have also tried this:

    if (rootNodeId > 0)
    {
        examineQuery.And().Field("__Path", rootNodeId.ToString());
    }
    

    And this:

    if (rootNodeId > 0)
    {
        string rootNodePath = $",{rootNodeId},";
        examineQuery.And().Field("__Path", rootNodePath.MultipleCharacterWildcard());
    }
    

    And a few others.

    This seems it MIGHT be working, but to be honest I dont exactly understand "why" at this point, and my gut feeling tells me there is a better approach:

    if (rootNodeId > 0)
    {
        examineQuery.And().Field("__Path", ("-1," + rootNodeId.ToString() + ",").MultipleCharacterWildcard());
    }
    
  • Frederik T 242 posts 373 karma points
    Oct 25, 2024 @ 07:40
    Frederik T
    0

    Over two weeks, is there seriously not a single one out there who has used this in a multi site setup?

  • Marc Love (uSkinned.net) 447 posts 1789 karma points
    Oct 25, 2024 @ 09:34
    Marc Love (uSkinned.net)
    0

    Hi Frederik,

    You need to add a searchable field into your Examine index. This essentially takes the path and replaces the commas with spaces.

    The method to update the Examine index varies depending on the version of Umbraco you are using.

    Here is a link to the old documentation on this:

    https://our.umbraco.com/documentation/reference/searching/examine/examine-events#adding-the-path-of-the-node-as-a-searchable-field-into-the-index

    Hope this helps.

    Cheers,

    Marc

  • Marc Love (uSkinned.net) 447 posts 1789 karma points
    Oct 25, 2024 @ 11:47
    Marc Love (uSkinned.net)
    0

    Just noticed you are using Umbraco 13. Here is the documentation for that version:

    https://docs.umbraco.com/umbraco-cms/13.latest-lts/reference/searching/examine/indexing

  • Frederik T 242 posts 373 karma points
    Nov 15, 2024 @ 09:46
    Frederik T
    0

    Yeah now its me who is late to reply, sorry about that. Other tasks got in the way.

    Thanks for the link, I have noticed that before, but I believed it would not be necessary to customize examine because I believed something as simple as searching from a specified home node was built in. It's a cornerstone feature of umbraco so I thought as much, so I guess that everyone else has customized examine to do exactly this? Still feels like it should be baked in.

    I will have to try and go the route suggested in the documentation.

Please Sign in or register to post replies

Write your reply to:

Draft