allBlogsList

Querying and Reading Content Hub Data with Web SDK Client

Intro

A collection of code snippets for Querying and Reading Content Hub Data with Web SDK Client

Introduction (what is this for?)

I wrote a number of custom Azure Functions, which search and read content from Sitecore Content Hub, and I could share some search code snippets as this may be useful to others... I'm using .NET Web Client SDK and LINQ to build queries, which is well documented here, but I thought it may help if I share more complete examples and explain a few gotchas.

Things to know about search with Web SDK

Web Client SDK

Web Client SDK is a core class, which encapsulates and abstracts away some of the idiosyncrasies of interacting with Content Hub REST API directly. Particularly, it helps to simplify authentication and automatically handles Content Hub's throttling behind the scene.

Authentication is done via the OAuth client, which needs to be set up in Content Hub and then configured on the client side.

For more details see Web Client SDK and Authentication

Paging and Iterators

It may not be immediately clear, but Sitecore Content Hub will page the results in the response, so one may be wondering why the number of results to search queries never goes over 50 (default). In order to page through the paged results.

For more details see Iterators in Web SDK

Load Configurations

The load configuration is a request parameter, which defines how much Entity data will be returned in the response. Load configuration defines how entity fields, cultures, and relations are to be returned in the response.

For more details see Entity Load Configurations

Bringing it all together with Code Examples

The following are a few well-commented functions and code snippets for how to use them. I hope some folks find this useful :)

Search and Fully Load a Single Entity Matching the Search Criteria

/// <summary>
/// Search for the ID of the first entity matching the search query (function)
/// </summary>
/// <param name="client">Content Hub Web SDK client</param>
/// <param name="queryFunction"></param>
/// <param name="log">optional logger - ignore if no logging is needed</param>
/// <returns>An ID of first entity matching the search criteria</returns>
public static async Task<IEntity> SearchSingleEntity(IWebMClient client, Func<QueryableEntities<IQueryableEntity>, IQueryable<IQueryableEntity>> queryFunction, IEntityLoadConfiguration loadConfiguration, TraceWriter log = null)
{
    Query query = Query.CreateQuery(queryFunction);
    try
    {
        //Search for the first match for a given query
        var result = (await client.Querying.SingleAsync(query, loadConfiguration));

        if (result != null)
        {
            //Log and return the results
            log?.Info($"Found entitity. ID: {result.Id}", "SearchSingleEntity");
            return result;
        }

        return null;
    }
    catch (Exception ex)
    {
        //Log and re-throw the exception
        log?.Error($"error message: {ex.Message}", ex, "SearchSingleEntity");
        throw ex;
    }
}


How to use

//Initialize CH Web SDK client
var clientInfo = Utils.ExtractClientInfo(req.Headers);
Uri endpoint = new Uri(clientInfo.baseUrl);
OAuthPasswordGrant oauth = new OAuthPasswordGrant
{
    ClientId = clientInfo.clientId,
    ClientSecret = clientInfo.clientSecret,
    UserName = clientInfo.userName,
    Password = clientInfo.password
};

IWebMClient client = MClientFactory.CreateMClient(endpoint, oauth);

IEntity entity = await Utils.SearchSingleEntity(client,
                                                (entities =>
                                                 from e in entities
                                                 where e.DefinitionName == "M.Asset"
                                      			where e.Property("some_property") == "some_value"
                                                 select e),
                                                EntityLoadConfiguration.Full, log);


Search and Fully Load Multiple Entities Matching the Search Criteria

/// <summary>
/// Search and load all entities matching the search query (function)
/// </summary>
/// <param name="client">Content Hub Web SDK client</param>
/// <param name="queryFunction"></param>
/// <param name="log">optional logger - ignore if no logging is needed</param>
/// <returns>List of fully loaded entities matching the search criteria. Warning: be careful - the resultset could grow huge</returns>
public static async Task<IList<IEntity>> SearcEntities(IWebMClient client, Func<QueryableEntities<IQueryableEntity>, IQueryable<IQueryableEntity>> queryFunction, IEntityLoadConfiguration loadConfiguration, TraceWriter log = null)
{
    log?.Info($"Search query function: {queryFunction}");
    //Initialize the query with given search criteria (function)
    Query query = Query.CreateQuery(queryFunction);
    try
    {
        var results = new List<IEntity>();
        //Deal with paging when there are more than 50 results (default page size)
        IEntityIterator iterator = client.Querying.CreateEntityIterator(query, loadConfiguration);
        while (await iterator.MoveNextAsync())
        {
            var entities = iterator.Current.Items;
            if (entities != null && entities.Any())
            {
                results.AddRange(entities);
            }
        }

        if (results != null && results.Any())
        {
            //Log and return the results
            log?.Info($"Found entities. Count: {results.Count}, IDs: {String.Join(",", results.Select(e => e.Id))}", "SearcEntitiesByFieldFalue");
            return results;
        }

        return null;
    }
    catch (Exception ex)
    {
        //Log and re-throw the exception
        log?.Error($"error message: {ex.Message}", ex, "SearcEntities");
        throw;
    }

}
		

How to use

//Initialize CH Web SDK client
var clientInfo = Utils.ExtractClientInfo(req.Headers);
Uri endpoint = new Uri(clientInfo.baseUrl);
OAuthPasswordGrant oauth = new OAuthPasswordGrant
{
    ClientId = clientInfo.clientId,
    ClientSecret = clientInfo.clientSecret,
    UserName = clientInfo.userName,
    Password = clientInfo.password
};

IWebMClient client = MClientFactory.CreateMClient(endpoint, oauth);

//Search for Entities matching the requested field value
IList<IEntity> entities = await Utils.SearcEntities(client,
                                     (entities =>
                                      from e in entities
                                      where e.DefinitionName == "M.Asset"
                                      where e.Property("some_property") ==  "some_value"
                                      select e),
                                     EntityLoadConfiguration.Full, log);


Get IDs of All Entities Matching the Search Criteria

/// <summary>
/// Search for IDs of all entities matching the search query (function)
/// </summary>
/// <param name="client">Content Hub Web SDK client</param>
/// <param name="queryFunction"></param>
/// <param name="log">optional logger - ignore if no logging is needed</param>
/// <returns>List of IDs of entities matching the search criteria</returns>
public static async Task<IList<long>> SearchEntityIDs(IWebMClient client, Func<QueryableEntities<IQueryableEntity>, IQueryable<IQueryableEntity>> queryFunction, TraceWriter log = null)
{
    log?.Info($"Search query function: {queryFunction}");
    //Initialize the query with given search criteria (function)
    Query query = Query.CreateQuery(queryFunction);

    try
    {
        var results = new List<long>();
        //Deal with paging when there are more than 50 results (default page size)
        IIdIterator iterator = client.Querying.CreateEntityIdIterator(query);
        while (await iterator.MoveNextAsync())
        {
            var ids = iterator.Current.Items;
            if (ids != null && ids.Any())
            {
                results.AddRange(ids);
            }
        }

        if (results != null && results.Any())
        {
            //Log and return the results
            log?.Info($"Found entities. Count: {results.Count}, IDs: {String.Join(",", results)}", "SearcEntitiesByFieldFalue");
            return results;
        }

        return null;
    }
    catch (Exception ex)
    {
        //Log and re-throw the exception
        log?.Error($"error message: {ex.Message}", ex, "SearcEntityIDs");
        throw ex;
    }

}

How to use

//Initialize CH Web SDK client
var clientInfo = Utils.ExtractClientInfo(req.Headers);
Uri endpoint = new Uri(clientInfo.baseUrl);
OAuthPasswordGrant oauth = new OAuthPasswordGrant
{
    ClientId = clientInfo.clientId,
    ClientSecret = clientInfo.clientSecret,
    UserName = clientInfo.userName,
    Password = clientInfo.password
};

IWebMClient client = MClientFactory.CreateMClient(endpoint, oauth);

//Search for IDs of all entities matching given definition AND field value
IList<long> entityIDs = await Utils.SearchEntityIDs(client,
                                        (entities =>
                                         from e in entities
                                         where e.DefinitionName == "M.Asset"
                                      	 where e.Property("some_property") ==  "some_value"
                                         select e),
                                        log);

Useful Links