Fixes back office searching

This commit is contained in:
Shannon
2021-06-23 12:46:50 -06:00
parent 37685e3b77
commit 76d206a4ba
6 changed files with 84 additions and 55 deletions

View File

@@ -8,7 +8,7 @@ using Umbraco.Core.Xml;
namespace Umbraco.Web namespace Umbraco.Web
{ {
using Examine = global::Examine; // TODO: Merge this into IPublishedContentQuery for v9!
public interface IPublishedContentQuery2 : IPublishedContentQuery public interface IPublishedContentQuery2 : IPublishedContentQuery
{ {
/// <summary> /// <summary>
@@ -32,7 +32,7 @@ namespace Umbraco.Web
/// </para> /// </para>
/// <para>While enumerating results, the ambient culture is changed to be the searched culture.</para> /// <para>While enumerating results, the ambient culture is changed to be the searched culture.</para>
/// </remarks> /// </remarks>
IEnumerable<PublishedSearchResult> Search(string term, int skip, int take, out long totalRecords, string culture = "*", string indexName = Umbraco.Core.Constants.UmbracoIndexes.ExternalIndexName, ISet<string> loadedFields = null); IEnumerable<PublishedSearchResult> Search(string term, int skip, int take, out long totalRecords, string culture = "*", string indexName = Constants.UmbracoIndexes.ExternalIndexName, ISet<string> loadedFields = null);
} }
/// <summary> /// <summary>

View File

@@ -180,7 +180,7 @@ namespace Umbraco.Web.Models.Mapping
target.Name = source.Values.ContainsKey("nodeName") ? source.Values["nodeName"] : "[no name]"; target.Name = source.Values.ContainsKey("nodeName") ? source.Values["nodeName"] : "[no name]";
var culture = context.GetCulture(); var culture = context.GetCulture()?.ToLowerInvariant();
if(culture.IsNullOrWhiteSpace() == false) if(culture.IsNullOrWhiteSpace() == false)
{ {
target.Name = source.Values.ContainsKey($"nodeName_{culture}") ? source.Values[$"nodeName_{culture}"] : target.Name; target.Name = source.Values.ContainsKey($"nodeName_{culture}") ? source.Values[$"nodeName_{culture}"] : target.Name;

View File

@@ -8,19 +8,22 @@ namespace Umbraco.Web.Search
public interface IUmbracoTreeSearcherFields public interface IUmbracoTreeSearcherFields
{ {
/// <summary> /// <summary>
/// Propagate list of searchable fields for all node types /// The default index fields that are searched on in the back office search for umbraco content entities.
/// </summary> /// </summary>
IEnumerable<string> GetBackOfficeFields(); IEnumerable<string> GetBackOfficeFields();
/// <summary> /// <summary>
/// Propagate list of searchable fields for Members /// The additional index fields that are searched on in the back office for member entities.
/// </summary> /// </summary>
IEnumerable<string> GetBackOfficeMembersFields(); IEnumerable<string> GetBackOfficeMembersFields();
/// <summary> /// <summary>
/// Propagate list of searchable fields for Media /// The additional index fields that are searched on in the back office for media entities.
/// </summary> /// </summary>
IEnumerable<string> GetBackOfficeMediaFields(); IEnumerable<string> GetBackOfficeMediaFields();
/// <summary> /// <summary>
/// Propagate list of searchable fields for Documents /// The additional index fields that are searched on in the back office for document entities.
/// </summary> /// </summary>
IEnumerable<string> GetBackOfficeDocumentFields(); IEnumerable<string> GetBackOfficeDocumentFields();
} }

View File

@@ -1,28 +1,29 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Umbraco.Web.Search namespace Umbraco.Web.Search
{ {
// TODO: Merge this interface to IUmbracoTreeSearcherFields for v9.
// We should probably make these method make a little more sense when they are combined so have
// a single method for getting fields to search and fields to load for each category.
public interface IUmbracoTreeSearcherFields2 : IUmbracoTreeSearcherFields public interface IUmbracoTreeSearcherFields2 : IUmbracoTreeSearcherFields
{ {
/// <summary> /// <summary>
/// Set of fields for all node types to be loaded /// Set of fields for all node types to be loaded
/// </summary> /// </summary>
ISet<string> GetBackOfficeFieldsToLoad(); ISet<string> GetBackOfficeFieldsToLoad();
/// <summary> /// <summary>
/// Set list of fields for Members to be loaded /// Additional set list of fields for Members to be loaded
/// </summary> /// </summary>
ISet<string> GetBackOfficeMembersFieldsToLoad(); ISet<string> GetBackOfficeMembersFieldsToLoad();
/// <summary> /// <summary>
/// Set of fields for Media to be loaded /// Additional set of fields for Media to be loaded
/// </summary> /// </summary>
ISet<string> GetBackOfficeMediaFieldsToLoad(); ISet<string> GetBackOfficeMediaFieldsToLoad();
/// <summary> /// <summary>
/// Set of fields for Documents to be loaded /// Additional set of fields for Documents to be loaded
/// </summary> /// </summary>
ISet<string> GetBackOfficeDocumentFieldsToLoad(); ISet<string> GetBackOfficeDocumentFieldsToLoad();
} }

View File

@@ -101,7 +101,9 @@ namespace Umbraco.Web.Search
string type; string type;
var indexName = Constants.UmbracoIndexes.InternalIndexName; var indexName = Constants.UmbracoIndexes.InternalIndexName;
var fields = _umbracoTreeSearcherFields.GetBackOfficeFields().ToList(); var fields = _umbracoTreeSearcherFields.GetBackOfficeFields().ToList();
ISet<string> fieldsToLoad = null; ISet<string> fieldsToLoad = _umbracoTreeSearcherFields is IUmbracoTreeSearcherFields2 searcherFields2
? new HashSet<string>(searcherFields2.GetBackOfficeFieldsToLoad())
: null;
// TODO: WE should try to allow passing in a lucene raw query, however we will still need to do some manual string // TODO: WE should try to allow passing in a lucene raw query, however we will still need to do some manual string
// manipulation for things like start paths, member types, etc... // manipulation for things like start paths, member types, etc...
@@ -124,7 +126,10 @@ namespace Umbraco.Web.Search
fields.AddRange(_umbracoTreeSearcherFields.GetBackOfficeMembersFields()); fields.AddRange(_umbracoTreeSearcherFields.GetBackOfficeMembersFields());
if (_umbracoTreeSearcherFields is IUmbracoTreeSearcherFields2 umbracoTreeSearcherFieldMember) if (_umbracoTreeSearcherFields is IUmbracoTreeSearcherFields2 umbracoTreeSearcherFieldMember)
{ {
fieldsToLoad = umbracoTreeSearcherFieldMember.GetBackOfficeMembersFieldsToLoad(); foreach(var field in umbracoTreeSearcherFieldMember.GetBackOfficeMembersFieldsToLoad())
{
fieldsToLoad.Add(field);
}
} }
if (searchFrom != null && searchFrom != Constants.Conventions.MemberTypes.AllMembersListId && searchFrom.Trim() != "-1") if (searchFrom != null && searchFrom != Constants.Conventions.MemberTypes.AllMembersListId && searchFrom.Trim() != "-1")
{ {
@@ -138,9 +143,13 @@ namespace Umbraco.Web.Search
fields.AddRange(_umbracoTreeSearcherFields.GetBackOfficeMediaFields()); fields.AddRange(_umbracoTreeSearcherFields.GetBackOfficeMediaFields());
if (_umbracoTreeSearcherFields is IUmbracoTreeSearcherFields2 umbracoTreeSearcherFieldsMedia) if (_umbracoTreeSearcherFields is IUmbracoTreeSearcherFields2 umbracoTreeSearcherFieldsMedia)
{ {
fieldsToLoad = umbracoTreeSearcherFieldsMedia.GetBackOfficeMediaFieldsToLoad(); foreach (var field in umbracoTreeSearcherFieldsMedia.GetBackOfficeMediaFieldsToLoad())
{
fieldsToLoad.Add(field);
}
} }
var allMediaStartNodes = _umbracoContext.Security.CurrentUser.CalculateMediaStartNodeIds(_entityService _appCaches);
var allMediaStartNodes = _umbracoContext.Security.CurrentUser.CalculateMediaStartNodeIds(_entityService, _appCaches);
AppendPath(sb, UmbracoObjectTypes.Media, allMediaStartNodes, searchFrom, ignoreUserStartNodes, _entityService); AppendPath(sb, UmbracoObjectTypes.Media, allMediaStartNodes, searchFrom, ignoreUserStartNodes, _entityService);
break; break;
case UmbracoEntityTypes.Document: case UmbracoEntityTypes.Document:
@@ -148,7 +157,10 @@ namespace Umbraco.Web.Search
fields.AddRange(_umbracoTreeSearcherFields.GetBackOfficeDocumentFields()); fields.AddRange(_umbracoTreeSearcherFields.GetBackOfficeDocumentFields());
if (_umbracoTreeSearcherFields is IUmbracoTreeSearcherFields2 umbracoTreeSearcherFieldsDocument) if (_umbracoTreeSearcherFields is IUmbracoTreeSearcherFields2 umbracoTreeSearcherFieldsDocument)
{ {
fieldsToLoad = umbracoTreeSearcherFieldsDocument.GetBackOfficeDocumentFieldsToLoad(); foreach (var field in umbracoTreeSearcherFieldsDocument.GetBackOfficeDocumentFieldsToLoad())
{
fieldsToLoad.Add(field);
}
} }
var allContentStartNodes = _umbracoContext.Security.CurrentUser.CalculateContentStartNodeIds(_entityService, _appCaches); var allContentStartNodes = _umbracoContext.Security.CurrentUser.CalculateContentStartNodeIds(_entityService, _appCaches);
AppendPath(sb, UmbracoObjectTypes.Document, allContentStartNodes, searchFrom, ignoreUserStartNodes, _entityService); AppendPath(sb, UmbracoObjectTypes.Document, allContentStartNodes, searchFrom, ignoreUserStartNodes, _entityService);
@@ -168,7 +180,13 @@ namespace Umbraco.Web.Search
return Enumerable.Empty<SearchResultEntity>(); return Enumerable.Empty<SearchResultEntity>();
} }
var result = internalSearcher.CreateQuery().NativeQuery(sb.ToString()).SelectFields(fieldsToLoad) var examineQuery = internalSearcher.CreateQuery().NativeQuery(sb.ToString());
if (fieldsToLoad != null)
{
examineQuery.SelectFields(fieldsToLoad);
}
var result = examineQuery
//only return the number of items specified to read up to the amount of records to fill from 0 -> the number of items on the page requested //only return the number of items specified to read up to the amount of records to fill from 0 -> the number of items on the page requested
.Execute(Convert.ToInt32(pageSize * (pageIndex + 1))); .Execute(Convert.ToInt32(pageSize * (pageIndex + 1)));

View File

@@ -1,55 +1,62 @@
using Examine;
using Examine.LuceneEngine.Providers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Umbraco.Core.Services;
using Umbraco.Examine; using Umbraco.Examine;
namespace Umbraco.Web.Search namespace Umbraco.Web.Search
{ {
public class UmbracoTreeSearcherFields : IUmbracoTreeSearcherFields2 public class UmbracoTreeSearcherFields : IUmbracoTreeSearcherFields2
{ {
private IReadOnlyList<string> _backOfficeFields = new List<string> {"id", "__NodeId", "__Key"}; private IReadOnlyList<string> _backOfficeFields = new List<string> {"id", LuceneIndex.ItemIdFieldName, UmbracoExamineIndex.NodeKeyFieldName};
public IEnumerable<string> GetBackOfficeFields() private readonly ISet<string> _backOfficeFieldsToLoad = new HashSet<string> { "id", LuceneIndex.ItemIdFieldName, UmbracoExamineIndex.NodeKeyFieldName, "nodeName", UmbracoExamineIndex.IconFieldName, LuceneIndex.CategoryFieldName, "parentID", LuceneIndex.ItemTypeFieldName };
private IReadOnlyList<string> _backOfficeMediaFields = new List<string> { UmbracoExamineIndex.UmbracoFileFieldName };
private readonly ISet<string> _backOfficeMediaFieldsToLoad = new HashSet<string> { UmbracoExamineIndex.UmbracoFileFieldName };
private IReadOnlyList<string> _backOfficeMembersFields = new List<string> { "email", "loginName" };
private readonly ISet<string> _backOfficeMembersFieldsToLoad = new HashSet<string> { "email", "loginName" };
private readonly ISet<string> _backOfficeDocumentFieldsToLoad = new HashSet<string> { UmbracoContentIndex.VariesByCultureFieldName };
private readonly ILocalizationService _localizationService;
public UmbracoTreeSearcherFields(ILocalizationService localizationService)
{ {
return _backOfficeFields; _localizationService = localizationService;
} }
/// <inheritdoc />
public IEnumerable<string> GetBackOfficeFields() => _backOfficeFields;
private IReadOnlyList<string> _backOfficeMembersFields = new List<string> {"email", "loginName"}; /// <inheritdoc />
public IEnumerable<string> GetBackOfficeMembersFields() public IEnumerable<string> GetBackOfficeMembersFields() => _backOfficeMembersFields;
{
return _backOfficeMembersFields;
}
private IReadOnlyList<string> _backOfficeMediaFields = new List<string> {UmbracoExamineIndex.UmbracoFileFieldName };
public IEnumerable<string> GetBackOfficeMediaFields()
{
return _backOfficeMediaFields;
}
public IEnumerable<string> GetBackOfficeDocumentFields()
{
return Enumerable.Empty<string>();
}
private readonly ISet<string> _backOfficeFieldsToLoad = new HashSet<string> { "id", "__NodeId", "__Key" }; /// <inheritdoc />
public ISet<string> GetBackOfficeFieldsToLoad() public IEnumerable<string> GetBackOfficeMediaFields() => _backOfficeMediaFields;
{
return _backOfficeFieldsToLoad;
}
private readonly ISet<string> _backOfficeMembersFieldsToLoad = new HashSet<string> { "id", "__NodeId", "__Key", "email", "loginName" }; /// <inheritdoc />
public ISet<string> GetBackOfficeMembersFieldsToLoad() public IEnumerable<string> GetBackOfficeDocumentFields() => Enumerable.Empty<string>();
{
return _backOfficeMembersFieldsToLoad;
}
private readonly ISet<string> _backOfficeMediaFieldsToLoad = new HashSet<string> { "id", "__NodeId", "__Key", UmbracoExamineIndex.UmbracoFileFieldName }; /// <inheritdoc />
public ISet<string> GetBackOfficeMediaFieldsToLoad() public ISet<string> GetBackOfficeFieldsToLoad() => _backOfficeFieldsToLoad;
{
return _backOfficeMediaFieldsToLoad;
}
private readonly ISet<string> _backOfficeDocumentFieldsToLoad = new HashSet<string> { "id", "__NodeId", "__Key" };
/// <inheritdoc />
public ISet<string> GetBackOfficeMembersFieldsToLoad() => _backOfficeMembersFieldsToLoad;
/// <inheritdoc />
public ISet<string> GetBackOfficeMediaFieldsToLoad() => _backOfficeMediaFieldsToLoad;
/// <inheritdoc />
public ISet<string> GetBackOfficeDocumentFieldsToLoad() public ISet<string> GetBackOfficeDocumentFieldsToLoad()
{ {
return _backOfficeDocumentFieldsToLoad; var fields = _backOfficeDocumentFieldsToLoad;
// We need to load all nodeName_* fields but we won't know those up front so need to get
// all langs (this is cached)
foreach(var field in _localizationService.GetAllLanguages().Select(x => "nodeName_" + x.IsoCode.ToLowerInvariant()))
{
fields.Add(field);
}
return fields;
} }
} }
} }