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
///
/// Search for the ID of the first entity matching the search query (function)
///
/// Content Hub Web SDK client
///
/// optional logger - ignore if no logging is needed
/// An ID of first entity matching the search criteria
public static async Task SearchSingleEntity(IWebMClient client, Func, IQueryable> 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
///
/// Search and load all entities matching the search query (function)
///
/// Content Hub Web SDK client
///
/// optional logger - ignore if no logging is needed
/// List of fully loaded entities matching the search criteria. Warning: be careful - the resultset could grow huge
public static async Task> SearcEntities(IWebMClient client, Func, IQueryable> 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();
//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 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
///
/// Search for IDs of all entities matching the search query (function)
///
/// Content Hub Web SDK client
///
/// optional logger - ignore if no logging is needed
/// List of IDs of entities matching the search criteria
public static async Task> SearchEntityIDs(IWebMClient client, Func, IQueryable> 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();
//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 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);