Search - JimBobSquarePants/Zoombraco GitHub Wiki

SearchEngine

Zoombraco provides a comprehensive search engine which is capable of multilingual indexing and simple faceting without any additional configuration.

The following languages have specific analysers. These are bound to a large range of cultures:

  • Arabic
  • Brazilian Portuguese
  • Chinese
  • Czech
  • Dutch
  • French
  • German
  • Japanese
  • Korean
  • Russian

All other languages fall back to using the standard analyser.

Searches can either search across all cultures or can be restricted to a culture or selection of cultures.

In this example we are searching for term "socket" against all cultures.

SearchResponse result = SearchEngine.SearchSite("socket");

In this example we are searching for term "Sichern" against the German de culture.

SearchResponse result = SearchEngine.SearchSite("Sichern", new[] { new CultureInfo("de") });

In this example we are searching for term "تأمين" against the Arabic ar-AE culture.

SearchResponse result = SearchEngine.SearchSite("تأمين", new[] { new CultureInfo("ar-AE") });

SearchResponse

A SearchResponse is the result of a search query. The properties of that class are as follows:

  • TotalCount The total count of all search results
  • SearchMatches The collection of SearchMatch all results or the paged portion of the total results should paging be requested.

SearchMatch

A single search match contains the following properties:

  • Id The id of the page returned in the result.
  • HighlightText The highlighted text fragment for this result.
  • Name The name of the page returned in the result.
  • Node The IPublishedContent representing the page returned in the result.
  • Url The relative url of the page returned in the result.
  • UrlAbsolute The absolute url of the page returned in the result.
  • Categories The categories within which a result falls.

Adding Properties to Search

Adding a property to the search results is achieved by usage of specific attributes. UmbracoSearchMergedField, ZoombracoSearchResolver, and UmbracoSearchCategory.

For example if you wanted to add nested content to search within the category "All" we could do so as follows:

[UmbracoSearchCategory(new[] { "All" })]
public class Generic : Page, IHeroPanel, INested
{
    /// <inheritdoc />
    public virtual IEnumerable<Image> HeroImages { get; set; }

    /// <inheritdoc />
    [UmbracoSearchMergedField]
    public virtual string HeroTitle { get; set; }

    /// <inheritdoc />
    public virtual RelatedLink HeroLink { get; set; }

    /// <inheritdoc />
    [UmbracoSearchMergedField]
    [NestedRichTextSearchResolver]
    public virtual IEnumerable<NestedComponent> NestedContent { get; set; }
}

Multiple search resolvers can be added to properties to resolve the values from complex objects. The ZoombracoSearchResolver provides all the properties and methods required to return both single and multilingual property results.

Here's the complete code for the NestedRichTextSearchResolver class. This class could be adapted to serve as a base class for all search resolvers.

/// <summary>
/// Resolves the <see cref="M:NestedRichText.BodyText"/> property for Examine.
/// </summary>
public class NestedRichTextSearchResolverAttribute : ZoombracoSearchResolverAttribute
{
    /// <inheritdoc/>
    public override string ResolveValue()
    {
        // Vorto nested values
        if (this.RawVortoValue != null)
        {
            if (this.RawVortoValue.Values.ContainsKey(this.Culture.Name))
            {
                List<object> nestedValue = JsonConvert.DeserializeObject<List<object>>(this.RawVortoValue.Values[this.Culture.Name].ToString());
                return this.GetNestedContentRichText(nestedValue);
            }
        }

        // Standard nested values
        List<object> rawValue = JsonConvert.DeserializeObject<List<object>>(this.RawValue);
        return this.GetNestedContentRichText(rawValue);
    }

    /// <summary>
    /// Returns the nested content type alias from the given item.
    /// </summary>
    /// <param name="item">The JSON object</param>
    /// <returns>The <see cref="string"/></returns>
    private static string GetContentTypeAliasFromItem(JObject item)
    {
        JToken contentTypeAliasProperty = item["ncContentTypeAlias"];
        return contentTypeAliasProperty?.ToObject<string>();
    }

    /// <summary>
    /// Returns the rich text values from the nested content.
    /// </summary>
    /// <param name="nestedRawValue">The raw value from nested content.</param>
    /// <returns>The <see cref="string"/>.</returns>
    private string GetNestedContentRichText(List<object> nestedRawValue)
    {
        StringBuilder sb = new StringBuilder();
        foreach (object value in nestedRawValue)
        {
            JObject item = (JObject)value;
            string contentTypeAlias = GetContentTypeAliasFromItem(item);
            if (string.IsNullOrEmpty(contentTypeAlias))
            {
                continue;
            }

            if (contentTypeAlias.InvariantEquals(nameof(NestedRichText)))
            {
                JToken contentTypeAliasProperty = item[this.PropertyAlias];
                sb.Append(contentTypeAliasProperty?.ToObject<string>());
            }
        }

        return sb.ToString();
    }
}
⚠️ **GitHub.com Fallback** ⚠️