async tree search (#12344)

This commit is contained in:
Chad
2022-05-04 07:13:27 +12:00
committed by GitHub
parent beeaa35320
commit 9f4ff0a398
12 changed files with 96 additions and 30 deletions

View File

@@ -0,0 +1,25 @@
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Umbraco.Cms.Core.Models.ContentEditing
{
[DataContract(Name = "searchResults", Namespace = "")]
public class EntitySearchResults : IEnumerable<SearchResultEntity?>
{
private readonly IEnumerable<SearchResultEntity?> _results;
public EntitySearchResults(IEnumerable<SearchResultEntity?> results, long totalFound)
{
_results = results;
TotalResults = totalFound;
}
[DataMember(Name = "totalResults")]
public long TotalResults { get; set; }
public IEnumerator<SearchResultEntity?> GetEnumerator() => _results.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_results).GetEnumerator();
}
}

View File

@@ -1,4 +1,6 @@
using System.Runtime.Serialization;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Umbraco.Cms.Core.Models.ContentEditing
{

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Models.ContentEditing;
@@ -22,6 +23,6 @@ namespace Umbraco.Cms.Core.Trees
/// A starting point for the search, generally a node id, but for members this is a member type alias
/// </param>
/// <returns></returns>
IEnumerable<SearchResultEntity?> Search(string query, int pageSize, long pageIndex, out long totalFound, string? searchFrom = null);
Task<EntitySearchResults> SearchAsync(string query, int pageSize, long pageIndex, string? searchFrom = null);
}
}

View File

@@ -1,10 +1,12 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Dynamic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
@@ -193,9 +195,9 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
/// methods might be used in things like pickers in the content editor.
/// </remarks>
[HttpGet]
public IDictionary<string, TreeSearchResult> SearchAll(string query)
public async Task<IDictionary<string, TreeSearchResult>> SearchAll(string query)
{
var result = new Dictionary<string, TreeSearchResult>();
var result = new ConcurrentDictionary<string, TreeSearchResult>();
if (string.IsNullOrEmpty(query))
{
@@ -204,6 +206,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
var allowedSections = _backofficeSecurityAccessor.BackOfficeSecurity?.CurrentUser?.AllowedSections.ToArray();
var searchTasks = new List<Task>();
foreach (KeyValuePair<string, SearchableApplicationTree> searchableTree in _searchableTreeCollection
.SearchableApplicationTrees.OrderBy(t => t.Value.SortOrder))
{
@@ -218,21 +221,32 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
var rootNodeDisplayName = Tree.GetRootNodeDisplayName(tree, _localizedTextService);
if (rootNodeDisplayName is not null)
{
result[rootNodeDisplayName] = new TreeSearchResult
{
Results = searchableTree.Value.SearchableTree.Search(query, 200, 0, out var total).WhereNotNull(),
TreeAlias = searchableTree.Key,
AppAlias = searchableTree.Value.AppAlias,
JsFormatterService = searchableTree.Value.FormatterService,
JsFormatterMethod = searchableTree.Value.FormatterMethod
};
searchTasks.Add(ExecuteSearchAsync(query, searchableTree, rootNodeDisplayName,result));
}
}
}
await Task.WhenAll(searchTasks);
return result;
}
private static async Task ExecuteSearchAsync(
string query,
KeyValuePair<string, SearchableApplicationTree> searchableTree,
string rootNodeDisplayName,
ConcurrentDictionary<string, TreeSearchResult> result)
{
var searchResult = new TreeSearchResult
{
Results = (await searchableTree.Value.SearchableTree.SearchAsync(query, 200, 0)).WhereNotNull(),
TreeAlias = searchableTree.Key,
AppAlias = searchableTree.Value.AppAlias,
JsFormatterService = searchableTree.Value.FormatterService,
JsFormatterMethod = searchableTree.Value.FormatterMethod
};
result.AddOrUpdate(rootNodeDisplayName, _=> searchResult, (_,_) => searchResult);
}
/// <summary>
/// Gets the path for a given node ID
/// </summary>

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -366,9 +367,10 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
var menuItem = menu.Items.Add<TAction>(LocalizedTextService, hasSeparator, opensDialog);
}
public IEnumerable<SearchResultEntity> Search(string query, int pageSize, long pageIndex, out long totalFound, string? searchFrom = null)
public async Task<EntitySearchResults> SearchAsync(string query, int pageSize, long pageIndex, string? searchFrom = null)
{
return _treeSearcher.ExamineSearch(query, UmbracoEntityTypes.Document, pageSize, pageIndex, out totalFound, searchFrom);
var results = _treeSearcher.ExamineSearch(query, UmbracoEntityTypes.Document, pageSize, pageIndex, out long totalFound, searchFrom);
return new EntitySearchResults(results, totalFound);
}
}
}

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -180,8 +181,11 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
return menu;
}
public IEnumerable<SearchResultEntity?> Search(string query, int pageSize, long pageIndex, out long totalFound, string? searchFrom = null)
=> _treeSearcher.EntitySearch(UmbracoObjectTypes.DocumentType, query, pageSize, pageIndex, out totalFound, searchFrom);
public async Task<EntitySearchResults> SearchAsync(string query, int pageSize, long pageIndex, string? searchFrom = null)
{
var results = _treeSearcher.EntitySearch(UmbracoObjectTypes.DocumentType, query, pageSize, pageIndex, out long totalFound, searchFrom);
return new EntitySearchResults(results, totalFound);
}
}
}

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -170,7 +171,10 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
return menu;
}
public IEnumerable<SearchResultEntity?> Search(string query, int pageSize, long pageIndex, out long totalFound, string? searchFrom = null)
=> _treeSearcher.EntitySearch(UmbracoObjectTypes.DataType, query, pageSize, pageIndex, out totalFound, searchFrom);
public async Task<EntitySearchResults> SearchAsync(string query, int pageSize, long pageIndex, string? searchFrom = null)
{
var results = _treeSearcher.EntitySearch(UmbracoObjectTypes.DataType, query, pageSize, pageIndex, out long totalFound, searchFrom);
return new EntitySearchResults(results, totalFound);
}
}
}

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -183,9 +184,10 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
return HasPathAccess(entity, queryStrings);
}
public IEnumerable<SearchResultEntity> Search(string query, int pageSize, long pageIndex, out long totalFound, string? searchFrom = null)
public async Task<EntitySearchResults> SearchAsync(string query, int pageSize, long pageIndex, string? searchFrom = null)
{
return _treeSearcher.ExamineSearch(query, UmbracoEntityTypes.Media, pageSize, pageIndex, out totalFound, searchFrom);
var results = _treeSearcher.ExamineSearch(query, UmbracoEntityTypes.Media, pageSize, pageIndex, out long totalFound, searchFrom);
return new EntitySearchResults(results, totalFound);
}
}

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -145,8 +146,10 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
return menu;
}
public IEnumerable<SearchResultEntity?> Search(string query, int pageSize, long pageIndex, out long totalFound, string? searchFrom = null)
=> _treeSearcher.EntitySearch(UmbracoObjectTypes.MediaType, query, pageSize, pageIndex, out totalFound, searchFrom);
public async Task<EntitySearchResults> SearchAsync(string query, int pageSize, long pageIndex, string? searchFrom = null)
{
var results = _treeSearcher.EntitySearch(UmbracoObjectTypes.MediaType, query, pageSize, pageIndex, out long totalFound, searchFrom);
return new EntitySearchResults(results, totalFound);
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -156,9 +157,10 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
return menu;
}
public IEnumerable<SearchResultEntity> Search(string query, int pageSize, long pageIndex, out long totalFound, string? searchFrom = null)
public async Task<EntitySearchResults> SearchAsync(string query, int pageSize, long pageIndex, string? searchFrom = null)
{
return _treeSearcher.ExamineSearch(query, UmbracoEntityTypes.Member, pageSize, pageIndex, out totalFound, searchFrom);
var results = _treeSearcher.ExamineSearch(query, UmbracoEntityTypes.Member, pageSize, pageIndex, out long totalFound, searchFrom);
return new EntitySearchResults(results, totalFound);
}
}
}

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -63,8 +64,10 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
.Select(dt => CreateTreeNode(dt, Constants.ObjectTypes.MemberType, id, queryStrings, dt?.Icon ?? Constants.Icons.MemberType, false));
}
public IEnumerable<SearchResultEntity?> Search(string query, int pageSize, long pageIndex, out long totalFound, string? searchFrom = null)
=> _treeSearcher.EntitySearch(UmbracoObjectTypes.MemberType, query, pageSize, pageIndex, out totalFound, searchFrom);
public async Task<EntitySearchResults> SearchAsync(string query, int pageSize, long pageIndex, string? searchFrom = null)
{
var results = _treeSearcher.EntitySearch(UmbracoObjectTypes.MemberType, query, pageSize, pageIndex, out long totalFound, searchFrom);
return new EntitySearchResults(results, totalFound);
}
}
}

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -156,7 +157,10 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
};
}
public IEnumerable<SearchResultEntity?> Search(string query, int pageSize, long pageIndex, out long totalFound, string? searchFrom = null)
=> _treeSearcher.EntitySearch(UmbracoObjectTypes.Template, query, pageSize, pageIndex, out totalFound, searchFrom);
public async Task<EntitySearchResults> SearchAsync(string query, int pageSize, long pageIndex, string? searchFrom = null)
{
var results = _treeSearcher.EntitySearch(UmbracoObjectTypes.Template, query, pageSize, pageIndex, out long totalFound, searchFrom);
return new EntitySearchResults(results, totalFound);
}
}
}