1. Search

Configuration

The Search API applies a default search configuration to all searches, using default values and filters.

Default Search configuration settings

The default search configuration is retrieved from a setting in M called SearchDefaults. The setting's name is a variable that is passed into the search-related API resources as a parameter called name. When a UI component performs a REST call, it looks up the setting in its configuration and passes it to the Search controller.

An example in Sitecore Content Hub is SearchConfiguration.json, which is in the PortalConfiguration section of the settings.

Warning

The API is configured to only load the related paths that are specified in a query. If you don't specify related path relations in your query, the response won't return any.

The search setting schema has the following properties.

Property

Description

Name

The name of the setting.

Take

The default number of results to return. This is only used if the search request does not include paging. By default, the maximum number of items per page is 50 and the maximum number of pages is 100.

Filters

The filters to apply to each query. If more than one filter is specified, they are evaluated together using AND operators.

Facets

The definitions used as facets. The schema determines how facets are linked to result-entities, for example using taxonomy relations.

Followups

Follow-up facet configuration. If a facet filter is applied for a certain definition, you can also append other facets to the search query.

PropertiesToLoad:

The properties that are included in the results.

relationsToLoad

The relations that are included in the results.

renditionsToLoad

The renditions to include in the results for entities that have renditions.

ResultTypes

The types of entities that are returned as results. Filters are added to the search query to make sure only entities of these types are returned.

SuperFacets

If a definition is flagged as a super facet in the configuration, the search response will contain additional information about that super facet.

Sorting

The default sorting method.

{
    "name": "SearchConfiguration",
    "take": 10,
    "filters": [
        {
            "name": "relations.FinalLifeCycleStatusToAsset.parents",
            "operator": "Equals",
            "valueExpression": "String(\"StatusValue\") == \"Approved\""
        }
    ],
    "facets": [
        {
            "name": "M.Campaign"
        },        
        {
            "name": "M.AssetOriginator",
           "limit": 3,
            "sorting": "Alphabetical",
            "direction": "Ascending"
        }
    ],
    "followups": [        
        {
            "name": "M.AssetType",
            "valueExpression": "string(\"ClassificationName\") == \"Video\"",
            "followupName": "Ms.BitRate"
        }
    ],
    "superfacets": [
        {
            "definition": "M.Brand"
        }
    ],
    "propertiesToLoad": [
        "FileName",
        "Renditions"
    ],
    "resultTypes": [
        "M.Asset"
    ],
    "sorting": [
        {
            "property": "ModifiedOn",
            "direction": "Descending"
        }
    ]
}

Facets

The simplest way to define a facet is to use the definition name. Facets depend on the Content Hub schema (for example, definitions being marked as IsTaxonomyItemDefinition).

There are two types of facets:

  • Normal facets (relations)

  • Field facets (properties)

Normal facet

{
  "name": "M.Campaign"
}

Field facet

{
  "name": "FileExtension",
  "type": 1
}

You can use the limit parameter to limit the number of values returned by the facet. The default value of this parameter is 10.

Note

Setting the limit parameter to 0 causes the facet to return all available values.

Each facet can be given a sorting parameter to determine how the items returned for that facet are ordered on the page. The potential values for this parameter are:

  • Count (default)

  • Alphabetical

  • Field

You can control the sort order of the facet by adding a direction parameter, which must be given a value of Ascending or Descending.

Note

Alphabetical sorting is only useful when all facet values are returned.

Filters

You can define filters using the JSON configuration setting or using the query contributor framework.

Each value expression used in the filter must resolve to a single Id.

This example applies a filter on definition_name == "M.Asset".

{
    "name": "relations.FinalLifeCycleStatusToAsset.parents",
    "operator": "Equals",
    "valueExpression": "String(\"StatusValue\") == \"Approved\""
}

The example above applies a filter on the Id of Lifecycle status approved. (single Id).

If no value expression is used, the name is treated as a definition name and the filter is based on that definition.

{
  "name": "M.Asset"
}

It is also possible to create a filter of filters and choose which operator to apply for those inner filters.

{
  "operator": "OR",
  "filters": [
    {
      "name": "relations.FinalLifeCycleStatusToAsset.parents",
      "operator": "Equals",
      "valueExpression": "String(\"StatusValue\") == \"Created\""
    },
    {
      "name": "relations.FinalLifeCycleStatusToAsset.parents",
      "operator": "Equals",
      "valueExpression": "String(\"StatusValue\") == \"Rejected\""
    }
  ]
}

Default filters using code

You can also apply filters using code.

In this example an OR filter is applied on multiple definition names and a specific one for M.Asset (lifecycle status approved).

The filter looks like this:

(definition = "M.Sku" OR definition = "M.Product" OR definition = "M.Campaign" OR definition = "M.Recipe" OR (definition = M.Asset AND LifeCycleStatus = Approved))

      public class SearchConfigurationQueryContributor : IQueryContributor
    {
        private readonly IQuerying _querying;

        public SearchConfigurationQueryContributor(IQuerying querying)
        {
            this._querying = querying;
        }

        public Base.Search.Filters.FilterBase AddQuery(QueryContext context)
        {
            CompositeFilter filter = new CompositeFilter(FilterCombineMethod.Or);

            var qb = new QueryBuilder();

            //First step is to resolve final lifecycle status = Approved. (we are only gonna show approved stuff in the search.)
            long? approvedId = this._querying.Basic.Entities.SingleId(qb.Definition.Name == Stylelabs.M.Content.Constants.FinalLifeCycleStatusDefinition.DefinitionName &&
                qb.String(Stylelabs.M.Content.Constants.FinalLifeCycleStatusDefinition.StatusValue) == Stylelabs.M.Content.Constants.FinalLifeCycleStatusDefinition.ApprovedStatus);

            if (!approvedId.HasValue)
                throw new InvalidOperationException("Could not resolve approved status.");

            //These are the definitions we will apply a simple filter for (OR between definitions)
            string[] definitionsToDisplay = new string[] { "M.Sku", "M.Product", "M.Campaign", "M.Recipe" };
            foreach(string definition in definitionsToDisplay)
            {
                filter.Add(new FieldFilter<string>(Stylelabs.M.Base.ElasticSearch.Constants.PropertyNames.DefinitionName) { Value = definition });
            }

            //For asset we will only display the approved ones
            var assetFilter = new CompositeFilter(FilterCombineMethod.And);
            assetFilter.Add(new FieldFilter<string>(Stylelabs.M.Base.ElasticSearch.Constants.PropertyNames.DefinitionName) { Value = "M.Asset" });
            assetFilter.Add(new FieldFilter<long>("relations.FinalLifeCycleStatusToAsset.parents") { Value = approvedId.Value });
            filter.Add(assetFilter);

            return filter;
        }
    }

This querycontributer allows you to directly influence the filters being applied on the query. These filters will not be visible on the client-side. (for example, querystring, querybuilder, and so on)

Once the querycontributer class is ready the next step is to register it in your project's ApplicationModule

        public override void OnConfiguration(IContainer container)
        {
            base.OnConfiguration(container);

            IQueryConfiguration queryConfiguration = container.Resolve<IQueryConfiguration>();
            queryConfiguration.QueryContributorRegistry.Add<SearchConfigurationQueryContributor>("SearchConfiguration");
        }

You can combine multiple query contributors together with the filters from configuration. A query contributor is always tied to the name of the SearchConfiguration it should append the filters for.

If you have suggestions for improving this article, let us know!