protected override async Task <IEnumerable <IDocument> > ExecuteConfigAsync(IDocument input, IExecutionContext context, IMetadata values)
        {
            string applicationId             = values.GetString(ApplicationId) ?? throw new ExecutionException("Invalid application ID");
            string apiKey                    = values.GetString(ApiKey) ?? throw new ExecutionException("Invalid search API key");
            string indexName                 = values.GetString(IndexName) ?? throw new ExecutionException("Invalid search index name");
            IReadOnlyList <string> indexKeys = values.GetList <string>(IndexKeys) ?? throw new ExecutionException("Invalid index keys");

            SearchClient client = new SearchClient(applicationId, apiKey);
            SearchIndex  index  = client.InitIndex(indexName);

            // Get the entire index
            HashSet <JObject>             existing = new HashSet <JObject>(new SearchIndexItemEqualityComparer());
            BrowseIndexResponse <JObject> results;
            int page = 0;

            do
            {
                RequestOptions options = new RequestOptions
                {
                    QueryParameters = new Dictionary <string, string>
                    {
                        { "page", page.ToString() }
                    }
                };
                results = await index.BrowseFromAsync <JObject>(new BrowseIndexQuery(), options, context.CancellationToken);

                existing.AddRange(results.Hits);
                page++;
            }while (page < results.NbPages);

            // Figure out what we need to add and remove
            List <JObject> adds = new List <JObject>();

            foreach (IDocument document in context.Inputs)
            {
                // Create a JObject for the item
                JObject item = new JObject();
                foreach (string indexKey in indexKeys)
                {
                    if (document.ContainsKey(indexKey))
                    {
                        string key   = indexKey.Substring(0, 1).ToLower() + indexKey.Substring(1);
                        string value = document.GetString(indexKey);
                        item.Add(key, value);
                    }
                }

                // Is it already in the index?
                if (!existing.Remove(item))
                {
                    // It wasn't matched, so this is a new one
                    adds.Add(item);
                }
            }

            context.LogInformation($"Search index \"{indexName}\": deleting {existing.Count}, adding {adds.Count}");

            // Update the search index
            if (existing.Count > 0)
            {
                await index.DeleteObjectsAsync(existing.Select(x => x.Property("objectID").Value.ToString()), ct : context.CancellationToken);
            }
            if (adds.Count > 0)
            {
                await index.SaveObjectsAsync(
                    adds,
                    ct : context.CancellationToken,
                    autoGenerateObjectId : true);
            }

            return(context.Inputs);
        }