Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

Dev guideRecipesAPI ReferenceChangelog
Dev guideRecipesUser GuidesNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

Search content

Use Optimizely Graph search with match operators and relevance or semantic ranking to deliver precise and meaningful content results.

Optimizely Graph provides powerful full-text search capabilities using the match operator. You can sort results with traditional relevance-based algorithms or with semantic search powered by AI.

match operator

The match operator searches full-text fields across content stored in Optimizely Graph. It supports multiple ranking modes and can be combined with filters, boosting, and facets.

Ranking types

Relevance

Use relevance ranking for keyword-based searches. It uses traditional algorithms such as TF-IDF and BM25. Relevance ranking is fast, predictable, and works well with exact matches.

Semantic

Use semantic ranking for natural language queries. It uses AI models to understand meaning and context. Semantic ranking understands synonyms, intent, and related concepts, which makes it suitable for user questions and conceptual searches.

When to use each ranking type

Use caseRecommended rankingReason
Product catalog searchRELEVANCEExact matches for product names and SKUs
Knowledge base searchSEMANTICUnderstands user intent and question
News or article searchSEMANTICFinds related topics and concepts
Technical documentationRELEVANCEMatches precise terminology
FAQ searchSEMANTICHandles natural language questions
Category browsingRELEVANCEMatches categories and tags

Tasks

Run a basic text search

Search across all content types by matching a query term.

query SearchContent($query: String!) {
  Content(
    where: { _fulltext: { match: $query } }
    orderBy: { _ranking: RELEVANCE }
  ) {
    items {
      Name
      RelativePath
      _score
    }
    total
  }
}

Variables

{ "query": "sustainability" }

Sort results by relevance

Relevance ranking uses traditional keyword-based algorithms.

query SearchByRelevance($query: String!) {
  ArticlePage(
    where: { _fulltext: { match: $query } }
    orderBy: { _ranking: RELEVANCE }
    limit: 10
  ) {
    items {
      Name
      TeaserText
      RelativePath
      _score
    }
    total
  }
}

Sort results by semantic ranking

Semantic ranking uses AI models to understand meaning and context.

query SearchBySemantic($query: String!) {
  ArticlePage(
    where: { _fulltext: { match: $query } }
    orderBy: { _ranking: SEMANTIC }
    limit: 10
  ) {
    items {
      Name
      TeaserText
      RelativePath
      _score
    }
    total
  }
}

Search across multiple fields

Target specific fields while maintaining relevance scoring.

query MultiFieldSearch($query: String!) {
  ArticlePage(
    where: {
      _or: [
        { Name: { match: $query } },
        { TeaserText: { match: $query } },
        { MainBody: { match: $query } }
      ]
    }
    orderBy: { _ranking: RELEVANCE }
  ) {
    items {
      Name
      TeaserText
      RelativePath
      _score
    }
    total
  }
}

Filter by content type

Combine search with content type filtering.

query SearchArticles($query: String!) {
  Content(
    where: {
      _and: [
        { _fulltext: { match: $query } },
        { _typeName: { eq: "ArticlePage" } }
      ]
    }
    orderBy: { _ranking: SEMANTIC }
    limit: 5
  ) {
    items {
      Name
      RelativePath
      _score
    }
    total
  }
}

Boost specific fields

Increase the relevance of certain fields.

query AdvancedSearch($query: String!) {
  ArticlePage(
    where: {
      _or:[
        { Name: { match: $query, boost: 5 } },
        { TeaserText: { match: $query, boost: 3 } },
        { _fulltext: { match: $query } }
      ]
    }
    orderBy: { _ranking: RELEVANCE }
  ) {
    items {
      Name
      TeaserText
      _score
    }
    total
  }
}

Apply date range filters

Restrict results to recently published content.

query SearchWithFilters($query: String!, $fromDate: DateTime!) {
  ArticlePage(
    where: {
      _and: [
        { _fulltext: { match: $query } },
        { StartPublish: { gte: $fromDate } }
      ]
    }
    orderBy: { _ranking: SEMANTIC }
    limit: 20
  ) {
    items {
      Name
      TeaserText
      RelativePath
      _score
      StartPublish
    }
    total
  }
}

Use faceted search

Retrieve facet counts for filtering.

query FacetedSearch($query: String!) {
  search: Content(
    where: { _fulltext: { match: $query } }
    orderBy: { _ranking: RELEVANCE }
    limit: 10
  ) {
    items {
      Name
      RelativePath
      _score
    }
    total
  }

  typeFacets: Content(
    where: { _fulltext: { match: $query } }
    facet: { _typeName(limit: 10) }
  ) {
    facet {
      _typeName {
        name
        count
      }
    }
  }
}

Paginate search results

Retrieve search results in pages.

query PaginatedSearch($query: String!, $skip: Int = 0, $limit: Int = 10) {
  Content(
    where: { _fulltext: { match: $query } }
    orderBy: { _ranking: SEMANTIC }
    skip: $skip
    limit: $limit
  ) {
    items {
      Name
      RelativePath
      _score
    }
    total
  }
}

References

Using search scores

The _score field indicates the relevance of a search result.

  • Higher scores mean higher relevance.
  • Scores vary depending on the ranking type.
  • You can filter results based on a minimum _score.

Example (React/Next.js):

const { data } = useQuery(SEARCH_QUERY, {
  variables: { query: searchTerm }
});

const relevantResults = data.Content.items.filter(item => item._score > 0.5);

C# implementation

public async Task<SearchResult> SearchContentAsync(string query, SearchType searchType = SearchType.Semantic)
{
    var orderBy = searchType == SearchType.Semantic ? "SEMANTIC" : "RELEVANCE";
    
    var graphQLQuery = $@"
        query SearchContent($query: String!) {{
            Content(
                where: {{ _fulltext: {{ match: $query }} }}
                orderBy: {{ _ranking: {orderBy} }}
                limit: 20
            ) {{
                items {{
                    Name
                    RelativePath
                    _score
                }}
                total
            }}
        }}";

    var request = new GraphQLRequest 
    { 
        Query = graphQLQuery,
        Variables = new { query }
    };

    var response = await _graphQLClient.SendQueryAsync<SearchResponse>(request);
    return response.Data;
}

public enum SearchType
{
    Relevance,
    Semantic
}