diff --git a/build/NuSpecs/UmbracoCms.Web.nuspec b/build/NuSpecs/UmbracoCms.Web.nuspec
index 82d15d2b95..59bd7d75aa 100644
--- a/build/NuSpecs/UmbracoCms.Web.nuspec
+++ b/build/NuSpecs/UmbracoCms.Web.nuspec
@@ -28,7 +28,7 @@
-
+
diff --git a/src/Umbraco.Examine/Umbraco.Examine.csproj b/src/Umbraco.Examine/Umbraco.Examine.csproj
index 0e0ee62139..517edf354c 100644
--- a/src/Umbraco.Examine/Umbraco.Examine.csproj
+++ b/src/Umbraco.Examine/Umbraco.Examine.csproj
@@ -49,7 +49,7 @@
-
+
1.0.0-beta2-19324-01
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/Umbraco.Examine/UmbracoContentIndex.cs b/src/Umbraco.Examine/UmbracoContentIndex.cs
index 88033b1407..468e794110 100644
--- a/src/Umbraco.Examine/UmbracoContentIndex.cs
+++ b/src/Umbraco.Examine/UmbracoContentIndex.cs
@@ -11,7 +11,7 @@ using Lucene.Net.Store;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using Examine.LuceneEngine;
-
+using Examine.Search;
namespace Umbraco.Examine
{
///
@@ -21,7 +21,7 @@ namespace Umbraco.Examine
{
public const string VariesByCultureFieldName = SpecialFieldPrefix + "VariesByCulture";
protected ILocalizationService LanguageService { get; }
-
+ private readonly ISet _idOnlyFieldSet = new HashSet { "id" };
#region Constructors
///
@@ -131,8 +131,9 @@ namespace Umbraco.Examine
var searcher = GetSearcher();
var c = searcher.CreateQuery();
var filtered = c.NativeQuery(rawQuery);
- var results = filtered.Execute();
+ var selectedFields = filtered.SelectFields(_idOnlyFieldSet);
+ var results = selectedFields.Execute();
ProfilingLogger.Debug(GetType(), "DeleteFromIndex with query: {Query} (found {TotalItems} results)", rawQuery, results.TotalItemCount);
//need to queue a delete item for each one found
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index 2ac28aa7d7..97604df0c6 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -79,7 +79,7 @@
-
+
1.8.14
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index 01d029cae0..69bdeba643 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -88,7 +88,7 @@
-
+
diff --git a/src/Umbraco.Web/IPublishedContentQuery.cs b/src/Umbraco.Web/IPublishedContentQuery.cs
index 7066475dc9..f513c1ac02 100644
--- a/src/Umbraco.Web/IPublishedContentQuery.cs
+++ b/src/Umbraco.Web/IPublishedContentQuery.cs
@@ -9,6 +9,31 @@ using Umbraco.Core.Xml;
namespace Umbraco.Web
{
using Examine = global::Examine;
+ public interface IPublishedContentQuery2 : IPublishedContentQuery
+ {
+ ///
+ /// Searches content.
+ ///
+ /// The term to search.
+ /// The amount of results to skip.
+ /// The amount of results to take/return.
+ /// The total amount of records.
+ /// The culture (defaults to a culture insensitive search).
+ /// The name of the index to search (defaults to ).
+ /// The fields to load in the results of the search (defaults to all fields loaded).
+ ///
+ /// The search results.
+ ///
+ ///
+ ///
+ /// When the is not specified or is *, all cultures are searched.
+ /// To search for only invariant documents and fields use null.
+ /// When searching on a specific culture, all culture specific fields are searched for the provided culture and all invariant fields for all documents.
+ ///
+ /// While enumerating results, the ambient culture is changed to be the searched culture.
+ ///
+ IEnumerable Search(string term, int skip, int take, out long totalRecords, string culture = "*", string indexName = Umbraco.Core.Constants.UmbracoIndexes.ExternalIndexName, ISet loadedFields = null);
+ }
///
/// Query methods used for accessing strongly typed content in templates
diff --git a/src/Umbraco.Web/PublishedContentQuery.cs b/src/Umbraco.Web/PublishedContentQuery.cs
index d697898f33..760a4b1c82 100644
--- a/src/Umbraco.Web/PublishedContentQuery.cs
+++ b/src/Umbraco.Web/PublishedContentQuery.cs
@@ -16,7 +16,7 @@ namespace Umbraco.Web
///
/// A class used to query for published content, media items
///
- public class PublishedContentQuery : IPublishedContentQuery
+ public class PublishedContentQuery : IPublishedContentQuery2
{
private readonly IPublishedSnapshot _publishedSnapshot;
private readonly IVariationContextAccessor _variationContextAccessor;
@@ -190,6 +190,10 @@ namespace Umbraco.Web
///
public IEnumerable Search(string term, int skip, int take, out long totalRecords, string culture = "*", string indexName = Constants.UmbracoIndexes.ExternalIndexName)
+ => Search(term, skip, take, out totalRecords, culture, indexName, null);
+
+ ///
+ public IEnumerable Search(string term, int skip, int take, out long totalRecords, string culture = "*", string indexName = Constants.UmbracoIndexes.ExternalIndexName, ISet loadedFields = null)
{
if (skip < 0)
{
@@ -212,7 +216,7 @@ namespace Umbraco.Web
}
var query = umbIndex.GetSearcher().CreateQuery(IndexTypes.Content);
-
+
IQueryExecutor queryExecutor;
if (culture == "*")
{
@@ -231,6 +235,10 @@ namespace Umbraco.Web
var fields = umbIndex.GetCultureAndInvariantFields(culture).ToArray(); // Get all index fields suffixed with the culture name supplied
queryExecutor = query.ManagedQuery(term, fields);
}
+ if (loadedFields != null && queryExecutor is IBooleanOperation booleanOperation)
+ {
+ queryExecutor = booleanOperation.SelectFields(loadedFields);
+ }
var results = skip == 0 && take == 0
? queryExecutor.Execute()
diff --git a/src/Umbraco.Web/Search/ExamineComponent.cs b/src/Umbraco.Web/Search/ExamineComponent.cs
index c9d7b7cf56..4fa2427fac 100644
--- a/src/Umbraco.Web/Search/ExamineComponent.cs
+++ b/src/Umbraco.Web/Search/ExamineComponent.cs
@@ -19,6 +19,7 @@ using Umbraco.Core.Composing;
using System.ComponentModel;
using System.Threading;
using Umbraco.Web.Scheduling;
+using Examine.Search;
namespace Umbraco.Web.Search
{
@@ -39,6 +40,7 @@ namespace Umbraco.Web.Search
private readonly IProfilingLogger _logger;
private readonly IUmbracoIndexesCreator _indexCreator;
private readonly BackgroundTaskRunner _indexItemTaskRunner;
+ private readonly ISet _idOnlyFieldSet = new HashSet { "id" };
// the default enlist priority is 100
@@ -425,7 +427,7 @@ namespace Umbraco.Web.Search
while (page * pageSize < total)
{
//paging with examine, see https://shazwazza.com/post/paging-with-examine/
- var results = searcher.CreateQuery().Field("nodeType", id.ToInvariantString()).Execute(maxResults: pageSize * (page + 1));
+ var results = searcher.CreateQuery().Field("nodeType", id.ToInvariantString()).SelectFields(_idOnlyFieldSet).Execute(maxResults: pageSize * (page + 1));
total = results.TotalItemCount;
var paged = results.Skip(page * pageSize);
diff --git a/src/Umbraco.Web/Search/GenericIndexDiagnostics.cs b/src/Umbraco.Web/Search/GenericIndexDiagnostics.cs
index cb25e1242a..c8d3a72a96 100644
--- a/src/Umbraco.Web/Search/GenericIndexDiagnostics.cs
+++ b/src/Umbraco.Web/Search/GenericIndexDiagnostics.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using Examine;
+using Examine.Search;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Examine;
@@ -17,6 +18,7 @@ namespace Umbraco.Web.Search
private readonly IIndex _index;
private static readonly string[] IgnoreProperties = { "Description" };
+ private readonly ISet _idOnlyFieldSet = new HashSet { "id" };
public GenericIndexDiagnostics(IIndex index)
{
_index = index;
@@ -34,7 +36,7 @@ namespace Umbraco.Web.Search
try
{
var searcher = _index.GetSearcher();
- var result = searcher.Search("test");
+ var result = searcher.CreateQuery().ManagedQuery("test").SelectFields(_idOnlyFieldSet).Execute(1);
return Attempt.Succeed(); //if we can search we'll assume it's healthy
}
catch (Exception e)
diff --git a/src/Umbraco.Web/Search/IUmbracoTreeSearcherFields2.cs b/src/Umbraco.Web/Search/IUmbracoTreeSearcherFields2.cs
new file mode 100644
index 0000000000..42f592a965
--- /dev/null
+++ b/src/Umbraco.Web/Search/IUmbracoTreeSearcherFields2.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Umbraco.Web.Search
+{
+ public interface IUmbracoTreeSearcherFields2 : IUmbracoTreeSearcherFields
+ {
+ ///
+ /// Set of fields for all node types to be loaded
+ ///
+ ISet GetBackOfficeFieldsToLoad();
+ ///
+ /// Set list of fields for Members to be loaded
+ ///
+ ISet GetBackOfficeMembersFieldsToLoad();
+ ///
+ /// Set of fields for Media to be loaded
+ ///
+ ISet GetBackOfficeMediaFieldsToLoad();
+
+ ///
+ /// Set of fields for Documents to be loaded
+ ///
+ ISet GetBackOfficeDocumentFieldsToLoad();
+ }
+}
diff --git a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs
index 410b654e32..44ba0766e0 100644
--- a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs
+++ b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Examine;
+using Examine.Search;
using Umbraco.Core;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
@@ -82,6 +83,7 @@ namespace Umbraco.Web.Search
string type;
var indexName = Constants.UmbracoIndexes.InternalIndexName;
var fields = _umbracoTreeSearcherFields.GetBackOfficeFields().ToList();
+ ISet fieldsToLoad = null;
// 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...
@@ -102,6 +104,10 @@ namespace Umbraco.Web.Search
indexName = Constants.UmbracoIndexes.MembersIndexName;
type = "member";
fields.AddRange(_umbracoTreeSearcherFields.GetBackOfficeMembersFields());
+ if (_umbracoTreeSearcherFields is IUmbracoTreeSearcherFields2 umbracoTreeSearcherFieldMember)
+ {
+ fieldsToLoad = umbracoTreeSearcherFieldMember.GetBackOfficeMembersFieldsToLoad();
+ }
if (searchFrom != null && searchFrom != Constants.Conventions.MemberTypes.AllMembersListId && searchFrom.Trim() != "-1")
{
sb.Append("+__NodeTypeAlias:");
@@ -112,12 +118,20 @@ namespace Umbraco.Web.Search
case UmbracoEntityTypes.Media:
type = "media";
fields.AddRange(_umbracoTreeSearcherFields.GetBackOfficeMediaFields());
+ if (_umbracoTreeSearcherFields is IUmbracoTreeSearcherFields2 umbracoTreeSearcherFieldsMedia)
+ {
+ fieldsToLoad = umbracoTreeSearcherFieldsMedia.GetBackOfficeMediaFieldsToLoad();
+ }
var allMediaStartNodes = _umbracoContext.Security.CurrentUser.CalculateMediaStartNodeIds(_entityService);
AppendPath(sb, UmbracoObjectTypes.Media, allMediaStartNodes, searchFrom, ignoreUserStartNodes, _entityService);
break;
case UmbracoEntityTypes.Document:
type = "content";
fields.AddRange(_umbracoTreeSearcherFields.GetBackOfficeDocumentFields());
+ if (_umbracoTreeSearcherFields is IUmbracoTreeSearcherFields2 umbracoTreeSearcherFieldsDocument)
+ {
+ fieldsToLoad = umbracoTreeSearcherFieldsDocument.GetBackOfficeDocumentFieldsToLoad();
+ }
var allContentStartNodes = _umbracoContext.Security.CurrentUser.CalculateContentStartNodeIds(_entityService);
AppendPath(sb, UmbracoObjectTypes.Document, allContentStartNodes, searchFrom, ignoreUserStartNodes, _entityService);
break;
@@ -136,7 +150,7 @@ namespace Umbraco.Web.Search
return Enumerable.Empty();
}
- var result = internalSearcher.CreateQuery().NativeQuery(sb.ToString())
+ var result = internalSearcher.CreateQuery().NativeQuery(sb.ToString()).SelectFields(fieldsToLoad)
//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)));
diff --git a/src/Umbraco.Web/Search/UmbracoTreeSearcherFields.cs b/src/Umbraco.Web/Search/UmbracoTreeSearcherFields.cs
index f90d7bc6b6..5a2fd91d18 100644
--- a/src/Umbraco.Web/Search/UmbracoTreeSearcherFields.cs
+++ b/src/Umbraco.Web/Search/UmbracoTreeSearcherFields.cs
@@ -4,7 +4,7 @@ using Umbraco.Examine;
namespace Umbraco.Web.Search
{
- public class UmbracoTreeSearcherFields : IUmbracoTreeSearcherFields
+ public class UmbracoTreeSearcherFields : IUmbracoTreeSearcherFields2
{
private IReadOnlyList _backOfficeFields = new List {"id", "__NodeId", "__Key"};
public IEnumerable GetBackOfficeFields()
@@ -27,5 +27,29 @@ namespace Umbraco.Web.Search
{
return Enumerable.Empty();
}
+
+ private readonly ISet _backOfficeFieldsToLoad = new HashSet { "id", "__NodeId", "__Key" };
+ public ISet GetBackOfficeFieldsToLoad()
+ {
+ return _backOfficeFieldsToLoad;
+ }
+
+ private readonly ISet _backOfficeMembersFieldsToLoad = new HashSet { "id", "__NodeId", "__Key", "email", "loginName" };
+ public ISet GetBackOfficeMembersFieldsToLoad()
+ {
+ return _backOfficeMembersFieldsToLoad;
+ }
+
+ private readonly ISet _backOfficeMediaFieldsToLoad = new HashSet { "id", "__NodeId", "__Key", UmbracoExamineIndex.UmbracoFileFieldName };
+ public ISet GetBackOfficeMediaFieldsToLoad()
+ {
+ return _backOfficeMediaFieldsToLoad;
+ }
+ private readonly ISet _backOfficeDocumentFieldsToLoad = new HashSet { "id", "__NodeId", "__Key" };
+
+ public ISet GetBackOfficeDocumentFieldsToLoad()
+ {
+ return _backOfficeDocumentFieldsToLoad;
+ }
}
}
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 8890d9cf25..189d2e02d1 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -63,7 +63,7 @@
-
+
4.0.217
@@ -284,6 +284,7 @@
+