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

Examine powered entity search for documents, media and members #15972

Merged
merged 2 commits into from Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -12,12 +12,12 @@ namespace Umbraco.Cms.Api.Management.Controllers.Document.Item;
[ApiVersion("1.0")]
public class SearchDocumentItemController : DocumentItemControllerBase
{
private readonly IEntitySearchService _entitySearchService;
private readonly IExamineEntitySearchService _examineEntitySearchService;
private readonly IDocumentPresentationFactory _documentPresentationFactory;

public SearchDocumentItemController(IEntitySearchService entitySearchService, IDocumentPresentationFactory documentPresentationFactory)
public SearchDocumentItemController(IExamineEntitySearchService examineEntitySearchService, IDocumentPresentationFactory documentPresentationFactory)
{
_entitySearchService = entitySearchService;
_examineEntitySearchService = examineEntitySearchService;
_documentPresentationFactory = documentPresentationFactory;
}

Expand All @@ -26,8 +26,7 @@ public SearchDocumentItemController(IEntitySearchService entitySearchService, ID
[ProducesResponseType(typeof(PagedModel<DocumentItemResponseModel>), StatusCodes.Status200OK)]
public async Task<ActionResult> Search(string query, int skip = 0, int take = 100)
{
// FIXME: use Examine and handle user start nodes
PagedModel<IEntitySlim> searchResult = _entitySearchService.Search(UmbracoObjectTypes.Document, query, skip, take);
PagedModel<IEntitySlim> searchResult = _examineEntitySearchService.Search(UmbracoObjectTypes.Document, query, skip, take);
var result = new PagedModel<DocumentItemResponseModel>
{
Items = searchResult.Items.OfType<IDocumentEntitySlim>().Select(_documentPresentationFactory.CreateItemResponseModel),
Expand Down
Expand Up @@ -12,12 +12,12 @@ namespace Umbraco.Cms.Api.Management.Controllers.Media.Item;
[ApiVersion("1.0")]
public class SearchMediaItemController : MediaItemControllerBase
{
private readonly IEntitySearchService _entitySearchService;
private readonly IExamineEntitySearchService _examineEntitySearchService;
private readonly IMediaPresentationFactory _mediaPresentationFactory;

public SearchMediaItemController(IEntitySearchService entitySearchService, IMediaPresentationFactory mediaPresentationFactory)
public SearchMediaItemController(IExamineEntitySearchService examineEntitySearchService, IMediaPresentationFactory mediaPresentationFactory)
{
_entitySearchService = entitySearchService;
_examineEntitySearchService = examineEntitySearchService;
_mediaPresentationFactory = mediaPresentationFactory;
}

Expand All @@ -26,8 +26,7 @@ public SearchMediaItemController(IEntitySearchService entitySearchService, IMedi
[ProducesResponseType(typeof(PagedModel<MediaItemResponseModel>), StatusCodes.Status200OK)]
public async Task<ActionResult> Search(string query, int skip = 0, int take = 100)
{
// FIXME: use Examine and handle user start nodes
PagedModel<IEntitySlim> searchResult = _entitySearchService.Search(UmbracoObjectTypes.Media, query, skip, take);
PagedModel<IEntitySlim> searchResult = _examineEntitySearchService.Search(UmbracoObjectTypes.Media, query, skip, take);
var result = new PagedModel<MediaItemResponseModel>
{
Items = searchResult.Items.OfType<IMediaEntitySlim>().Select(_mediaPresentationFactory.CreateItemResponseModel),
Expand Down
Expand Up @@ -12,12 +12,12 @@ namespace Umbraco.Cms.Api.Management.Controllers.Member.Item;
[ApiVersion("1.0")]
public class SearchMemberItemController : MemberItemControllerBase
{
private readonly IEntitySearchService _entitySearchService;
private readonly IExamineEntitySearchService _examineEntitySearchService;
private readonly IMemberPresentationFactory _memberPresentationFactory;

public SearchMemberItemController(IEntitySearchService entitySearchService, IMemberPresentationFactory memberPresentationFactory)
public SearchMemberItemController(IExamineEntitySearchService examineEntitySearchService, IMemberPresentationFactory memberPresentationFactory)
{
_entitySearchService = entitySearchService;
_examineEntitySearchService = examineEntitySearchService;
_memberPresentationFactory = memberPresentationFactory;
}

Expand All @@ -26,8 +26,7 @@ public SearchMemberItemController(IEntitySearchService entitySearchService, IMem
[ProducesResponseType(typeof(PagedModel<MemberItemResponseModel>), StatusCodes.Status200OK)]
public async Task<ActionResult> Search(string query, int skip = 0, int take = 100)
{
// FIXME: use Examine
PagedModel<IEntitySlim> searchResult = _entitySearchService.Search(UmbracoObjectTypes.Member, query, skip, take);
PagedModel<IEntitySlim> searchResult = _examineEntitySearchService.Search(UmbracoObjectTypes.Member, query, skip, take);
var result = new PagedModel<MemberItemResponseModel>
{
Items = searchResult.Items.OfType<IMemberEntitySlim>().Select(_memberPresentationFactory.CreateItemResponseModel),
Expand Down
9 changes: 9 additions & 0 deletions src/Umbraco.Core/Services/IExamineEntitySearchService.cs
@@ -0,0 +1,9 @@
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Entities;

namespace Umbraco.Cms.Core.Services;

public interface IExamineEntitySearchService
{
PagedModel<IEntitySlim> Search(UmbracoObjectTypes objectType, string query, int skip = 0, int take = 100, bool ignoreUserStartNodes = false);
}
Expand Up @@ -63,6 +63,7 @@ internal static IUmbracoBuilder AddServices(this IUmbracoBuilder builder)
builder.Services.AddUnique<IContentListViewService, ContentListViewService>();
builder.Services.AddUnique<IMediaListViewService, MediaListViewService>();
builder.Services.AddUnique<IEntitySearchService, EntitySearchService>();
builder.Services.AddUnique<IExamineEntitySearchService, ExamineEntitySearchService>();

return builder;
}
Expand Down
@@ -0,0 +1,59 @@
using Examine;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.Models.Entities;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.Examine;

namespace Umbraco.Cms.Infrastructure.Services.Implement;

internal sealed class ExamineEntitySearchService : IExamineEntitySearchService
{
private readonly IBackOfficeExamineSearcher _backOfficeExamineSearcher;
private readonly IEntityService _entityService;

public ExamineEntitySearchService(IBackOfficeExamineSearcher backOfficeExamineSearcher, IEntityService entityService)
{
_backOfficeExamineSearcher = backOfficeExamineSearcher;
_entityService = entityService;
}

public PagedModel<IEntitySlim> Search(UmbracoObjectTypes objectType, string query, int skip = 0, int take = 100, bool ignoreUserStartNodes = false)
{
UmbracoEntityTypes entityType = objectType switch
{
UmbracoObjectTypes.Document => UmbracoEntityTypes.Document,
UmbracoObjectTypes.Media => UmbracoEntityTypes.Media,
UmbracoObjectTypes.Member => UmbracoEntityTypes.Member,
_ => throw new NotSupportedException("This service only supports searching for documents, media and members")
};

PaginationHelper.ConvertSkipTakeToPaging(skip, take, out var pageNumber, out var pageSize);

IEnumerable<ISearchResult> searchResults = _backOfficeExamineSearcher.Search(
query,
entityType,
pageSize,
pageNumber,
out var totalFound,
ignoreUserStartNodes: ignoreUserStartNodes);

Guid[] keys = searchResults.Select(
result =>
result.Values.TryGetValue(UmbracoExamineFieldNames.NodeKeyFieldName, out var keyValue) &&
Guid.TryParse(keyValue, out Guid key)
? key
: Guid.Empty)
.Where(key => key != Guid.Empty)
.ToArray();

return new PagedModel<IEntitySlim>
{
Items = keys.Any()
? _entityService.GetAll(objectType, keys)
: Enumerable.Empty<IEntitySlim>(),
Total = totalFound
};
}

Check warning on line 58 in src/Umbraco.Infrastructure/Services/Implement/ExamineEntitySearchService.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (v14/dev)

❌ New issue: Complex Method

Search has a cyclomatic complexity of 9, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 58 in src/Umbraco.Infrastructure/Services/Implement/ExamineEntitySearchService.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (v14/dev)

❌ New issue: Excess Number of Function Arguments

Search has 5 arguments, threshold = 4. This function has too many arguments, indicating a lack of encapsulation. Avoid adding more arguments.
}