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

Cleanup Search Services #14928

Merged
merged 5 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using System.Threading.Tasks;
using Cysharp.Text;
using OrchardCore.ContentManagement;
Expand All @@ -7,14 +6,9 @@

namespace OrchardCore.Contents.Indexing
{
public class FullTextContentIndexHandler : IContentItemIndexHandler
public class FullTextContentIndexHandler(IContentManager contentManager) : IContentItemIndexHandler
{
private readonly IContentManager _contentManager;

public FullTextContentIndexHandler(IContentManager contentManager)
{
_contentManager = contentManager;
}
private readonly IContentManager _contentManager = contentManager;

public async Task BuildIndexAsync(BuildIndexContext context)
{
Expand All @@ -24,16 +18,17 @@ public async Task BuildIndexAsync(BuildIndexContext context)

foreach (var segment in result.Segments)
{
stringBuilder.Append(segment + " ");
stringBuilder.AppendLine(segment);
MikeAlhayek marked this conversation as resolved.
Show resolved Hide resolved
}

if (!string.IsNullOrEmpty(stringBuilder.ToString()))
var value = stringBuilder.ToString();

if (string.IsNullOrEmpty(value))
{
context.DocumentIndex.Set(
IndexingConstants.FullTextKey,
stringBuilder.ToString(),
DocumentIndexOptions.Sanitize);
return;
}

context.DocumentIndex.Set(IndexingConstants.FullTextKey, value, DocumentIndexOptions.Sanitize);
}
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,11 @@ public class ElasticsearchIndexPermissionHelper

private static readonly Permission _indexPermissionTemplate = new("QueryElasticsearch{0}Index", "Query Elasticsearch {0} Index", new[] { ManageElasticIndexes });

private static readonly Dictionary<string, Permission> _permissions = new();
private static readonly Dictionary<string, Permission> _permissions = [];

public static Permission GetElasticIndexPermission(string indexName)
{
if (string.IsNullOrEmpty(indexName))
{
throw new ArgumentException($"{nameof(indexName)} cannot be null or empty");
}
ArgumentException.ThrowIfNullOrEmpty(indexName, nameof(indexName));

if (!_permissions.TryGetValue(indexName, out var permission))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using OrchardCore.Entities;
using OrchardCore.Search.Abstractions;
using OrchardCore.Search.Elasticsearch;
using OrchardCore.Search.Elasticsearch.Core.Models;
Expand All @@ -12,18 +11,13 @@

namespace OrchardCore.Search.Lucene.Handler;

public class ElasticsearchAuthorizationHandler : AuthorizationHandler<PermissionRequirement>
public class ElasticsearchAuthorizationHandler(IServiceProvider serviceProvider) : AuthorizationHandler<PermissionRequirement>
{
private readonly IServiceProvider _serviceProvider;
private readonly IServiceProvider _serviceProvider = serviceProvider;

private IAuthorizationService _authorizationService;
private ISiteService _siteService;

public ElasticsearchAuthorizationHandler(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}

protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
{
if (context.HasSucceeded)
Expand All @@ -37,9 +31,7 @@ protected override async Task HandleRequirementAsync(AuthorizationHandlerContext
return;
}

var service = _serviceProvider.GetService<ElasticsearchService>();

if (service == null || service.Name != parameters.ServiceName)
if (ElasticsearchService.Key != parameters.ServiceName)
{
// Only validate if Elasticsearch is requested.
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace OrchardCore.Search.Elasticsearch.Services;

public class ElasticsearchService : ISearchService
{
public const string Key = "Elasticsearch";

private readonly ISiteService _siteService;
private readonly ElasticIndexManager _elasticIndexManager;
private readonly ElasticIndexSettingsService _elasticIndexSettingsService;
Expand Down Expand Up @@ -47,15 +49,18 @@ ILogger<ElasticsearchService> logger
_logger = logger;
}

public string Name => "Elasticsearch";
public string Name => Key;

public async Task<SearchResult> SearchAsync(string indexName, string term, int start, int pageSize)
{
var index = !string.IsNullOrWhiteSpace(indexName) ? indexName.Trim() : await DefaultIndexAsync();
var siteSettings = await _siteService.GetSiteSettingsAsync();
var searchSettings = siteSettings.As<ElasticSettings>();

var index = !string.IsNullOrWhiteSpace(indexName) ? indexName.Trim() : searchSettings.SearchIndex;

var result = new SearchResult();

if (index == null || !await _elasticIndexManager.Exists(index))
if (index == null || !await _elasticIndexManager.ExistsAsync(index))
{
_logger.LogWarning("Elasticsearch: Couldn't execute search. The search index doesn't exist.");

Expand All @@ -65,12 +70,9 @@ public async Task<SearchResult> SearchAsync(string indexName, string term, int s
var elasticIndexSettings = await _elasticIndexSettingsService.GetSettingsAsync(index);
result.Latest = elasticIndexSettings.IndexLatest;

var siteSettings = await _siteService.GetSiteSettingsAsync();
var searchSettings = siteSettings.As<ElasticSettings>();

if (searchSettings.DefaultSearchFields == null || searchSettings.DefaultSearchFields.Length == 0)
{
_logger.LogWarning("Elasticsearch: Couldn't execute search. No serach provider settings was defined.");
_logger.LogWarning("Elasticsearch: Couldn't execute search. No search provider settings was defined.");

return result;
}
Expand Down Expand Up @@ -125,11 +127,4 @@ public async Task<SearchResult> SearchAsync(string indexName, string term, int s

return result;
}

private async Task<string> DefaultIndexAsync()
{
var siteSettings = await _siteService.GetSiteSettingsAsync();

return siteSettings.As<ElasticSettings>().SearchIndex;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,6 @@ public override void ConfigureServices(IServiceCollection services)
services.AddScoped<IDisplayDriver<Query>, ElasticQueryDisplayDriver>();
services.AddScoped<IContentTypePartDefinitionDisplayDriver, ContentTypePartIndexSettingsDisplayDriver>();
services.AddScoped<IContentPartFieldDefinitionDisplayDriver, ContentPartFieldIndexSettingsDisplayDriver>();
services.AddScoped<ElasticsearchService>();
services.AddScoped<ISearchService>(sp => sp.GetRequiredService<ElasticsearchService>());
services.AddScoped<IAuthorizationHandler, ElasticsearchAuthorizationHandler>();
}

Expand Down Expand Up @@ -259,6 +257,15 @@ private static IConnectionPool GetConnectionPool(ElasticConnectionOptions elasti
}
}

[RequireFeatures("OrchardCore.Search")]
public class SearchStartup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddScoped<ISearchService, ElasticsearchService>();
}
}

[RequireFeatures("OrchardCore.Deployment")]
public class DeploymentStartup : StartupBase
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
@using OrchardCore.Contents.Indexing
@using OrchardCore.Search.Elasticsearch.Core.Models

@model ElasticSettingsViewModel

@if (!Model.SearchIndexes.Any())
{
<div class="alert alert-warning">@T["You need to create at least an index to set as the Search index."]</div>
<div class="alert alert-warning">@T["No indices exists! Please create at least one index to configure Elasticsearch service."]</div>

return;
}
Expand Down Expand Up @@ -38,7 +39,7 @@
<label asp-for="SearchFields" class="form-label">@T["Default searched fields"]</label>
<input asp-for="SearchFields" class="form-control" />
<span asp-validation-for="SearchFields"></span>
<span class="hint">@T["A comma separated list of fields to use for search pages. The default value is <code>Content.ContentItem.FullText</code>."]</span>
<span class="hint">@T["A comma separated list of fields to use for search pages. The default value is <code>{0}</code>.", IndexingConstants.FullTextKey]</span>
</div>

<script at="Foot">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using OrchardCore.Entities;
using OrchardCore.Search.Abstractions;
using OrchardCore.Search.Lucene.Model;
using OrchardCore.Search.Lucene.Services;
Expand All @@ -11,18 +10,13 @@

namespace OrchardCore.Search.Lucene.Handler;

public class LuceneAuthorizationHandler : AuthorizationHandler<PermissionRequirement>
public class LuceneAuthorizationHandler(IServiceProvider serviceProvider) : AuthorizationHandler<PermissionRequirement>
{
private readonly IServiceProvider _serviceProvider;
private readonly IServiceProvider _serviceProvider = serviceProvider;

private IAuthorizationService _authorizationService;
private ISiteService _siteService;

public LuceneAuthorizationHandler(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}

protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
{
if (context.HasSucceeded)
Expand All @@ -36,9 +30,7 @@ protected override async Task HandleRequirementAsync(AuthorizationHandlerContext
return;
}

var service = _serviceProvider.GetService<LuceneSearchService>();

if (service == null || service.Name != parameters.ServiceName)
if (LuceneSearchService.Key != parameters.ServiceName)
{
// Only validate if Lucene is requested.
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System;
using System.Threading.Tasks;
using Lucene.Net.QueryParsers.Classic;
using Microsoft.Extensions.Logging;
using OrchardCore.Entities;
using OrchardCore.Search.Abstractions;
using OrchardCore.Search.Lucene.Model;
using OrchardCore.Settings;
Expand All @@ -11,6 +9,8 @@ namespace OrchardCore.Search.Lucene.Services;

public class LuceneSearchService : ISearchService
{
public const string Key = "Lucene";

private readonly ISiteService _siteService;
private readonly LuceneIndexManager _luceneIndexManager;
private readonly LuceneIndexingService _luceneIndexingService;
Expand All @@ -37,7 +37,7 @@ public LuceneSearchService(
_logger = logger;
}

public string Name => "Lucene";
public string Name => Key;

public async Task<SearchResult> SearchAsync(string indexName, string term, int start, int size)
{
Expand All @@ -56,7 +56,7 @@ public async Task<SearchResult> SearchAsync(string indexName, string term, int s

if (defaultSearchFields == null || defaultSearchFields.Length == 0)
{
_logger.LogWarning("Lucene: Couldn't execute search. No serach provider settings was defined.");
_logger.LogWarning("Lucene: Couldn't execute search. No search provider settings was defined.");

return result;
}
Expand Down Expand Up @@ -89,6 +89,6 @@ private async Task<string[]> GetSearchFieldsAsync()
{
var luceneSettings = await _luceneIndexingService.GetLuceneSettingsAsync();

return luceneSettings?.DefaultSearchFields ?? Array.Empty<string>();
return luceneSettings?.DefaultSearchFields ?? [];
}
}
11 changes: 9 additions & 2 deletions src/OrchardCore.Modules/OrchardCore.Search.Lucene/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ public override void ConfigureServices(IServiceCollection services)
services.AddRecipeExecutionStep<LuceneIndexStep>();
services.AddRecipeExecutionStep<LuceneIndexRebuildStep>();
services.AddRecipeExecutionStep<LuceneIndexResetStep>();
services.AddScoped<LuceneSearchService>();
services.AddScoped<ISearchService>(sp => sp.GetRequiredService<LuceneSearchService>());
services.AddScoped<IAuthorizationHandler, LuceneAuthorizationHandler>();
}

Expand Down Expand Up @@ -129,6 +127,15 @@ public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder ro
}
}

[RequireFeatures("OrchardCore.Search")]
public class SearchStartup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddScoped<ISearchService, LuceneSearchService>();
}
}

[RequireFeatures("OrchardCore.Deployment")]
public class DeploymentStartup : StartupBase
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,25 @@

namespace OrchardCore.Search.Elasticsearch.Core.Handlers
{
public class ElasticIndexingContentHandler : ContentHandlerBase
public class ElasticIndexingContentHandler(IHttpContextAccessor httpContextAccessor) : ContentHandlerBase
{
private readonly List<ContentContextBase> _contexts = new();
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly List<ContentContextBase> _contexts = [];
private readonly IHttpContextAccessor _httpContextAccessor = httpContextAccessor;

public ElasticIndexingContentHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public override Task PublishedAsync(PublishContentContext context)
=> AddContextAsync(context);

public override Task CreatedAsync(CreateContentContext context)
=> AddContextAsync(context);

public override Task UpdatedAsync(UpdateContentContext context)
=> AddContextAsync(context);

public override Task RemovedAsync(RemoveContentContext context)
=> AddContextAsync(context);

public override Task PublishedAsync(PublishContentContext context) => AddContextAsync(context);
public override Task CreatedAsync(CreateContentContext context) => AddContextAsync(context);
public override Task UpdatedAsync(UpdateContentContext context) => AddContextAsync(context);
public override Task RemovedAsync(RemoveContentContext context) => AddContextAsync(context);
public override Task UnpublishedAsync(PublishContentContext context) => AddContextAsync(context);
public override Task UnpublishedAsync(PublishContentContext context)
=> AddContextAsync(context);

private Task AddContextAsync(ContentContextBase context)
{
Expand All @@ -43,7 +47,7 @@ private Task AddContextAsync(ContentContextBase context)

if (context.ContentItem.Id == 0)
{
// Ignore that case, when Update is called on a content item which has not be "created" yet.
// Ignore that case, when Update is called on a content item which has not been created yet.
return Task.CompletedTask;
}

Expand Down Expand Up @@ -105,15 +109,15 @@ private static async Task IndexingAsync(ShellScope scope, IEnumerable<ContentCon

if (contentItem == null)
{
await elasticIndexManager.DeleteDocumentsAsync(indexSettings.IndexName, new string[] { context.ContentItem.ContentItemId });
await elasticIndexManager.DeleteDocumentsAsync(indexSettings.IndexName, [context.ContentItem.ContentItemId]);
}
else
{
var buildIndexContext = new BuildIndexContext(new DocumentIndex(contentItem.ContentItemId, contentItem.ContentItemVersionId), contentItem, new string[] { contentItem.ContentType }, new ElasticContentIndexSettings());
var buildIndexContext = new BuildIndexContext(new DocumentIndex(contentItem.ContentItemId, contentItem.ContentItemVersionId), contentItem, [contentItem.ContentType], new ElasticContentIndexSettings());
await contentItemIndexHandlers.InvokeAsync(x => x.BuildIndexAsync(buildIndexContext), logger);

await elasticIndexManager.DeleteDocumentsAsync(indexSettings.IndexName, new string[] { contentItem.ContentItemId });
await elasticIndexManager.StoreDocumentsAsync(indexSettings.IndexName, new DocumentIndex[] { buildIndexContext.DocumentIndex });
await elasticIndexManager.DeleteDocumentsAsync(indexSettings.IndexName, [contentItem.ContentItemId]);
await elasticIndexManager.StoreDocumentsAsync(indexSettings.IndexName, [buildIndexContext.DocumentIndex]);
}
}
}
Expand Down
Loading