Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix AzureAI Search issues #16093

Merged
merged 11 commits into from
May 19, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@ public async Task<IActionResult> EditPost(AzureAISettingsViewModel model)
settings.IndexedContentTypes = model.IndexedContentTypes;
settings.Culture = model.Culture ?? string.Empty;

if (string.IsNullOrEmpty(settings.IndexFullName))
{
settings.IndexFullName = _indexManager.GetFullIndexName(settings.IndexName);
}

if (string.IsNullOrEmpty(settings.AnalyzerName))
{
settings.AnalyzerName = AzureAISearchDefaultOptions.DefaultAnalyzer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ public override async Task<IDisplayResult> EditAsync(ContentPartFieldDefinition
return null;
}

return Initialize<AzureAISearchContentIndexSettings>("AzureAISearchContentIndexSettings_Edit", model => contentPartFieldDefinition.GetSettings<AzureAISearchContentIndexSettings>())
.Location("Content:10");
return Initialize<AzureAISearchContentIndexSettings>("AzureAISearchContentIndexSettings_Edit", model =>
{
model.Included = contentPartFieldDefinition.GetSettings<AzureAISearchContentIndexSettings>().Included;
}).Location("Content:10");
}

public override async Task<IDisplayResult> UpdateAsync(ContentPartFieldDefinition contentPartFieldDefinition, UpdatePartFieldEditorContext context)
Expand All @@ -33,11 +35,11 @@ public override async Task<IDisplayResult> UpdateAsync(ContentPartFieldDefinitio
return null;
}

var model = new AzureAISearchContentIndexSettings();
var settings = new AzureAISearchContentIndexSettings();

await context.Updater.TryUpdateModelAsync(model, Prefix);
await context.Updater.TryUpdateModelAsync(settings, Prefix);

context.Builder.WithSettings(model);
context.Builder.WithSettings(settings);

return await EditAsync(contentPartFieldDefinition, context.Updater);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ public override async Task<IDisplayResult> EditAsync(ContentTypePartDefinition c
return null;
}

return Initialize<AzureAISearchContentIndexSettings>("AzureAISearchContentIndexSettings_Edit", model => contentTypePartDefinition.GetSettings<AzureAISearchContentIndexSettings>())
.Location("Content:10");
return Initialize<AzureAISearchContentIndexSettings>("AzureAISearchContentIndexSettings_Edit", model =>
{
model.Included = contentTypePartDefinition.GetSettings<AzureAISearchContentIndexSettings>().Included;
}).Location("Content:10");
}

public override async Task<IDisplayResult> UpdateAsync(ContentTypePartDefinition contentTypePartDefinition, UpdateTypePartEditorContext context)
Expand All @@ -33,11 +35,11 @@ public override async Task<IDisplayResult> UpdateAsync(ContentTypePartDefinition
return null;
}

var model = new AzureAISearchContentIndexSettings();
var settings = new AzureAISearchContentIndexSettings();

await context.Updater.TryUpdateModelAsync(model, Prefix);
await context.Updater.TryUpdateModelAsync(settings, Prefix);

context.Builder.WithSettings(model);
context.Builder.WithSettings(settings);

return await EditAsync(contentTypePartDefinition, context.Updater);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using OrchardCore.Deployment;
using OrchardCore.Search.AzureAI.Deployment.Models;
using OrchardCore.Search.AzureAI.Models;
using OrchardCore.Search.AzureAI.Services;

Expand All @@ -14,33 +14,45 @@ public class AzureAISearchIndexDeploymentSource(AzureAISearchIndexSettingsServic

public async Task ProcessDeploymentStepAsync(DeploymentStep step, DeploymentPlanResult result)
{
if (step is not AzureAISearchIndexDeploymentStep settingsStep)
if (step is not AzureAISearchIndexDeploymentStep indexStep)
{
return;
}

var indexSettings = await _indexSettingsService.GetSettingsAsync();

var data = new JsonArray();
var indicesToAdd = settingsStep.IncludeAll ? indexSettings.Select(x => x.IndexName).ToArray() : settingsStep.IndexNames;
var indicesToAdd = indexStep.IncludeAll
? indexSettings.Select(x => x.IndexName).ToArray()
: indexStep.IndexNames;

foreach (var index in indexSettings)
{
if (indicesToAdd.Contains(index.IndexName))
if (index.IndexName == null || !indicesToAdd.Contains(index.IndexName))
{
var indexSettingsDict = new Dictionary<string, AzureAISearchIndexSettings>
{
{ index.IndexName, index },
};

data.Add(JObject.FromObject(indexSettingsDict));
continue;
}

var indexInfo = GetIndexInfo(index);

data.Add(JObject.FromObject(indexInfo));
}

result.Steps.Add(new JsonObject
{
["name"] = nameof(AzureAISearchIndexSettings),
["name"] = step.Name,
["Indices"] = data,
});
}

private static AzureAISearchIndexInfo GetIndexInfo(AzureAISearchIndexSettings settings)
=> new()
{
IndexName = settings.IndexName,
AnalyzerName = settings.AnalyzerName,
QueryAnalyzerName = settings.QueryAnalyzerName,
IndexedContentTypes = settings.IndexedContentTypes ?? [],
IndexLatest = settings.IndexLatest,
Culture = settings.Culture,
};
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using OrchardCore.Deployment;
using OrchardCore.Search.AzureAI.Recipes;

namespace OrchardCore.Search.AzureAI.Deployment;

public class AzureAISearchIndexDeploymentStep : DeploymentStep
{
public AzureAISearchIndexDeploymentStep()
{
Name = "AzureAISearchIndexSettings";
Name = AzureAISearchIndexSettingsStep.Name;
}

public bool IncludeAll { get; set; } = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace OrchardCore.Search.AzureAI.Deployment.Models;

public class AzureAISearchIndexInfo
{
public string IndexName { get; set; }

public string AnalyzerName { get; set; }

public string QueryAnalyzerName { get; set; }

public bool IndexLatest { get; set; }

public string[] IndexedContentTypes { get; set; }

public string Culture { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;

namespace OrchardCore.Search.AzureAI.Models;

public class AzureAISearchIndexSettings
{
[JsonIgnore]
public string IndexName { get; set; }

[JsonIgnore]
public string IndexFullName { get; set; }

public string AnalyzerName { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using OrchardCore.Recipes.Models;
using OrchardCore.Recipes.Services;
using OrchardCore.Search.AzureAI.Deployment;
using OrchardCore.Search.AzureAI.Deployment.Models;
using OrchardCore.Search.AzureAI.Models;
using OrchardCore.Search.AzureAI.Services;

Expand Down Expand Up @@ -46,23 +47,45 @@ public async Task ExecuteAsync(RecipeExecutionContext context)
return;
}

var indexNames = new List<string>();
var newIndexNames = new List<string>();

foreach (var index in indexes)
{
var indexSettings = index.ToObject<AzureAISearchIndexSettings>();
var indexInfo = index.ToObject<AzureAISearchIndexInfo>();

if (!AzureAISearchIndexNamingHelper.TryGetSafeIndexName(indexSettings.IndexName, out var indexName))
if (string.IsNullOrWhiteSpace(indexInfo.IndexName))
{
_logger.LogError("Invalid index name was provided in the recipe step. IndexName: {indexName}.", indexSettings.IndexName);
_logger.LogError("No index name was provided in the '{Name}' recipe step.", Name);

continue;
}

indexSettings.IndexName = indexName;
if (!AzureAISearchIndexNamingHelper.TryGetSafeIndexName(indexInfo.IndexName, out var indexName))
{
_logger.LogError("Invalid index name was provided in the recipe step. IndexName: {IndexName}.", indexInfo.IndexName);

continue;
}

if (!await _indexManager.ExistsAsync(indexSettings.IndexName))
if (indexInfo.IndexedContentTypes?.Length == 0)
{
_logger.LogError("No {IndexedContentTypes} were provided in the recipe step. IndexName: {IndexName}.", nameof(indexInfo.IndexedContentTypes), indexInfo.IndexName);

continue;
}

if (!await _indexManager.ExistsAsync(indexInfo.IndexName))
{
var indexSettings = new AzureAISearchIndexSettings()
{
IndexName = indexInfo.IndexName,
AnalyzerName = indexInfo.AnalyzerName,
QueryAnalyzerName = indexInfo.QueryAnalyzerName,
IndexedContentTypes = indexInfo.IndexedContentTypes,
IndexLatest = indexInfo.IndexLatest,
Culture = indexInfo.Culture,
};

if (string.IsNullOrWhiteSpace(indexSettings.AnalyzerName))
{
indexSettings.AnalyzerName = AzureAISearchDefaultOptions.DefaultAnalyzer;
Expand All @@ -73,22 +96,14 @@ public async Task ExecuteAsync(RecipeExecutionContext context)
indexSettings.QueryAnalyzerName = indexSettings.AnalyzerName;
}

if (indexSettings.IndexedContentTypes == null || indexSettings.IndexedContentTypes.Length == 0)
{
_logger.LogError("No {fieldName} were provided in the recipe step. IndexName: {indexName}.", nameof(indexSettings.IndexedContentTypes), indexSettings.IndexName);

continue;
}

indexSettings.SetLastTaskId(0);
indexSettings.IndexMappings = await _azureAIIndexDocumentManager.GetMappingsAsync(indexSettings.IndexedContentTypes);
indexSettings.IndexFullName = _indexManager.GetFullIndexName(indexSettings.IndexName);

if (await _indexManager.CreateAsync(indexSettings))
{
await _azureAISearchIndexSettingsService.UpdateAsync(indexSettings);

indexNames.Add(indexSettings.IndexName);
newIndexNames.Add(indexSettings.IndexName);
}
}
}
Expand All @@ -97,7 +112,7 @@ await HttpBackgroundJob.ExecuteAfterEndOfRequestAsync(AzureAISearchIndexRebuildD
{
var searchIndexingService = scope.ServiceProvider.GetService<AzureAISearchIndexingService>();

await searchIndexingService.ProcessContentItemsAsync(indexNames.ToArray());
await searchIndexingService.ProcessContentItemsAsync(newIndexNames.ToArray());
});
}
}
Loading