Merge branch 'ronaldbarendse-v8/bugfix/contentquery-search' into v8/dev
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
<dependency id="ClientDependency" version="[1.9.8,1.999999)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.9.3,1.999999)" />
|
||||
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.999999)" />
|
||||
<dependency id="Examine" version="[1.0.1,1.999999)" />
|
||||
<dependency id="Examine" version="[1.0.2,1.999999)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.8.14,1.999999)" />
|
||||
<dependency id="ImageProcessor" version="[2.7.0.100,2.999999)" />
|
||||
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- note: NuGet deals with transitive references now -->
|
||||
<PackageReference Include="Examine" Version="1.0.1" />
|
||||
<PackageReference Include="Examine" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub">
|
||||
<Version>1.0.0-beta2-19324-01</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
@@ -112,4 +112,4 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -79,7 +79,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Castle.Core" Version="4.3.1" />
|
||||
<PackageReference Include="Examine" Version="1.0.1" />
|
||||
<PackageReference Include="Examine" Version="1.0.2" />
|
||||
<PackageReference Include="HtmlAgilityPack">
|
||||
<Version>1.8.14</Version>
|
||||
</PackageReference>
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
<PackageReference Include="CSharpTest.Net.Collections" Version="14.906.1403.1082" />
|
||||
<PackageReference Include="ClientDependency" Version="1.9.8" />
|
||||
<PackageReference Include="ClientDependency-Mvc5" Version="1.9.3" />
|
||||
<PackageReference Include="Examine" Version="1.0.1" />
|
||||
<PackageReference Include="Examine" Version="1.0.2" />
|
||||
<PackageReference Include="ImageProcessor.Web" Version="4.10.0.100" />
|
||||
<PackageReference Include="ImageProcessor.Web.Config" Version="2.5.0.100" />
|
||||
<PackageReference Include="Microsoft.AspNet.Identity.Owin" Version="2.2.2" />
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for Examine
|
||||
/// Extension methods for Examine.
|
||||
/// </summary>
|
||||
public static class ExamineExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IEnumerable{PublishedSearchResult}" /> containing all content from the <paramref name="cache" />.
|
||||
/// </summary>
|
||||
/// <param name="results">The search results.</param>
|
||||
/// <param name="cache">The cache to fetch the content from.</param>
|
||||
/// <returns>
|
||||
/// An <see cref="IEnumerable{PublishedSearchResult}" /> containing all content.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">cache</exception>
|
||||
/// <remarks>
|
||||
/// Search results are skipped if it can't be fetched from the <paramref name="cache" /> by its integer id.
|
||||
/// </remarks>
|
||||
public static IEnumerable<PublishedSearchResult> ToPublishedSearchResults(this IEnumerable<ISearchResult> results, IPublishedCache cache)
|
||||
{
|
||||
var list = new List<PublishedSearchResult>();
|
||||
if (cache == null) throw new ArgumentNullException(nameof(cache));
|
||||
|
||||
foreach (var result in results.OrderByDescending(x => x.Score))
|
||||
var publishedSearchResults = new List<PublishedSearchResult>();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IEnumerable{PublishedSearchResult}" /> containing all content, media or members from the <paramref name="snapshot" />.
|
||||
/// </summary>
|
||||
/// <param name="results">The search results.</param>
|
||||
/// <param name="snapshot">The snapshot.</param>
|
||||
/// <returns>
|
||||
/// An <see cref="IEnumerable{PublishedSearchResult}" /> containing all content, media or members.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">snapshot</exception>
|
||||
/// <remarks>
|
||||
/// Search results are skipped if it can't be fetched from the respective cache by its integer id.
|
||||
/// </remarks>
|
||||
public static IEnumerable<PublishedSearchResult> ToPublishedSearchResults(this IEnumerable<ISearchResult> results, IPublishedSnapshot snapshot)
|
||||
{
|
||||
if (snapshot == null) throw new ArgumentNullException(nameof(snapshot));
|
||||
|
||||
var publishedSearchResults = new List<PublishedSearchResult>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,52 +35,63 @@ namespace Umbraco.Web
|
||||
/// <summary>
|
||||
/// Searches content.
|
||||
/// </summary>
|
||||
/// <param name="term">Term to search.</param>
|
||||
/// <param name="culture">Optional culture.</param>
|
||||
/// <param name="indexName">Optional index name.</param>
|
||||
/// <param name="term">The term to search.</param>
|
||||
/// <param name="culture">The culture (defaults to a culture insensitive search).</param>
|
||||
/// <param name="indexName">The name of the index to search (defaults to <see cref="Constants.UmbracoIndexes.ExternalIndexName" />).</param>
|
||||
/// <returns>
|
||||
/// The search results.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// When the <paramref name="culture"/> is not specified or is *, all cultures are searched.
|
||||
/// When the <paramref name="culture" /> 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.
|
||||
/// </para>
|
||||
/// <para>While enumerating results, the ambient culture is changed to be the searched culture.</para>
|
||||
/// </remarks>
|
||||
IEnumerable<PublishedSearchResult> Search(string term, string culture = "*", string indexName = null);
|
||||
IEnumerable<PublishedSearchResult> Search(string term, string culture = "*", string indexName = Constants.UmbracoIndexes.ExternalIndexName);
|
||||
|
||||
/// <summary>
|
||||
/// Searches content.
|
||||
/// </summary>
|
||||
/// <param name="term">Term to search.</param>
|
||||
/// <param name="skip">Numbers of items to skip.</param>
|
||||
/// <param name="take">Numbers of items to return.</param>
|
||||
/// <param name="totalRecords">Total number of matching items.</param>
|
||||
/// <param name="culture">Optional culture.</param>
|
||||
/// <param name="indexName">Optional index name.</param>
|
||||
/// <param name="term">The term to search.</param>
|
||||
/// <param name="skip">The amount of results to skip.</param>
|
||||
/// <param name="take">The amount of results to take/return.</param>
|
||||
/// <param name="totalRecords">The total amount of records.</param>
|
||||
/// <param name="culture">The culture (defaults to a culture insensitive search).</param>
|
||||
/// <param name="indexName">The name of the index to search (defaults to <see cref="Constants.UmbracoIndexes.ExternalIndexName" />).</param>
|
||||
/// <returns>
|
||||
/// The search results.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// When the <paramref name="culture"/> is not specified or is *, all cultures are searched.
|
||||
/// When the <paramref name="culture" /> 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.
|
||||
/// </para>
|
||||
/// <para>While enumerating results, the ambient culture is changed to be the searched culture.</para>
|
||||
/// </remarks>
|
||||
IEnumerable<PublishedSearchResult> Search(string term, int skip, int take, out long totalRecords, string culture = "*", string indexName = null);
|
||||
IEnumerable<PublishedSearchResult> Search(string term, int skip, int take, out long totalRecords, string culture = "*", string indexName = Constants.UmbracoIndexes.ExternalIndexName);
|
||||
|
||||
/// <summary>
|
||||
/// Executes the query and converts the results to PublishedSearchResult.
|
||||
/// Executes the query and converts the results to <see cref="PublishedSearchResult" />.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>While enumerating results, the ambient culture is changed to be the searched culture.</para>
|
||||
/// </remarks>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>
|
||||
/// The search results.
|
||||
/// </returns>
|
||||
IEnumerable<PublishedSearchResult> Search(IQueryExecutor query);
|
||||
|
||||
/// <summary>
|
||||
/// Executes the query and converts the results to PublishedSearchResult.
|
||||
/// Executes the query and converts the results to <see cref="PublishedSearchResult" />.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>While enumerating results, the ambient culture is changed to be the searched culture.</para>
|
||||
/// </remarks>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="skip">The amount of results to skip.</param>
|
||||
/// <param name="take">The amount of results to take/return.</param>
|
||||
/// <param name="totalRecords">The total amount of records.</param>
|
||||
/// <returns>
|
||||
/// The search results.
|
||||
/// </returns>
|
||||
IEnumerable<PublishedSearchResult> Search(IQueryExecutor query, int skip, int take, out long totalRecords);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,54 +183,62 @@ namespace Umbraco.Web
|
||||
#region Search
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PublishedSearchResult> Search(string term, string culture = "*", string indexName = null)
|
||||
public IEnumerable<PublishedSearchResult> Search(string term, string culture = "*", string indexName = Constants.UmbracoIndexes.ExternalIndexName)
|
||||
{
|
||||
return Search(term, 0, 0, out _, culture, indexName);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PublishedSearchResult> Search(string term, int skip, int take, out long totalRecords, string culture = "*", string indexName = null)
|
||||
public IEnumerable<PublishedSearchResult> 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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -242,12 +250,23 @@ namespace Umbraco.Web
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PublishedSearchResult> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -320,9 +339,6 @@ namespace Umbraco.Web
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ClientDependency" Version="1.9.8" />
|
||||
<PackageReference Include="CSharpTest.Net.Collections" Version="14.906.1403.1082" />
|
||||
<PackageReference Include="Examine" Version="1.0.1" />
|
||||
<PackageReference Include="Examine" Version="1.0.2" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.8.14" />
|
||||
<PackageReference Include="ImageProcessor">
|
||||
<Version>2.7.0.100</Version>
|
||||
@@ -1279,4 +1279,4 @@
|
||||
<Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly" />
|
||||
</SGen>
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user