Skip to content

Commit

Permalink
Cleanup Search Services (OrchardCMS#14928)
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeAlhayek authored and urbanit committed Mar 18, 2024
1 parent 8d17dcd commit 6a265ad
Show file tree
Hide file tree
Showing 19 changed files with 227 additions and 249 deletions.
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,18 @@ public async Task BuildIndexAsync(BuildIndexContext context)

foreach (var segment in result.Segments)
{
stringBuilder.Append(segment + " ");
stringBuilder.Append(segment);
stringBuilder.Append(" ");
}

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 exist! 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

0 comments on commit 6a265ad

Please sign in to comment.