In Part 1, we explored how to build efficient, maintainable asset searches in Optimizely DAM using GraphQL fragments. By modularizing queries, we kept our search logic clean and reusable, simplifying future evolution as your DAM implementation grows.
In Part 2, we’ll dive deeper into managing nested data—like tags, categories, and linked assets—to build richer, more context-aware search experiences. I’ll also show how the fragment-based approach from Part 1 integrates seamlessly with these nested structures, keeping your queries performant and your code maintainable.
In Part 1, we defined GraphQL fragments for different asset types—images, videos, and files—using the FragmentBuilder
pattern:
var imageFragment = new FragmentBuilder<DAMPublicImageAsset>("ImageFields").Fields(a => a.Url, a => a.AltText, a => a.Width, a => a.Height);var videoFragment = new FragmentBuilder<DAMPublicVideoAsset>("VideoFields").Fields(a => a.Url, a => a.AltText);var fileFragment = new FragmentBuilder<DAMPublicFileAsset>("FileFields").Fields(a => a.Url);
These fragments let you define reusable field sets for different asset types, keeping queries clean and consistent.
When working with DAM assets, you often need structured data—like tags, categories, or linked assets—alongside basic asset fields. Fetching this nested data in a single query is efficient and reduces API round-trips.
Here’s an example
public partial class DAMAsset{public string Id { get; set; }public string Title { get; set; }public string MimeType { get; set; }public string Url { get; set; }public string Description { get; set; }// Highlighted usage: Tags nested datapublic IEnumerable<Tags> Tags { get; set; }// Fragments populated dynamicallypublic DAMPublicImageAsset PublicImageAsset { get; set; }public DAMPublicVideoAsset PublicVideoAsset { get; set; }public DAMPublicFileAsset PublicRawFileAsset { get; set; }}public partial class Tags{public string Name { get; set; }public string Guid { get; set; }}
By defining a dedicated Tags
class with properties like Name
and Guid
, you enable strongly-typed querying of nested fields in your GraphQL client. This approach:
Here’s how we combine fragments and nested fields (using Tags
) in the search query:
var damAssetSearch = _graphClient.OperationName("SearchDAMAssets").ForType<DAMAsset>().Fields(x => x.Id,x => x.Title,x => x.MimeType,)// NestedFields: Leverage the Tags class for clean nested data.NestedFields(x => x.Tags,f => f.Name)// Add reusable fragments for different asset types.AddFragments(imageFragment,videoFragment,fileFragment)// Add facets for interactive filtering.Facet(x => x.Tags, f => f.Name).Facet(x => x.MimeType)// Return the total count of matching assets.Total()// Apply global filters.ApplySearchFilters(_damAssetSearchOptions.Value.GlobalFilters)// Support pagination.ApplyPagination(pageNumber, pageSize);
Strongly-Typed Nested Fields
Modeling Tags
as a class with Name
and Guid
creates a clear contract between API responses and C# code—improving type safety, code completion, and reducing runtime errors.
Performance & Maintainability
Using .NestedFields()
and Tags
avoids multiple GraphQL queries or additional API calls for related data. This keeps the codebase clean and the application performant.
Ready for Extensions
If you decide to extend Tags
(e.g., by adding Category
or Color
), your strongly-typed structure is already in place. Just update the Tags
class and adjust your .NestedFields()
call—no major query refactoring needed.
Quick Links
Legal Stuff