Merge branch 'temp8-contentquery-search-culture-3828' into temp8

This commit is contained in:
Stephan
2018-12-21 09:00:13 +01:00
35 changed files with 344 additions and 405 deletions
+2 -3
View File
@@ -14,7 +14,7 @@
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependencies>
<!--
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
@@ -25,8 +25,7 @@
<dependency id="ClientDependency" version="[1.9.7,1.999999)" />
<dependency id="ClientDependency-Mvc5" version="[1.8.0,1.999999)" />
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.999999)" />
<dependency id="Examine" version="[1.0.0-beta046,1.999999)" />
<dependency id="Lucene.Net.Contrib" version="[3.0.3,3.999999)" />
<dependency id="Examine" version="[1.0.0-beta067,1.999999)" />
<dependency id="HtmlAgilityPack" version="[1.8.9,1.999999)" />
<dependency id="ImageProcessor" version="[2.6.2.25,2.999999)" />
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
+2
View File
@@ -618,6 +618,8 @@ namespace Umbraco.Core.Composing
// doesn't actualy load in all assemblies, only the types that have been referenced so far.
// However, in a web context, the BuildManager will have executed which will force all assemblies
// to be loaded so it's fine for now.
// It could be fairly easy to parse the typeName to get the assembly name and then do Assembly.Load and
// find the type from there.
//now try fall back procedures.
type = Type.GetType(typeName);
+1 -4
View File
@@ -15,7 +15,7 @@ namespace Umbraco.Examine
/// <summary>
/// Performs the data lookups required to rebuild a content index
/// </summary>
public class ContentIndexPopulator : IndexPopulator
public class ContentIndexPopulator : IndexPopulator<UmbracoContentIndex>
{
private readonly IContentService _contentService;
private readonly IValueSetBuilder<IContent> _contentValueSetBuilder;
@@ -56,9 +56,6 @@ namespace Umbraco.Examine
_publishedQuery = sqlContext.Query<IContent>().Where(x => x.Published);
_publishedValuesOnly = publishedValuesOnly;
_parentId = parentId;
RegisterIndex(Constants.UmbracoIndexes.InternalIndexName);
RegisterIndex(Constants.UmbracoIndexes.ExternalIndexName);
}
protected override void PopulateIndexes(IEnumerable<IIndex> indexes)
+6 -4
View File
@@ -3,12 +3,14 @@ using Examine;
namespace Umbraco.Examine
{
public interface IIndexPopulator
{
bool IsRegistered(string indexName);
void RegisterIndex(string indexName);
/// <summary>
/// If this index is registered with this populatr
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
bool IsRegistered(IIndex index);
/// <summary>
/// Populate indexers
@@ -1,11 +1,12 @@
using Examine;
using System.Collections.Generic;
using Examine;
namespace Umbraco.Examine
{
/// <summary>
/// A Marker interface for defining an Umbraco indexer
/// </summary>
public interface IUmbracoIndexer : IIndex
public interface IUmbracoIndex : IIndex
{
/// <summary>
/// When set to true Umbraco will keep the index in sync with Umbraco data automatically
@@ -21,5 +22,11 @@ namespace Umbraco.Examine
/// * non-published Variants
/// </remarks>
bool PublishedValuesOnly { get; }
/// <summary>
/// Returns a list of all indexed fields
/// </summary>
/// <returns></returns>
IEnumerable<string> GetFields();
}
}
+16 -3
View File
@@ -5,13 +5,26 @@ using Umbraco.Core.Collections;
namespace Umbraco.Examine
{
/// <summary>
/// An <see cref="IIndexPopulator"/> that is automatically associated to any index of type <see cref="TIndex"/>
/// </summary>
/// <typeparam name="TIndex"></typeparam>
public abstract class IndexPopulator<TIndex> : IndexPopulator where TIndex : IIndex
{
public override bool IsRegistered(IIndex index)
{
if (base.IsRegistered(index)) return true;
return index is TIndex;
}
}
public abstract class IndexPopulator : IIndexPopulator
{
private readonly ConcurrentHashSet<string> _registeredIndexes = new ConcurrentHashSet<string>();
public bool IsRegistered(string indexName)
public virtual bool IsRegistered(IIndex index)
{
return _registeredIndexes.Contains(indexName);
return _registeredIndexes.Contains(index.Name);
}
/// <summary>
@@ -25,7 +38,7 @@ namespace Umbraco.Examine
public void Populate(params IIndex[] indexes)
{
PopulateIndexes(indexes.Where(x => IsRegistered(x.Name)));
PopulateIndexes(indexes.Where(IsRegistered));
}
protected abstract void PopulateIndexes(IEnumerable<IIndex> indexes);
+2 -2
View File
@@ -20,9 +20,9 @@ namespace Umbraco.Examine
ExamineManager = examineManager;
}
public bool CanRebuild(string indexName)
public bool CanRebuild(IIndex index)
{
return _populators.Any(x => x.IsRegistered(indexName));
return _populators.Any(x => x.IsRegistered(index));
}
public void RebuildIndex(string indexName)
+26 -7
View File
@@ -1,8 +1,12 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using Examine;
using Examine.LuceneEngine.Directories;
using Lucene.Net.Store;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.IO;
namespace Umbraco.Examine
@@ -18,17 +22,30 @@ namespace Umbraco.Examine
/// <summary>
/// Creates a file system based Lucene <see cref="Lucene.Net.Store.Directory"/> with the correct locking guidelines for Umbraco
/// </summary>
/// <param name="name"></param>
/// <param name="folderName">
/// The folder name to store the index (single word, not a fully qualified folder) (i.e. Internal)
/// </param>
/// <returns></returns>
public virtual Lucene.Net.Store.Directory CreateFileSystemLuceneDirectory(string name)
public virtual Lucene.Net.Store.Directory CreateFileSystemLuceneDirectory(string folderName)
{
//TODO: We should have a single AppSetting to be able to specify a default DirectoryFactory so we can have a single
//setting to configure all indexes that use this to easily swap the directory to Sync/%temp%/blog, etc...
var dirInfo = new DirectoryInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.Data), "TEMP", "ExamineIndexes", name));
var dirInfo = new DirectoryInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.Data), "TEMP", "ExamineIndexes", folderName));
if (!dirInfo.Exists)
System.IO.Directory.CreateDirectory(dirInfo.FullName);
//check if there's a configured directory factory, if so create it and use that to create the lucene dir
var configuredDirectoryFactory = ConfigurationManager.AppSettings["Umbraco.Examine.LuceneDirectoryFactory"];
if (!configuredDirectoryFactory.IsNullOrWhiteSpace())
{
//this should be a fully qualified type
var factoryType = TypeFinder.GetTypeByName(configuredDirectoryFactory);
if (factoryType == null) throw new NullReferenceException("No directory type found for value: " + configuredDirectoryFactory);
var directoryFactory = (IDirectoryFactory)Activator.CreateInstance(factoryType);
return directoryFactory.CreateDirectory(dirInfo);
}
//no dir factory, just create a normal fs directory
var luceneDir = new SimpleFSDirectory(dirInfo);
//we want to tell examine to use a different fs lock instead of the default NativeFSFileLock which could cause problems if the appdomain
@@ -38,6 +55,8 @@ namespace Umbraco.Examine
// however, we are setting the DefaultLockFactory in startup so we'll use that instead since it can be managed globally.
luceneDir.SetLockFactory(DirectoryFactory.DefaultLockFactory(dirInfo));
return luceneDir;
}
}
}
+1 -4
View File
@@ -10,7 +10,7 @@ namespace Umbraco.Examine
/// <summary>
/// Performs the data lookups required to rebuild a media index
/// </summary>
public class MediaIndexPopulator : IndexPopulator
public class MediaIndexPopulator : IndexPopulator<UmbracoContentIndex>
{
private readonly int? _parentId;
private readonly IMediaService _mediaService;
@@ -37,9 +37,6 @@ namespace Umbraco.Examine
_parentId = parentId;
_mediaService = mediaService;
_mediaValueSetBuilder = mediaValueSetBuilder;
RegisterIndex(Constants.UmbracoIndexes.InternalIndexName);
RegisterIndex(Constants.UmbracoIndexes.ExternalIndexName);
}
protected override void PopulateIndexes(IEnumerable<IIndex> indexes)
+1 -3
View File
@@ -7,7 +7,7 @@ using Umbraco.Core.Services;
namespace Umbraco.Examine
{
public class MemberIndexPopulator : IndexPopulator
public class MemberIndexPopulator : IndexPopulator<UmbracoMemberIndex>
{
private readonly IMemberService _memberService;
private readonly IValueSetBuilder<IMember> _valueSetBuilder;
@@ -16,8 +16,6 @@ namespace Umbraco.Examine
{
_memberService = memberService;
_valueSetBuilder = valueSetBuilder;
RegisterIndex(Core.Constants.UmbracoIndexes.MembersIndexName);
}
protected override void PopulateIndexes(IEnumerable<IIndex> indexes)
{
+3 -3
View File
@@ -48,7 +48,7 @@
</ItemGroup>
<ItemGroup>
<!-- note: NuGet deals with transitive references now -->
<PackageReference Include="Examine" Version="1.0.0-beta046" />
<PackageReference Include="Examine" Version="1.0.0-beta067" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="NPoco" Version="3.9.4" />
</ItemGroup>
@@ -72,7 +72,7 @@
<Compile Include="IndexPopulator.cs" />
<Compile Include="IndexRebuilder.cs" />
<Compile Include="IPublishedContentValueSetBuilder.cs" />
<Compile Include="IUmbracoIndexer.cs" />
<Compile Include="IUmbracoIndex.cs" />
<Compile Include="IValueSetBuilder.cs" />
<Compile Include="MediaIndexPopulator.cs" />
<Compile Include="MediaValueSetBuilder.cs" />
@@ -88,8 +88,8 @@
<Compile Include="ContentValueSetValidator.cs" />
<Compile Include="UmbracoExamineIndexDiagnostics.cs" />
<Compile Include="UmbracoExamineIndex.cs" />
<Compile Include="UmbracoExamineSearcher.cs" />
<Compile Include="LuceneIndexCreator.cs" />
<Compile Include="UmbracoFieldDefinitionCollection.cs" />
<Compile Include="UmbracoMemberIndex.cs" />
<Compile Include="..\SolutionInfo.cs">
<Link>Properties\SolutionInfo.cs</Link>
+7 -31
View File
@@ -52,13 +52,13 @@ namespace Umbraco.Examine
/// <param name="indexValueTypes"></param>
public UmbracoContentIndex(
string name,
IEnumerable<FieldDefinition> fieldDefinitions,
FieldDefinitionCollection fieldDefinitions,
Directory luceneDirectory,
Analyzer defaultAnalyzer,
ProfilingLogger profilingLogger,
ILocalizationService languageService,
IContentValueSetValidator validator,
IReadOnlyDictionary<string, Func<string, IIndexValueType>> indexValueTypes = null)
IReadOnlyDictionary<string, IFieldValueTypeFactory> indexValueTypes = null)
: base(name, fieldDefinitions, luceneDirectory, defaultAnalyzer, profilingLogger, validator, indexValueTypes)
{
if (validator == null) throw new ArgumentNullException(nameof(validator));
@@ -122,7 +122,7 @@ namespace Umbraco.Examine
//anywhere else in this class
Current.Services.PublicAccessService,
parentId,
ConfigIndexCriteria.IncludeItemTypes, ConfigIndexCriteria.ExcludeItemTypes);
ConfigIndexCriteria?.IncludeItemTypes, ConfigIndexCriteria?.ExcludeItemTypes);
PublishedValuesOnly = supportUnpublished;
}
@@ -200,41 +200,17 @@ namespace Umbraco.Examine
var descendantPath = $@"\-1\,*{nodeId}\,*";
var rawQuery = $"{IndexPathFieldName}:{descendantPath}";
var searcher = GetSearcher();
var c = searcher.CreateCriteria();
var filtered = c.RawQuery(rawQuery);
var results = searcher.Search(filtered);
var c = searcher.CreateQuery();
var filtered = c.NativeQuery(rawQuery);
var results = filtered.Execute();
ProfilingLogger.Logger.Debug(GetType(), "DeleteFromIndex with query: {Query} (found {TotalItems} results)", rawQuery, results.TotalItemCount);
//need to queue a delete item for each one found
foreach (var r in results)
{
QueueIndexOperation(new IndexOperation(new ValueSet(r.Id), IndexOperationType.Delete));
}
QueueIndexOperation(results.Select(r => new IndexOperation(new ValueSet(r.Id), IndexOperationType.Delete)));
base.PerformDeleteFromIndex(nodeId, onComplete);
}
/// <summary>
/// Overridden to ensure that the variant system fields have the right value types
/// </summary>
/// <param name="x"></param>
/// <param name="indexValueTypesFactory"></param>
/// <returns></returns>
protected override FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictionary<string, Func<string, IIndexValueType>> indexValueTypesFactory = null)
{
//fixme: languages are dynamic so although this will work on startup it wont work when languages are edited
foreach(var lang in LanguageService.GetAllLanguages())
{
foreach (var field in UmbracoIndexFieldDefinitions)
{
var def = new FieldDefinition($"{field.Name}_{lang.IsoCode.ToLowerInvariant()}", field.Type);
FieldDefinitionCollection.TryAdd(def.Name, def);
}
}
return base.CreateFieldValueTypes(indexValueTypesFactory);
}
}
}
@@ -1,10 +1,6 @@
using System;
using System.ComponentModel;
using System.Web;
using Examine.LuceneEngine.SearchCriteria;
using Examine.SearchCriteria;
using Examine.LuceneEngine.Search;
using Examine.Search;
using Umbraco.Core;
using Umbraco.Examine.Config;
namespace Umbraco.Examine
{
+34 -80
View File
@@ -20,10 +20,9 @@ namespace Umbraco.Examine
{
/// <summary>
/// An abstract provider containing the basic functionality to be able to query against
/// Umbraco data.
/// An abstract provider containing the basic functionality to be able to query against Umbraco data.
/// </summary>
public abstract class UmbracoExamineIndex : LuceneIndex, IUmbracoIndexer, IIndexDiagnostics
public abstract class UmbracoExamineIndex : LuceneIndex, IUmbracoIndex, IIndexDiagnostics
{
// note
// wrapping all operations that end up calling base.SafelyProcessQueueItems in a safe call
@@ -53,6 +52,7 @@ namespace Umbraco.Examine
{
ProfilingLogger = Current.ProfilingLogger;
_configBased = true;
_diagnostics = new UmbracoExamineIndexDiagnostics(this, ProfilingLogger.Logger);
}
/// <summary>
@@ -67,12 +67,12 @@ namespace Umbraco.Examine
/// <param name="indexValueTypes"></param>
protected UmbracoExamineIndex(
string name,
IEnumerable<FieldDefinition> fieldDefinitions,
FieldDefinitionCollection fieldDefinitions,
Directory luceneDirectory,
Analyzer defaultAnalyzer,
ProfilingLogger profilingLogger,
IValueSetValidator validator = null,
IReadOnlyDictionary<string, Func<string, IIndexValueType>> indexValueTypes = null)
IReadOnlyDictionary<string, IFieldValueTypeFactory> indexValueTypes = null)
: base(name, fieldDefinitions, luceneDirectory, defaultAnalyzer, validator, indexValueTypes)
{
ProfilingLogger = profilingLogger ?? throw new ArgumentNullException(nameof(profilingLogger));
@@ -86,60 +86,10 @@ namespace Umbraco.Examine
private readonly bool _configBased = false;
/// <summary>
/// A type that defines the type of index for each Umbraco field (non user defined fields)
/// Alot of standard umbraco fields shouldn't be tokenized or even indexed, just stored into lucene
/// for retreival after searching.
/// </summary>
public static readonly FieldDefinition[] UmbracoIndexFieldDefinitions =
{
new FieldDefinition("parentID", FieldDefinitionTypes.Integer),
new FieldDefinition("level", FieldDefinitionTypes.Integer),
new FieldDefinition("writerID", FieldDefinitionTypes.Integer),
new FieldDefinition("creatorID", FieldDefinitionTypes.Integer),
new FieldDefinition("sortOrder", FieldDefinitionTypes.Integer),
new FieldDefinition("template", FieldDefinitionTypes.Integer),
new FieldDefinition("createDate", FieldDefinitionTypes.DateTime),
new FieldDefinition("updateDate", FieldDefinitionTypes.DateTime),
new FieldDefinition("key", FieldDefinitionTypes.InvariantCultureIgnoreCase),
new FieldDefinition("version", FieldDefinitionTypes.Raw),
new FieldDefinition("nodeType", FieldDefinitionTypes.InvariantCultureIgnoreCase),
new FieldDefinition("template", FieldDefinitionTypes.Raw),
new FieldDefinition("urlName", FieldDefinitionTypes.InvariantCultureIgnoreCase),
new FieldDefinition("path", FieldDefinitionTypes.Raw),
new FieldDefinition("email", FieldDefinitionTypes.EmailAddress),
new FieldDefinition(PublishedFieldName, FieldDefinitionTypes.Raw),
new FieldDefinition(NodeKeyFieldName, FieldDefinitionTypes.Raw),
new FieldDefinition(IndexPathFieldName, FieldDefinitionTypes.Raw),
new FieldDefinition(IconFieldName, FieldDefinitionTypes.Raw)
};
protected ProfilingLogger ProfilingLogger { get; }
/// <summary>
/// Overridden to ensure that the umbraco system field definitions are in place
/// </summary>
/// <param name="indexValueTypesFactory"></param>
/// <returns></returns>
protected override FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictionary<string, Func<string, IIndexValueType>> indexValueTypesFactory = null)
{
//if config based then ensure the value types else it's assumed these were passed in via ctor
if (_configBased)
{
foreach (var field in UmbracoIndexFieldDefinitions)
{
FieldDefinitionCollection.TryAdd(field.Name, field);
}
}
return base.CreateFieldValueTypes(indexValueTypesFactory);
}
/// <summary>
/// When set to true Umbraco will keep the index in sync with Umbraco data automatically
/// </summary>
@@ -147,6 +97,14 @@ namespace Umbraco.Examine
public bool PublishedValuesOnly { get; protected set; } = false;
/// <inheritdoc />
public IEnumerable<string> GetFields()
{
//we know this is a LuceneSearcher
var searcher = (LuceneSearcher) GetSearcher();
return searcher.GetAllIndexedFields();
}
protected ConfigIndexCriteria ConfigIndexCriteria { get; private set; }
/// <summary>
@@ -174,12 +132,15 @@ namespace Umbraco.Examine
EnableDefaultEventHandler = enabled;
}
//Need to check if the index set or IndexerData is specified...
if (config["indexSet"] == null && FieldDefinitionCollection.Count == 0)
//this is config based, so add the default definitions
foreach (var field in UmbracoFieldDefinitionCollection.UmbracoIndexFieldDefinitions)
{
//if we don't have either, then we'll try to set the index set by naming conventions
var found = false;
FieldDefinitionCollection.TryAdd(field);
}
//Need to check if the index set is specified...
if (config["indexSet"] == null)
{
var possibleSuffixes = new[] {"Index", "Indexer"};
foreach (var suffix in possibleSuffixes)
{
@@ -200,36 +161,29 @@ namespace Umbraco.Examine
ConfigIndexCriteria = CreateFieldDefinitionsFromConfig(indexSet);
foreach (var fieldDefinition in ConfigIndexCriteria.StandardFields.Union(ConfigIndexCriteria.UserFields))
{
FieldDefinitionCollection.TryAdd(fieldDefinition.Name, fieldDefinition);
//replace any existing or add
FieldDefinitionCollection.AddOrUpdate(fieldDefinition);
}
found = true;
break;
}
if (!found)
throw new ArgumentNullException("indexSet on LuceneExamineIndexer provider has not been set in configuration and/or the IndexerData property has not been explicitly set");
}
else if (config["indexSet"] != null)
else
{
//if an index set is specified, ensure it exists and initialize the indexer based on the set
if (IndexSets.Instance.Sets[config["indexSet"]] == null)
{
throw new ArgumentException("The indexSet specified for the LuceneExamineIndexer provider does not exist");
}
else
IndexSetName = config["indexSet"];
var indexSet = IndexSets.Instance.Sets[IndexSetName];
//get the index criteria and ensure folder
ConfigIndexCriteria = CreateFieldDefinitionsFromConfig(indexSet);
foreach (var fieldDefinition in ConfigIndexCriteria.StandardFields.Union(ConfigIndexCriteria.UserFields))
{
IndexSetName = config["indexSet"];
var indexSet = IndexSets.Instance.Sets[IndexSetName];
//get the index criteria and ensure folder
ConfigIndexCriteria = CreateFieldDefinitionsFromConfig(indexSet);
foreach (var fieldDefinition in ConfigIndexCriteria.StandardFields.Union(ConfigIndexCriteria.UserFields))
{
FieldDefinitionCollection.TryAdd(fieldDefinition.Name, fieldDefinition);
}
//replace any existing or add
FieldDefinitionCollection.AddOrUpdate(fieldDefinition);
}
}
@@ -1,52 +0,0 @@
//using System;
//using System.ComponentModel;
//using System.IO;
//using System.Linq;
//using Umbraco.Core;
//using Examine.LuceneEngine.Providers;
//using Lucene.Net.Analysis;
//using Lucene.Net.Index;
//using Umbraco.Core.Composing;
//using Umbraco.Examine.Config;
//using Directory = Lucene.Net.Store.Directory;
//using Examine.LuceneEngine;
//namespace Umbraco.Examine
//{
// /// <summary>
// /// An Examine searcher which uses Lucene.Net as the
// /// </summary>
// public class UmbracoExamineSearcher : LuceneSearcher
// {
// /// <summary>
// /// Constructor to allow for creating an indexer at runtime
// /// </summary>
// /// <param name="name"></param>
// /// <param name="luceneDirectory"></param>
// /// <param name="analyzer"></param>
// public UmbracoExamineSearcher(string name, Directory luceneDirectory, Analyzer analyzer, FieldValueTypeCollection fieldValueTypeCollection)
// : base(name, luceneDirectory, analyzer, fieldValueTypeCollection)
// {
// }
// /// <inheritdoc />
// public UmbracoExamineSearcher(string name, IndexWriter writer, Analyzer analyzer, FieldValueTypeCollection fieldValueTypeCollection)
// : base(name, writer, analyzer, fieldValueTypeCollection)
// {
// }
// /// <summary>
// /// Returns a list of fields to search on, this will also exclude the IndexPathFieldName and node type alias
// /// </summary>
// /// <returns></returns>
// public override string[] GetAllIndexedFields()
// {
// var fields = base.GetAllIndexedFields();
// return fields
// .Where(x => x != UmbracoExamineIndexer.IndexPathFieldName)
// .Where(x => x != LuceneIndex.ItemTypeFieldName)
// .ToArray();
// }
// }
//}
@@ -0,0 +1,75 @@
using Examine;
namespace Umbraco.Examine
{
/// <summary>
/// Custom <see cref="FieldDefinitionCollection"/> allowing dynamic creation of <see cref="FieldDefinition"/>
/// </summary>
public class UmbracoFieldDefinitionCollection : FieldDefinitionCollection
{
public UmbracoFieldDefinitionCollection()
: base(UmbracoIndexFieldDefinitions)
{
}
/// <summary>
/// A type that defines the type of index for each Umbraco field (non user defined fields)
/// Alot of standard umbraco fields shouldn't be tokenized or even indexed, just stored into lucene
/// for retreival after searching.
/// </summary>
public static readonly FieldDefinition[] UmbracoIndexFieldDefinitions =
{
new FieldDefinition("parentID", FieldDefinitionTypes.Integer),
new FieldDefinition("level", FieldDefinitionTypes.Integer),
new FieldDefinition("writerID", FieldDefinitionTypes.Integer),
new FieldDefinition("creatorID", FieldDefinitionTypes.Integer),
new FieldDefinition("sortOrder", FieldDefinitionTypes.Integer),
new FieldDefinition("template", FieldDefinitionTypes.Integer),
new FieldDefinition("createDate", FieldDefinitionTypes.DateTime),
new FieldDefinition("updateDate", FieldDefinitionTypes.DateTime),
new FieldDefinition("key", FieldDefinitionTypes.InvariantCultureIgnoreCase),
new FieldDefinition("version", FieldDefinitionTypes.Raw),
new FieldDefinition("nodeType", FieldDefinitionTypes.InvariantCultureIgnoreCase),
new FieldDefinition("template", FieldDefinitionTypes.Raw),
new FieldDefinition("urlName", FieldDefinitionTypes.InvariantCultureIgnoreCase),
new FieldDefinition("path", FieldDefinitionTypes.Raw),
new FieldDefinition("email", FieldDefinitionTypes.EmailAddress),
new FieldDefinition(UmbracoExamineIndex.PublishedFieldName, FieldDefinitionTypes.Raw),
new FieldDefinition(UmbracoExamineIndex.NodeKeyFieldName, FieldDefinitionTypes.Raw),
new FieldDefinition(UmbracoExamineIndex.IndexPathFieldName, FieldDefinitionTypes.Raw),
new FieldDefinition(UmbracoExamineIndex.IconFieldName, FieldDefinitionTypes.Raw)
};
///// <summary>
///// Overridden to dynamically add field definitions for culture variations
///// </summary>
///// <param name="fieldName"></param>
///// <param name="fieldDefinition"></param>
///// <returns></returns>
//public override bool TryGetValue(string fieldName, out FieldDefinition fieldDefinition)
//{
// var result = base.TryGetValue(fieldName, out fieldDefinition);
// if (result) return true;
// //if the fieldName is not suffixed with _iso-Code
// var underscoreIndex = fieldName.LastIndexOf('_');
// if (underscoreIndex == -1) return false;
// var isoCode = fieldName.Substring(underscoreIndex);
// if (isoCode.Length < 6) return false; //invalid isoCode
// var hyphenIndex = isoCode.IndexOf('-');
// if (hyphenIndex != 3) return false; //invalid isoCode
// //we'll assume this is a valid isoCode
//}
}
}
+4 -4
View File
@@ -42,8 +42,8 @@ namespace Umbraco.Examine
/// <param name="validator"></param>
/// <param name="analyzer"></param>
public UmbracoMemberIndex(
string name,
IEnumerable<FieldDefinition> fieldDefinitions,
string name,
FieldDefinitionCollection fieldDefinitions,
Directory luceneDirectory,
Analyzer analyzer,
ProfilingLogger profilingLogger,
@@ -64,10 +64,10 @@ namespace Umbraco.Examine
/// </summary>
/// <param name="indexValueTypesFactory"></param>
/// <returns></returns>
protected override FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictionary<string, Func<string, IIndexValueType>> indexValueTypesFactory = null)
protected override FieldValueTypeCollection CreateFieldValueTypes(IReadOnlyDictionary<string, IFieldValueTypeFactory> indexValueTypesFactory = null)
{
var keyDef = new FieldDefinition("__key", FieldDefinitionTypes.Raw);
FieldDefinitionCollection.TryAdd(keyDef.Name, keyDef);
FieldDefinitionCollection.TryAdd(keyDef);
return base.CreateFieldValueTypes(indexValueTypesFactory);
}
@@ -173,9 +173,9 @@ namespace Umbraco.Tests.PublishedContent
//ensure it still exists in the index (raw examine search)
var criteria = searcher.CreateCriteria();
var criteria = searcher.CreateQuery();
var filter = criteria.Id(3113);
var found = searcher.Search(filter.Compile());
var found = filter.Execute();
Assert.IsNotNull(found);
Assert.AreEqual(1, found.TotalItemCount);
+1 -1
View File
@@ -77,7 +77,7 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="7.0.1" />
<PackageReference Include="Castle.Core" Version="4.2.1" />
<PackageReference Include="Examine" Version="1.0.0-beta046" />
<PackageReference Include="Examine" Version="1.0.0-beta067" />
<PackageReference Include="HtmlAgilityPack">
<Version>1.8.9</Version>
</PackageReference>
@@ -36,7 +36,7 @@ namespace Umbraco.Tests.UmbracoExamine
var valueSet = node.ConvertToValueSet(IndexTypes.Content);
indexer.IndexItems(new[] { valueSet });
var found = searcher.Search(searcher.CreateCriteria().Id((string)node.Attribute("id")).Compile());
var found = searcher.CreateQuery().Id((string)node.Attribute("id")).Execute();
Assert.AreEqual(0, found.TotalItemCount);
}
@@ -164,7 +164,7 @@ namespace Umbraco.Tests.UmbracoExamine
var i = new UmbracoContentIndex(
"testIndexer",
UmbracoExamineIndex.UmbracoIndexFieldDefinitions,
new UmbracoFieldDefinitionCollection(),
luceneDir,
analyzer,
profilingLogger,
+11 -14
View File
@@ -105,7 +105,7 @@ namespace Umbraco.Tests.UmbracoExamine
var searcher = indexer.GetSearcher();
var results = searcher.Search(searcher.CreateCriteria().Id(555).Compile());
var results = searcher.CreateQuery().Id(555).Execute();
Assert.AreEqual(1, results.TotalItemCount);
var result = results.First();
@@ -130,8 +130,6 @@ namespace Umbraco.Tests.UmbracoExamine
validator: new ContentValueSetValidator(false)))
using (indexer.ProcessNonAsync())
{
contentRebuilder.RegisterIndex(indexer.Name);
mediaRebuilder.RegisterIndex(indexer.Name);
var searcher = indexer.GetSearcher();
@@ -139,7 +137,7 @@ namespace Umbraco.Tests.UmbracoExamine
contentRebuilder.Populate(indexer);
mediaRebuilder.Populate(indexer);
var result = searcher.Search(searcher.CreateCriteria().All().Compile());
var result = searcher.CreateQuery().All().Execute();
Assert.AreEqual(29, result.TotalItemCount);
}
@@ -210,7 +208,7 @@ namespace Umbraco.Tests.UmbracoExamine
indexer.IndexItem(node.ConvertToValueSet(IndexTypes.Media));
//it will not exist because it exists under 2222
var results = searcher.Search(searcher.CreateCriteria().Id(2112).Compile());
var results = searcher.CreateQuery().Id(2112).Execute();
Assert.AreEqual(0, results.Count());
//now mimic moving 2112 to 1116
@@ -222,7 +220,7 @@ namespace Umbraco.Tests.UmbracoExamine
indexer.IndexItems(new[] { node.ConvertToValueSet(IndexTypes.Media) });
//now ensure it exists
results = searcher.Search(searcher.CreateCriteria().Id(2112).Compile());
results = searcher.CreateQuery().Id(2112).Execute();
Assert.AreEqual(1, results.Count());
}
}
@@ -253,7 +251,7 @@ namespace Umbraco.Tests.UmbracoExamine
indexer1.IndexItem(node.ConvertToValueSet(IndexTypes.Media));
//it will exist because it exists under 2222
var results = searcher.Search(searcher.CreateCriteria().Id(2112).Compile());
var results = searcher.CreateQuery().Id(2112).Execute();
Assert.AreEqual(1, results.Count());
//now mimic moving the node underneath 1116 instead of 2222
@@ -264,7 +262,7 @@ namespace Umbraco.Tests.UmbracoExamine
indexer1.IndexItems(new[] { node.ConvertToValueSet(IndexTypes.Media) });
//now ensure it's deleted
results = searcher.Search(searcher.CreateCriteria().Id(2112).Compile());
results = searcher.CreateQuery().Id(2112).Execute();
Assert.AreEqual(0, results.Count());
}
}
@@ -283,14 +281,13 @@ namespace Umbraco.Tests.UmbracoExamine
validator: new ContentValueSetValidator(false)))
using (indexer.ProcessNonAsync())
{
rebuilder.RegisterIndex(indexer.Name);
var searcher = indexer.GetSearcher();
//create the whole thing
rebuilder.Populate(indexer);
var result = searcher.Search(searcher.CreateCriteria().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Compile());
var result = searcher.CreateQuery().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Execute();
Assert.AreEqual(21, result.TotalItemCount);
//delete all content
@@ -301,13 +298,13 @@ namespace Umbraco.Tests.UmbracoExamine
//ensure it's all gone
result = searcher.Search(searcher.CreateCriteria().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Compile());
result = searcher.CreateQuery().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Execute();
Assert.AreEqual(0, result.TotalItemCount);
//call our indexing methods
rebuilder.Populate(indexer);
result = searcher.Search(searcher.CreateCriteria().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Compile());
result = searcher.CreateQuery().Field(LuceneIndex.CategoryFieldName, IndexTypes.Content).Execute();
Assert.AreEqual(21, result.TotalItemCount);
}
}
@@ -335,10 +332,10 @@ namespace Umbraco.Tests.UmbracoExamine
indexer.DeleteFromIndex(1140.ToString());
//this node had children: 1141 & 1142, let's ensure they are also removed
var results = searcher.Search(searcher.CreateCriteria().Id(1141).Compile());
var results = searcher.CreateQuery().Id(1141).Execute();
Assert.AreEqual(0, results.Count());
results = searcher.Search(searcher.CreateCriteria().Id(1142).Compile());
results = searcher.CreateQuery().Id(1142).Execute();
Assert.AreEqual(0, results.Count());
}
@@ -3,17 +3,15 @@ using System.Collections.Generic;
using System.Linq;
using LightInject;
using Examine;
using Examine.Search;
using NUnit.Framework;
using Examine.LuceneEngine.SearchCriteria;
using Moq;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Services;
using Umbraco.Examine;
using Umbraco.Tests.Testing;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Strings;
using Umbraco.Examine;
namespace Umbraco.Tests.UmbracoExamine
{
@@ -62,21 +60,20 @@ namespace Umbraco.Tests.UmbracoExamine
using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir))
using (indexer.ProcessNonAsync())
{
rebuilder.RegisterIndex(indexer.Name);
indexer.CreateIndex();
rebuilder.Populate(indexer);
var searcher = indexer.GetSearcher();
var numberSortedCriteria = searcher.CreateCriteria()
.ParentId(1148).And()
var numberSortedCriteria = searcher.CreateQuery()
.ParentId(1148)
.OrderBy(new SortableField("sortOrder", SortType.Int));
var numberSortedResult = searcher.Search(numberSortedCriteria.Compile());
var numberSortedResult = numberSortedCriteria.Execute();
var stringSortedCriteria = searcher.CreateCriteria()
.ParentId(1148).And()
.OrderBy("sortOrder"); //will default to string
var stringSortedResult = searcher.Search(stringSortedCriteria.Compile());
var stringSortedCriteria = searcher.CreateQuery()
.ParentId(1148)
.OrderBy(new SortableField("sortOrder"));//will default to string
var stringSortedResult = stringSortedCriteria.Execute();
Assert.AreEqual(12, numberSortedResult.TotalItemCount);
Assert.AreEqual(12, stringSortedResult.TotalItemCount);
+1 -1
View File
@@ -88,7 +88,7 @@
<PackageReference Include="CSharpTest.Net.Collections" Version="14.906.1403.1082" />
<PackageReference Include="ClientDependency" Version="1.9.7" />
<PackageReference Include="ClientDependency-Mvc5" Version="1.8.0.0" />
<PackageReference Include="Examine" Version="1.0.0-beta046" />
<PackageReference Include="Examine" Version="1.0.0-beta067" />
<PackageReference Include="ImageProcessor.Web" Version="4.9.3.25" />
<PackageReference Include="ImageProcessor.Web.Config" Version="2.4.1.19" />
<PackageReference Include="Microsoft.AspNet.Identity.Owin" Version="2.2.2" />
@@ -74,8 +74,8 @@ namespace Umbraco.Web.Editors
throw new HttpResponseException(msg);
var results = Examine.ExamineExtensions.TryParseLuceneQuery(query)
? searcher.Search(searcher.CreateCriteria().RawQuery(query), maxResults: pageSize * (pageIndex + 1))
: searcher.Search(query, true, maxResults: pageSize * (pageIndex + 1));
? searcher.CreateQuery().NativeQuery(query).Execute(maxResults: pageSize * (pageIndex + 1))
: searcher.Search(query, maxResults: pageSize * (pageIndex + 1));
var pagedResults = results.Skip(pageIndex * pageSize);
@@ -109,7 +109,7 @@ namespace Umbraco.Web.Editors
if (!validate.IsSuccessStatusCode)
throw new HttpResponseException(validate);
validate = ValidatePopulator(indexName);
validate = ValidatePopulator(index);
if (!validate.IsSuccessStatusCode)
throw new HttpResponseException(validate);
@@ -134,7 +134,7 @@ namespace Umbraco.Web.Editors
if (!validate.IsSuccessStatusCode)
return validate;
validate = ValidatePopulator(indexName);
validate = ValidatePopulator(index);
if (!validate.IsSuccessStatusCode)
return validate;
@@ -201,7 +201,7 @@ namespace Umbraco.Web.Editors
Name = indexName,
HealthStatus = isHealth.Success ? (isHealth.Result ?? "Healthy") : (isHealth.Result ?? "Unhealthy"),
ProviderProperties = properties,
CanRebuild = _indexRebuilder.CanRebuild(indexName)
CanRebuild = _indexRebuilder.CanRebuild(index)
};
@@ -228,13 +228,13 @@ namespace Umbraco.Web.Editors
return response1;
}
private HttpResponseMessage ValidatePopulator(string indexName)
private HttpResponseMessage ValidatePopulator(IIndex index)
{
if (_indexRebuilder.CanRebuild(indexName))
if (_indexRebuilder.CanRebuild(index))
return Request.CreateResponse(HttpStatusCode.OK);
var response = Request.CreateResponse(HttpStatusCode.BadRequest);
response.Content = new StringContent($"The index {indexName} cannot be rebuilt because it does not have an associated {typeof(IIndexPopulator)}");
response.Content = new StringContent($"The index {index.Name} cannot be rebuilt because it does not have an associated {typeof(IIndexPopulator)}");
response.ReasonPhrase = "Index cannot be rebuilt";
return response;
}
+22 -6
View File
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Xml.XPath;
using Examine.Search;
using Umbraco.Core;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Xml;
@@ -34,21 +35,36 @@ namespace Umbraco.Web
/// <summary>
/// Searches content.
/// </summary>
IEnumerable<PublishedSearchResult> Search(string term, bool useWildCards = true, string indexName = null);
/// <param name="term">Term to search.</param>
/// <param name="culture">Optional culture.</param>
/// <param name="indexName">Optional index name.</param>
/// <remarks>
/// <para>When the <paramref name="culture"/> is not specified, all cultures are searched.</para>
/// </remarks>
IEnumerable<PublishedSearchResult> Search(string term, string culture = null, string indexName = null);
/// <summary>
/// Searches content.
/// </summary>
IEnumerable<PublishedSearchResult> Search(int skip, int take, out long totalRecords, string term, bool useWildCards = true, string indexName = null);
/// <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>
/// <remarks>
/// <para>When the <paramref name="culture"/> is not specified, all cultures are searched.</para>
/// </remarks>
IEnumerable<PublishedSearchResult> Search(string term, int skip, int take, out long totalRecords, string culture = null, string indexName = null);
/// <summary>
/// Searches content.
/// Executes the query and converts the results to PublishedSearchResult.
/// </summary>
IEnumerable<PublishedSearchResult> Search(Examine.SearchCriteria.ISearchCriteria criteria, Examine.ISearcher searchProvider = null);
IEnumerable<PublishedSearchResult> Search(IQueryExecutor query);
/// <summary>
/// Searches content.
/// Executes the query and converts the results to PublishedSearchResult.
/// </summary>
IEnumerable<PublishedSearchResult> Search(int skip, int take, out long totalRecords, Examine.SearchCriteria.ISearchCriteria criteria, Examine.ISearcher searcher = null);
IEnumerable<PublishedSearchResult> Search(IQueryExecutor query, int skip, int take, out long totalRecords);
}
}
@@ -6,8 +6,8 @@ using System.Linq;
using System.Threading;
using System.Xml.XPath;
using Examine;
using Examine.LuceneEngine.SearchCriteria;
using Examine.Providers;
using Examine.Search;
using Lucene.Net.Store;
using Umbraco.Core;
using Umbraco.Core.Logging;
@@ -15,7 +15,6 @@ using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Xml;
using Umbraco.Examine;
using umbraco;
using Umbraco.Core.Cache;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
@@ -107,10 +106,10 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
// first check in Examine for the cache values
// +(+parentID:-1) +__IndexType:media
var criteria = searchProvider.CreateCriteria("media");
var criteria = searchProvider.CreateQuery("media");
var filter = criteria.ParentId(-1).Not().Field(UmbracoExamineIndex.IndexPathFieldName, "-1,-21,".MultipleCharacterWildcard());
var result = searchProvider.Search(filter.Compile());
var result = filter.Execute();
if (result != null)
return result.Select(x => CreateFromCacheValues(ConvertFromSearchResult(x)));
}
@@ -293,10 +292,10 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
//
// note that since the use of the wildcard, it automatically escapes it in Lucene.
var criteria = searchProvider.CreateCriteria("media");
var criteria = searchProvider.CreateQuery("media");
var filter = criteria.Id(id.ToInvariantString()).Not().Field(UmbracoExamineIndex.IndexPathFieldName, "-1,-21,".MultipleCharacterWildcard());
var result = searchProvider.Search(filter.Compile()).FirstOrDefault();
var result = filter.Execute().FirstOrDefault();
if (result != null) return ConvertFromSearchResult(result);
}
catch (Exception ex)
@@ -507,15 +506,15 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
try
{
//first check in Examine as this is WAY faster
var criteria = searchProvider.CreateCriteria("media");
var criteria = searchProvider.CreateQuery("media");
var filter = criteria.ParentId(parentId).Not().Field(UmbracoExamineIndex.IndexPathFieldName, "-1,-21,".MultipleCharacterWildcard());
var filter = criteria.ParentId(parentId).Not().Field(UmbracoExamineIndex.IndexPathFieldName, "-1,-21,".MultipleCharacterWildcard())
.OrderBy(new SortableField("sortOrder", SortType.Int));
//the above filter will create a query like this, NOTE: That since the use of the wildcard, it automatically escapes it in Lucene.
//+(+parentId:3113 -__Path:-1,-21,*) +__IndexType:media
// sort with the Sort field (updated for 8.0)
var results = searchProvider.Search(
filter.And().OrderBy(new SortableField("sortOrder", SortType.Int)).Compile());
var results = filter.Execute();
if (results.Any())
{
+18 -29
View File
@@ -4,12 +4,13 @@ using System.Data;
using System.Linq;
using System.Web;
using Examine;
using Examine.LuceneEngine.SearchCriteria;
using Examine.Search;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Examine;
using Umbraco.Web.Composing;
namespace Umbraco.Web
@@ -266,7 +267,7 @@ namespace Umbraco.Web
#region Search
public static IEnumerable<PublishedSearchResult> SearchDescendants(this IPublishedContent content, string term, bool useWildCards = true, string indexName = null)
public static IEnumerable<PublishedSearchResult> SearchDescendants(this IPublishedContent content, string term, string indexName = null)
{
//fixme: pass in the IExamineManager
@@ -276,17 +277,18 @@ namespace Umbraco.Web
var searcher = index.GetSearcher();
var t = term.Escape().Value;
if (useWildCards)
t = term.MultipleCharacterWildcard().Value;
//var t = term.Escape().Value;
//var luceneQuery = "+__Path:(" + content.Path.Replace("-", "\\-") + "*) +" + t;
var luceneQuery = "+__Path:(" + content.Path.Replace("-", "\\-") + "*) +" + t;
var crit = searcher.CreateCriteria().RawQuery(luceneQuery);
var query = searcher.CreateQuery()
.Field(UmbracoExamineIndex.IndexPathFieldName, (content.Path + ",").MultipleCharacterWildcard())
.And()
.ManagedQuery(term);
return content.Search(crit, searcher);
return query.Execute().ToPublishedSearchResults(UmbracoContext.Current.ContentCache);
}
public static IEnumerable<PublishedSearchResult> SearchChildren(this IPublishedContent content, string term, bool useWildCards = true, string indexName = null)
public static IEnumerable<PublishedSearchResult> SearchChildren(this IPublishedContent content, string term, string indexName = null)
{
//fixme: pass in the IExamineManager
@@ -296,28 +298,15 @@ namespace Umbraco.Web
var searcher = index.GetSearcher();
var t = term.Escape().Value;
if (useWildCards)
t = term.MultipleCharacterWildcard().Value;
//var t = term.Escape().Value;
//var luceneQuery = "+parentID:" + content.Id + " +" + t;
var luceneQuery = "+parentID:" + content.Id + " +" + t;
var crit = searcher.CreateCriteria().RawQuery(luceneQuery);
var query = searcher.CreateQuery()
.Field("parentID", content.Id)
.And()
.ManagedQuery(term);
return content.Search(crit, searcher);
}
public static IEnumerable<PublishedSearchResult> Search(this IPublishedContent content, Examine.SearchCriteria.ISearchCriteria criteria, ISearcher searchProvider = null)
{
//fixme: pass in the IExamineManager
if (searchProvider == null)
{
if (!ExamineManager.Instance.TryGetIndex(Constants.UmbracoIndexes.ExternalIndexName, out var index))
throw new InvalidOperationException("No index found with name " + Constants.UmbracoIndexes.ExternalIndexName);
searchProvider = index.GetSearcher();
}
var results = searchProvider.Search(criteria);
return results.ToPublishedSearchResults(UmbracoContext.Current.ContentCache);
return query.Execute().ToPublishedSearchResults(UmbracoContext.Current.ContentCache);
}
#endregion
+54 -34
View File
@@ -2,15 +2,15 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Xml.XPath;
using Examine;
using Examine.LuceneEngine.Providers;
using Examine.LuceneEngine.SearchCriteria;
using Examine.SearchCriteria;
using Examine.Search;
using Umbraco.Core;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
using Umbraco.Core.Xml;
using Umbraco.Examine;
using Umbraco.Web.PublishedCache;
namespace Umbraco.Web
@@ -181,58 +181,78 @@ namespace Umbraco.Web
#region Search
/// <inheritdoc />
public IEnumerable<PublishedSearchResult> Search(string term, bool useWildCards = true, string indexName = null)
public IEnumerable<PublishedSearchResult> Search(string term, string culture = null, string indexName = null)
{
return Search(0, 0, out _, term, useWildCards, indexName);
return Search(term, 0, 0, out _, culture, indexName);
}
/// <inheritdoc />
public IEnumerable<PublishedSearchResult> Search(int skip, int take, out long totalRecords, string term, bool useWildCards = true, string indexName = null)
public IEnumerable<PublishedSearchResult> Search(string term, int skip, int take, out long totalRecords, string culture = null, string indexName = null)
{
//fixme: inject IExamineManager
indexName = string.IsNullOrEmpty(indexName)
? Constants.UmbracoIndexes.ExternalIndexName
: indexName;
if (!ExamineManager.Instance.TryGetIndex(indexName, out var index))
throw new InvalidOperationException($"No index found by name {indexName}");
if (!ExamineManager.Instance.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 = index.GetSearcher();
var searcher = umbIndex.GetSearcher();
var results = skip == 0 && take == 0
? searcher.Search(term, true)
: searcher.Search(term, true, maxResults: skip + take);
// default to max 500 results
var count = skip == 0 && take == 0 ? 500 : skip + take;
totalRecords = results.TotalItemCount;
return results.ToPublishedSearchResults(_contentCache);
}
/// <inheritdoc />
public IEnumerable<PublishedSearchResult> Search(ISearchCriteria criteria, ISearcher searchProvider = null)
{
return Search(0, 0, out _, criteria, searchProvider);
}
/// <inheritdoc />
public IEnumerable<PublishedSearchResult> Search(int skip, int take, out long totalRecords, ISearchCriteria criteria, ISearcher searcher = null)
{
//fixme: inject IExamineManager
if (searcher == null)
ISearchResults results;
if (culture.IsNullOrWhiteSpace())
{
if (!ExamineManager.Instance.TryGetIndex(Constants.UmbracoIndexes.ExternalIndexName, out var index))
throw new InvalidOperationException($"No index found by name {Constants.UmbracoIndexes.ExternalIndexName}");
searcher = index.GetSearcher();
results = searcher.Search(term, count);
}
else
{
//get all index fields suffixed with the culture name supplied
var cultureFields = new List<string>();
var fields = umbIndex.GetFields();
var qry = searcher.CreateQuery().Field(UmbracoContentIndex.VariesByCultureFieldName, 1); //must vary by culture
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var field in fields)
{
var match = CultureIsoCodeFieldName.Match(field);
if (match.Success && match.Groups.Count == 2 && culture.InvariantEquals(match.Groups[1].Value))
cultureFields.Add(field);
}
qry = qry.And().ManagedQuery(term, cultureFields.ToArray());
results = qry.Execute(count);
}
totalRecords = results.TotalItemCount;
return results.ToPublishedSearchResults(_contentCache);
}
/// <inheritdoc />
public IEnumerable<PublishedSearchResult> Search(IQueryExecutor query)
{
return Search(query, 0, 0, out _);
}
/// <inheritdoc />
public IEnumerable<PublishedSearchResult> Search(IQueryExecutor query, int skip, int take, out long totalRecords)
{
var results = skip == 0 && take == 0
? searcher.Search(criteria)
: searcher.Search(criteria, maxResults: skip + take);
? query.Execute()
: query.Execute(maxResults: skip + take);
totalRecords = results.TotalItemCount;
return results.ToPublishedSearchResults(_contentCache);
}
/// <summary>
/// Matches a culture iso name suffix
/// </summary>
/// <remarks>
/// myFieldName_en-us will match the "en-us"
/// </remarks>
private static readonly Regex CultureIsoCodeFieldName = new Regex("^[_\\w]+_([a-z]{2}-[a-z0-9]{2,4})$", RegexOptions.Compiled);
#endregion
}
+9 -10
View File
@@ -23,6 +23,7 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Web.Scheduling;
using System.Threading.Tasks;
using Examine.LuceneEngine.Directories;
using Examine.LuceneEngine.Indexing;
using LightInject;
using Umbraco.Core.Composing;
using Umbraco.Core.Strings;
@@ -149,7 +150,7 @@ namespace Umbraco.Web.Search
profilingLogger.Logger.Debug<ExamineComponent>("Examine shutdown registered with MainDom");
var registeredIndexers = examineManager.Indexes.OfType<IUmbracoIndexer>().Count(x => x.EnableDefaultEventHandler);
var registeredIndexers = examineManager.Indexes.OfType<IUmbracoIndex>().Count(x => x.EnableDefaultEventHandler);
profilingLogger.Logger.Info<ExamineComponent>("Adding examine event handlers for {RegisteredIndexers} index providers.", registeredIndexers);
@@ -166,10 +167,10 @@ namespace Umbraco.Web.Search
EnsureUnlocked(profilingLogger.Logger, examineManager);
//TODO: Instead of waiting 5000 ms, we could add an event handler on to fulfilling the first request, then start?
RebuildIndexes(indexRebuilder, profilingLogger.Logger, true, 5000);
}
/// <summary>
/// Called to rebuild empty indexes on startup
/// </summary>
@@ -480,7 +481,7 @@ namespace Umbraco.Web.Search
//Delete all content of this content/media/member type that is in any content indexer by looking up matched examine docs
foreach (var id in ci.Value.removedIds)
{
foreach (var index in _examineManager.Indexes.OfType<IUmbracoIndexer>())
foreach (var index in _examineManager.Indexes.OfType<IUmbracoIndex>())
{
var searcher = index.GetSearcher();
@@ -489,9 +490,7 @@ namespace Umbraco.Web.Search
while (page * pageSize < total)
{
//paging with examine, see https://shazwazza.com/post/paging-with-examine/
var results = searcher.Search(
searcher.CreateCriteria().Field("nodeType", id).Compile(),
maxResults: pageSize * (page + 1));
var results = searcher.CreateQuery().Field("nodeType", id).Execute(maxResults: pageSize * (page + 1));
total = results.TotalItemCount;
var paged = results.Skip(page * pageSize);
@@ -686,7 +685,7 @@ namespace Umbraco.Web.Search
public static void Execute(ExamineComponent examineComponent, IContent content, bool isPublished)
{
foreach (var index in examineComponent._examineManager.Indexes.OfType<IUmbracoIndexer>()
foreach (var index in examineComponent._examineManager.Indexes.OfType<IUmbracoIndex>()
//filter the indexers
.Where(x => isPublished || !x.PublishedValuesOnly)
.Where(x => x.EnableDefaultEventHandler))
@@ -723,7 +722,7 @@ namespace Umbraco.Web.Search
{
var valueSet = examineComponent._mediaValueSetBuilder.GetValueSets(media).ToList();
foreach (var index in examineComponent._examineManager.Indexes.OfType<IUmbracoIndexer>()
foreach (var index in examineComponent._examineManager.Indexes.OfType<IUmbracoIndex>()
//filter the indexers
.Where(x => isPublished || !x.PublishedValuesOnly)
.Where(x => x.EnableDefaultEventHandler))
@@ -752,7 +751,7 @@ namespace Umbraco.Web.Search
public static void Execute(ExamineComponent examineComponent, IMember member)
{
var valueSet = examineComponent._memberValueSetBuilder.GetValueSets(member).ToList();
foreach (var index in examineComponent._examineManager.Indexes.OfType<IUmbracoIndexer>()
foreach (var index in examineComponent._examineManager.Indexes.OfType<IUmbracoIndex>()
//filter the indexers
.Where(x => x.EnableDefaultEventHandler))
{
@@ -782,7 +781,7 @@ namespace Umbraco.Web.Search
public static void Execute(ExamineComponent examineComponent, int id, bool keepIfUnpublished)
{
var strId = id.ToString(CultureInfo.InvariantCulture);
foreach (var index in examineComponent._examineManager.Indexes.OfType<IUmbracoIndexer>()
foreach (var index in examineComponent._examineManager.Indexes.OfType<IUmbracoIndex>()
.Where(x => (keepIfUnpublished && !x.PublishedValuesOnly) || !keepIfUnpublished)
.Where(x => x.EnableDefaultEventHandler))
@@ -33,7 +33,7 @@ namespace Umbraco.Web.Search
try
{
var searcher = _index.GetSearcher();
var result = searcher.Search("test", false);
var result = searcher.Search("test");
return Attempt<string>.Succeed(); //if we can search we'll assume it's healthy
}
catch (Exception e)
@@ -59,8 +59,7 @@ namespace Umbraco.Web.Search
{
var index = new UmbracoContentIndex(
Constants.UmbracoIndexes.InternalIndexName,
//fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes
UmbracoExamineIndex.UmbracoIndexFieldDefinitions,
new UmbracoFieldDefinitionCollection(),
CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.InternalIndexPath),
new CultureInvariantWhitespaceAnalyzer(),
ProfilingLogger,
@@ -73,8 +72,7 @@ namespace Umbraco.Web.Search
{
var index = new UmbracoContentIndex(
Constants.UmbracoIndexes.ExternalIndexName,
//fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes
UmbracoExamineIndex.UmbracoIndexFieldDefinitions,
new UmbracoFieldDefinitionCollection(),
CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.ExternalIndexPath),
new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30),
ProfilingLogger,
@@ -87,8 +85,7 @@ namespace Umbraco.Web.Search
{
var index = new UmbracoMemberIndex(
Constants.UmbracoIndexes.MembersIndexName,
//fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes
UmbracoExamineIndex.UmbracoIndexFieldDefinitions,
new UmbracoFieldDefinitionCollection(),
CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.MembersIndexPath),
new CultureInvariantWhitespaceAnalyzer(),
ProfilingLogger,
@@ -109,11 +109,9 @@ namespace Umbraco.Web.Search
return Enumerable.Empty<SearchResultEntity>();
}
var raw = internalSearcher.CreateCriteria().RawQuery(sb.ToString());
var result = internalSearcher
var result = internalSearcher.CreateQuery().NativeQuery(sb.ToString())
//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
.Search(raw, Convert.ToInt32(pageSize * (pageIndex + 1)));
.Execute(Convert.ToInt32(pageSize * (pageIndex + 1)));
totalFound = result.TotalItemCount;
+1 -1
View File
@@ -63,7 +63,7 @@
<PackageReference Include="AutoMapper" Version="7.0.1" />
<PackageReference Include="ClientDependency" Version="1.9.7" />
<PackageReference Include="CSharpTest.Net.Collections" Version="14.906.1403.1082" />
<PackageReference Include="Examine" Version="1.0.0-beta046" />
<PackageReference Include="Examine" Version="1.0.0-beta067" />
<PackageReference Include="HtmlAgilityPack" Version="1.8.9" />
<PackageReference Include="ImageProcessor">
<Version>2.6.2.25</Version>
-56
View File
@@ -775,62 +775,6 @@ namespace Umbraco.Web
#endregion
#region Search
/// <summary>
/// Searches content.
/// </summary>
/// <param name="term"></param>
/// <param name="useWildCards"></param>
/// <param name="indexName"></param>
/// <returns></returns>
public IEnumerable<PublishedSearchResult> Search(string term, bool useWildCards = true, string indexName = null)
{
return ContentQuery.Search(term, useWildCards, indexName);
}
/// <summary>
/// Searches content.
/// </summary>
/// <param name="skip"></param>
/// <param name="take"></param>
/// <param name="totalRecords"></param>
/// <param name="term"></param>
/// <param name="useWildCards"></param>
/// <param name="indexName"></param>
/// <returns></returns>
public IEnumerable<PublishedSearchResult> Search(int skip, int take, out long totalRecords, string term, bool useWildCards = true, string indexName = null)
{
return ContentQuery.Search(skip, take, out totalRecords, term, useWildCards, indexName);
}
/// <summary>
/// Searhes content.
/// </summary>
/// <param name="skip"></param>
/// <param name="take"></param>
/// <param name="totalRecords"></param>
/// <param name="criteria"></param>
/// <param name="searchProvider"></param>
/// <returns></returns>
public IEnumerable<PublishedSearchResult> Search(int skip, int take, out long totalRecords, Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null)
{
return ContentQuery.Search(skip, take, out totalRecords, criteria, searchProvider);
}
/// <summary>
/// Searhes content.
/// </summary>
/// <param name="criteria"></param>
/// <param name="searchProvider"></param>
/// <returns></returns>
public IEnumerable<PublishedSearchResult> Search(Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null)
{
return ContentQuery.Search(criteria, searchProvider);
}
#endregion
#region Strings
/// <summary>