diff --git a/build/NuSpecs/UmbracoCms.Web.nuspec b/build/NuSpecs/UmbracoCms.Web.nuspec
index 658d2f0672..347bde139e 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 7eff1bddc2..0e0ee62139 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
@@ -112,4 +112,4 @@
-
+
\ No newline at end of file
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index 06f41b21c6..15c8eec0e1 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 56fb338d01..8f0db76c1d 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/ExamineExtensions.cs b/src/Umbraco.Web/ExamineExtensions.cs
index 9a9fa98d95..421993f8fd 100644
--- a/src/Umbraco.Web/ExamineExtensions.cs
+++ b/src/Umbraco.Web/ExamineExtensions.cs
@@ -2,32 +2,95 @@
using System.Collections.Generic;
using System.Linq;
using Examine;
-using Umbraco.Core;
+using Examine.LuceneEngine.Providers;
using Umbraco.Core.Models.PublishedContent;
+using Umbraco.Examine;
using Umbraco.Web.PublishedCache;
namespace Umbraco.Web
{
///
- /// Extension methods for Examine
+ /// Extension methods for Examine.
///
public static class ExamineExtensions
{
+ ///
+ /// Creates an containing all content from the .
+ ///
+ /// The search results.
+ /// The cache to fetch the content from.
+ ///
+ /// An containing all content.
+ ///
+ /// cache
+ ///
+ /// Search results are skipped if it can't be fetched from the by its integer id.
+ ///
public static IEnumerable ToPublishedSearchResults(this IEnumerable results, IPublishedCache cache)
{
- var list = new List();
+ if (cache == null) throw new ArgumentNullException(nameof(cache));
- foreach (var result in results.OrderByDescending(x => x.Score))
+ var publishedSearchResults = new List();
+
+ foreach (var result in results)
{
- if (!int.TryParse(result.Id, out var intId)) continue; //invalid
- var content = cache.GetById(intId);
- if (content == null) continue; // skip if this doesn't exist in the cache
-
- list.Add(new PublishedSearchResult(content, result.Score));
-
+ if (int.TryParse(result.Id, out var contentId) &&
+ cache.GetById(contentId) is IPublishedContent content)
+ {
+ publishedSearchResults.Add(new PublishedSearchResult(content, result.Score));
+ }
}
- return list;
+ return publishedSearchResults;
+ }
+
+ ///
+ /// Creates an containing all content, media or members from the .
+ ///
+ /// The search results.
+ /// The snapshot.
+ ///
+ /// An containing all content, media or members.
+ ///
+ /// snapshot
+ ///
+ /// Search results are skipped if it can't be fetched from the respective cache by its integer id.
+ ///
+ public static IEnumerable ToPublishedSearchResults(this IEnumerable results, IPublishedSnapshot snapshot)
+ {
+ if (snapshot == null) throw new ArgumentNullException(nameof(snapshot));
+
+ var publishedSearchResults = new List();
+
+ foreach (var result in results)
+ {
+ if (int.TryParse(result.Id, out var contentId) &&
+ result.Values.TryGetValue(LuceneIndex.CategoryFieldName, out var indexType))
+ {
+ IPublishedContent content;
+ switch (indexType)
+ {
+ case IndexTypes.Content:
+ content = snapshot.Content.GetById(contentId);
+ break;
+ case IndexTypes.Media:
+ content = snapshot.Media.GetById(contentId);
+ break;
+ case IndexTypes.Member:
+ content = snapshot.Members.GetById(contentId);
+ break;
+ default:
+ continue;
+ }
+
+ if (content != null)
+ {
+ publishedSearchResults.Add(new PublishedSearchResult(content, result.Score));
+ }
+ }
+ }
+
+ return publishedSearchResults;
}
}
}
diff --git a/src/Umbraco.Web/IPublishedContentQuery.cs b/src/Umbraco.Web/IPublishedContentQuery.cs
index 8a8d678aba..7066475dc9 100644
--- a/src/Umbraco.Web/IPublishedContentQuery.cs
+++ b/src/Umbraco.Web/IPublishedContentQuery.cs
@@ -35,52 +35,63 @@ namespace Umbraco.Web
///
/// Searches content.
///
- /// Term to search.
- /// Optional culture.
- /// Optional index name.
+ /// The term to search.
+ /// The culture (defaults to a culture insensitive search).
+ /// The name of the index to search (defaults to ).
+ ///
+ /// The search results.
+ ///
///
///
- /// When the is not specified or is *, all cultures are searched.
+ /// 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, string culture = "*", string indexName = null);
+ IEnumerable Search(string term, string culture = "*", string indexName = Constants.UmbracoIndexes.ExternalIndexName);
///
/// Searches content.
///
- /// Term to search.
- /// Numbers of items to skip.
- /// Numbers of items to return.
- /// Total number of matching items.
- /// Optional culture.
- /// Optional index name.
+ /// 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 search results.
+ ///
///
///
- /// When the is not specified or is *, all cultures are searched.
+ /// 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 = null);
+ IEnumerable Search(string term, int skip, int take, out long totalRecords, string culture = "*", string indexName = Constants.UmbracoIndexes.ExternalIndexName);
///
- /// Executes the query and converts the results to PublishedSearchResult.
+ /// Executes the query and converts the results to .
///
- ///
- /// While enumerating results, the ambient culture is changed to be the searched culture.
- ///
+ /// The query.
+ ///
+ /// The search results.
+ ///
IEnumerable Search(IQueryExecutor query);
///
- /// Executes the query and converts the results to PublishedSearchResult.
+ /// Executes the query and converts the results to .
///
- ///
- /// While enumerating results, the ambient culture is changed to be the searched culture.
- ///
+ /// The query.
+ /// The amount of results to skip.
+ /// The amount of results to take/return.
+ /// The total amount of records.
+ ///
+ /// The search results.
+ ///
IEnumerable Search(IQueryExecutor query, int skip, int take, out long totalRecords);
}
}
diff --git a/src/Umbraco.Web/PublishedContentQuery.cs b/src/Umbraco.Web/PublishedContentQuery.cs
index 2dbe4de4c5..d697898f33 100644
--- a/src/Umbraco.Web/PublishedContentQuery.cs
+++ b/src/Umbraco.Web/PublishedContentQuery.cs
@@ -183,54 +183,62 @@ namespace Umbraco.Web
#region Search
///
- public IEnumerable Search(string term, string culture = "*", string indexName = null)
+ public IEnumerable Search(string term, string culture = "*", string indexName = Constants.UmbracoIndexes.ExternalIndexName)
{
return Search(term, 0, 0, out _, culture, indexName);
}
///
- public IEnumerable Search(string term, int skip, int take, out long totalRecords, string culture = "*", string indexName = null)
+ public IEnumerable Search(string term, int skip, int take, out long totalRecords, string culture = "*", string indexName = Constants.UmbracoIndexes.ExternalIndexName)
{
- indexName = string.IsNullOrEmpty(indexName)
- ? Constants.UmbracoIndexes.ExternalIndexName
- : indexName;
+ if (skip < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(skip), skip, "The value must be greater than or equal to zero.");
+ }
+
+ if (take < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(take), take, "The value must be greater than or equal to zero.");
+ }
+
+ if (string.IsNullOrEmpty(indexName))
+ {
+ indexName = Constants.UmbracoIndexes.ExternalIndexName;
+ }
if (!_examineManager.TryGetIndex(indexName, out var index) || !(index is IUmbracoIndex umbIndex))
+ {
throw new InvalidOperationException($"No index found by name {indexName} or is not of type {typeof(IUmbracoIndex)}");
+ }
- var searcher = umbIndex.GetSearcher();
+ var query = umbIndex.GetSearcher().CreateQuery(IndexTypes.Content);
- // default to max 500 results
- var count = skip == 0 && take == 0 ? 500 : skip + take;
-
- ISearchResults results;
+ IQueryExecutor queryExecutor;
if (culture == "*")
{
- //search everything
-
- results = searcher.Search(term, count);
+ // Search everything
+ queryExecutor = query.ManagedQuery(term);
}
- else if (culture.IsNullOrWhiteSpace())
+ else if (string.IsNullOrWhiteSpace(culture))
{
- //only search invariant
-
- var qry = searcher.CreateQuery().Field(UmbracoContentIndex.VariesByCultureFieldName, "n"); //must not vary by culture
- qry = qry.And().ManagedQuery(term);
- results = qry.Execute(count);
+ // Only search invariant
+ queryExecutor = query.Field(UmbracoContentIndex.VariesByCultureFieldName, "n") // Must not vary by culture
+ .And().ManagedQuery(term);
}
else
{
- //search only the specified culture
-
- //get all index fields suffixed with the culture name supplied
- var cultureFields = umbIndex.GetCultureAndInvariantFields(culture).ToArray();
- var qry = searcher.CreateQuery().ManagedQuery(term, cultureFields);
- results = qry.Execute(count);
+ // Only search the specified culture
+ var fields = umbIndex.GetCultureAndInvariantFields(culture).ToArray(); // Get all index fields suffixed with the culture name supplied
+ queryExecutor = query.ManagedQuery(term, fields);
}
+ var results = skip == 0 && take == 0
+ ? queryExecutor.Execute()
+ : queryExecutor.Execute(skip + take);
+
totalRecords = results.TotalItemCount;
- return new CultureContextualSearchResults(results.ToPublishedSearchResults(_publishedSnapshot.Content), _variationContextAccessor, culture);
+ return new CultureContextualSearchResults(results.Skip(skip).ToPublishedSearchResults(_publishedSnapshot.Content), _variationContextAccessor, culture);
}
///
@@ -242,12 +250,23 @@ namespace Umbraco.Web
///
public IEnumerable Search(IQueryExecutor query, int skip, int take, out long totalRecords)
{
+ if (skip < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(skip), skip, "The value must be greater than or equal to zero.");
+ }
+
+ if (take < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(take), take, "The value must be greater than or equal to zero.");
+ }
+
var results = skip == 0 && take == 0
? query.Execute()
- : query.Execute(maxResults: skip + take);
+ : query.Execute(skip + take);
totalRecords = results.TotalItemCount;
- return results.ToPublishedSearchResults(_publishedSnapshot.Content);
+
+ return results.Skip(skip).ToPublishedSearchResults(_publishedSnapshot);
}
///
@@ -320,9 +339,6 @@ namespace Umbraco.Web
}
}
-
-
-
#endregion
}
}
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 5d29e53d4a..caf91152fe 100755
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -63,7 +63,7 @@
-
+
2.7.0.100
@@ -1279,4 +1279,4 @@
-
+
\ No newline at end of file