HomeDev GuideRecipesAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Migrate synonyms

Migrate synonym configurations from Optimizely Search & Navigation to Optimizely Graph.

👍

Early access preview

This content is an early access preview and may change before general availability. Use the thumbs up or down at the end of this article to share feedback and help shape the final release.

Migrate synonym functionality from Optimizely Search & Navigation to Optimizely Graph. This article explains differences in configuration, language handling, query behavior, and operator support, and provides migration approaches for both small and large synonym sets. Use the information to preserve synonym behavior while running Search & Navigation and Graph in parallel during migration.

Synonyms expand search queries with equivalent or related terms. They improve search relevance and reduce zero-result searches when users use different terminology.

Use synonyms when:

  • Users search using different terms for the same concept (for example, bike and bicycle).
  • Brand names have common alternatives (for example, mib and men in black).
  • Technical terms have widely used alternatives (for example, H2O and water).

Learn more about feature comparisons for Synonyms.

Migration options

You can choose to do a manual migration or a programmatic migration.

  • Manual migration – Recommended for small to medium-sized synonym lists. Uses Search & Navigation Admin UI export and manual conversion.
  • Programmatic migration – Recommended for large synonym lists or multiple languages. Automates the entire migration process via code.

Manual migration

1. Export synonyms from Search & Navigation Admin UI

  1. Navigate to Menu > Search & Navigation.
  2. Go to Optimize > Synonyms.
  3. Click "Export".
  4. Save the CSV file.

2. Convert to Graph plain text format

Conversion rules:

  • Bidirectional (Search & Navigation: bidirectional: true) – Use commas
  • One-way (Search & Navigation: bidirectional: false) – Use => arrow

Example conversion:

From Search & Navigation CSV export:

phrase,bidirectional,synonym
"bike",true,"bicycle"
"h2o",true,"water"
"mib",false,"men in black"

To Graph plain text:

bike, bicycle
h2o, water
mib => men in black

3. Upload to Graph using the API

Execute the following steps using Postman or Swagger UI:

  1. Open https://cg.optimizely.com/app/swagger.
  2. Locate the PUT /resources/synonyms endpoint.
  3. Set language_routing and synonym_slot parameters accordingly.
  4. Set body (raw text):
    bike, bicycle
    h2o, water
    mib => men in black
  5. Click Execute.
🚧

Important

For All languages synonyms from Search & Navigation, repeat steps 1-5 for each language your application supports (for example, language_routing=en, then language_routing=sv, then language_routing=fr, and so on.)

Programmatic migration

Recommended for large synonym lists or multiple languages. Automates the entire migration process via code.

1. Fetch synonyms from Search & Navigation

For a specific language:

var languageCode = Language.English.FieldSuffix; // e.g., "en"
var client = SearchClient.Instance;
var allSynonyms = client.Optimizations().Synonyms().List(size: 100, from: 0, [$"language:{languageCode}"]);

For All languages synonyms:

// Note: Language.All.FieldSuffix returns a GUID, not a language code
var allLanguagesCode = Language.All.FieldSuffix;
var client = SearchClient.Instance;
var allLanguagesSynonyms = client.Optimizations().Synonyms().List(size: 100, from: 0, [$"language:{allLanguagesCode}"]);
🚧

Important

If you have All languages synonyms in Optimizely Search & Navigation, you must upload them to each individual language in Graph.

2. Convert to Graph plain text format

var graphSynonyms = new StringBuilder();
foreach (var synonym in allSynonyms.Hits)
{
    var formattedSynonym = synonym.Bidirectional
        ? $"{synonym.Phrase}, {synonym.SynonymPhrase}"
        : $"{synonym.Phrase} => {synonym.SynonymPhrase}";
    graphSynonyms.AppendLine(formattedSynonym);
}
string plainTextContent = graphSynonyms.ToString().TrimEnd();

3. Upload to Graph via HTTP client

📘

Note

This example uses basic authentication. For better security, use HMAC authentication instead. See the HMAC Authentication for implementation details.

// Configure Basic authentication credentials
var appKey = "your-app-key";
var secret = "your-secret";
var credentials = Convert.ToBase64String(
    Encoding.UTF8.GetBytes($"{appKey}:{secret}")
);

// Upload to Graph
var httpClient = new HttpClient();
var graphLanguageCode = "en";
var synonymSlot = "one";
var url = $"https://cg.optimizely.com/resources/synonyms?language_routing={graphLanguageCode}&synonym_slot={synonymSlot}";

var request = new HttpRequestMessage(HttpMethod.Put, url);
request.Headers.Add("Authorization", $"Basic {credentials}");
request.Content = new StringContent(plainTextContent, Encoding.UTF8, "text/plain");

var response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();

Update application queries after migration

After migrating synonyms to Graph, update your application code to use GraphQL queries with synonym support.

Search & Navigation(before):

var results = await SearchClient.Instance
    .Search<IContent>(Language.English)
    .For("bicycle")
    .InField(x => x.Name)
    .UsingSynonyms()
    .Take(10)
    .GetContentResultAsync();

Graph (after) executing GraphQL queries in C#:

using Optimizely.ContentGraph.Core;

public class SearchService
{
    private readonly IClient _graphClient;

    public SearchService(IClient graphClient)
    {
        _graphClient = graphClient;
    }

    public async Task<SearchResult> SearchWithSynonymsAsync(string searchTerm)
    {
        var query = @"
            query SearchContent($searchTerm: String!) {
              Content(
                where: { Name: { contains: $searchTerm, synonyms: [ONE] } }
                locale: en
                limit: 10
              ) {
                total
                items {
                  Name
                  ContentType
                }
              }
            }";

        var variables = new { searchTerm };
        var result = await _graphClient.QueryAsync(query, variables);
        return result;
    }
}

Verify and test

After uploading synonyms, verify the upload was successful and test synonym functionality.

1. Verify upload via REST API

Confirm synonyms were successfully uploaded using the Swagger UI.

  1. Navigate to https://cg.optimizely.com/app/swagger.
  2. Locate the GET /resources/synonyms endpoint.
  3. Set language_routing and synonym_slot parameters accordingly.
  4. Execute the request.
  5. Verify the response contains your synonym list.

2. Test synonyms with Optimizely GraphQL

Test synonym expansion using the GraphiQL URL: https://cg.optimizely.com/app/graphiql?auth=YOUR_SINGLE_KEY.

Test bidirectional synonyms:

# Searching for "bike" should find content with both "bike" and "bicycle"
{
  Content(where: { Name: { contains: "bike", synonyms: [ONE] } }) {
    total
    items {
      Name
    }
  }
}

Test one-way synonyms:

# Searching for "mib" should find "men in black"
{
  Content(where: { _fulltext: { contains: "mib", synonyms: [ONE] } }) {
    total
    items {
      Name
      _fulltext
    }
  }
}

Test using both synonym slots:

{
  Content(where: { Name: { contains: "laptop", synonyms: [ONE, TWO] } }) {
    total
    items {
      Name
    }
  }
}

For more query examples, see Query with synonyms.