public void CreateIndex(string name, FieldDefinitionCollection fields, Analyzer analyzer = null) { if (analyzer == null) { analyzer = new KeywordAnalyzer(); } // examineIndex.WaitForIndexQueueOnShutdown = false; _examineManager.TryGetIndex(name, out var index); if (index == null) { var dir = examineIndex.GetLuceneDirectory(); if (!string.IsNullOrEmpty(dir.GetLockID())) { // _loggingService.Info("Forcing index {IndexerName} to be unlocked since it was left in a locked state", examineIndex.Name); dir.ClearLock("write.lock"); } if (IndexWriter.IsLocked(dir)) { IndexWriter.Unlock(dir); } } }
/// <summary> /// Remove the media from the PDF index /// </summary> /// <param name="media"></param> public void RemoveFromIndex(params IMedia[] media) { if (!_examineManager.TryGetIndex(PdfIndexConstants.PdfIndexName, out var index)) { return; } var ids = media.Select(m => m.Id.ToInvariantString()); index.DeleteFromIndex(ids); }
public void ConfigureIndexes(IEnumerable<IIndexConfig> indexes) { foreach (var index in indexes) { if (_examineManager.TryGetIndex(index.Name, out IIndex existingIndex) == true) { throw new Exception($"Index {index.Name} already exists"); } } }
private PagedResult <ProductPage> GetPagedProducts(int?collectionId, string category, int page, int pageSize) { if (_examineManager.TryGetIndex("ExternalIndex", out var index)) { var searcher = index.GetSearcher(); var query = searcher.CreateQuery() .Field("__NodeTypeAlias", ProductPage.ModelTypeAlias); if (collectionId.HasValue) { query = query.And().Field("parentID", collectionId.Value); } if (!category.IsNullOrWhiteSpace()) { query = query.And().Field("categoryAliases", category); } var results = query.OrderBy(new SortableField("name", SortType.String)).Execute(pageSize * page); var totalResults = results.TotalItemCount; var pagedResults = results.Skip(pageSize * (page - 1)); var items = pagedResults.ToPublishedSearchResults(_umbracoContextAccessor.UmbracoContext.Content) .Select(x => x.Content) .OfType <ProductPage>(); return(new PagedResult <ProductPage>(totalResults, page, pageSize) { Items = items }); } return(new PagedResult <ProductPage>(0, page, pageSize)); }
private ISearcher GetSearchProviderSafe() { if (_searchProvider != null) { return(_searchProvider); } try { return(_examineManager.TryGetIndex(Constants.UmbracoIndexes.InternalIndexName, out var index) ? index.GetSearcher() : null); } catch (FileNotFoundException) { //Currently examine is throwing FileNotFound exceptions when we have a load balanced filestore and a node is published in umbraco //See this thread: http://examine.cdodeplex.com/discussions/264341 //Catch the exception here for the time being, and just fallback to GetMedia // TODO: Need to fix examine in LB scenarios! } catch (NullReferenceException) { //This will occur when the search provider cannot be initialized. In newer examine versions the initialization is lazy and therefore // the manager will return the singleton without throwing initialization errors, however if examine isn't configured correctly a null // reference error will occur because the examine settings are null. } catch (ObjectDisposedException) { //If the app domain is shutting down and the site is under heavy load the index reader will be closed and it really cannot //be re-opened since the app domain is shutting down. In this case we have no option but to try to load the data from the db. } return(null); }
public ActionResult Search(string q = "", int p = 1, int ps = 12) { // The logic for searching is mostly pulled from ezSearch // https://github.com/umco/umbraco-ezsearch/blob/master/Src/Our.Umbraco.ezSearch/Web/UI/Views/MacroPartials/ezSearch.cshtml var result = new PagedResult <IPublishedContent>(0, 1, ps); if (!q.IsNullOrWhiteSpace() && _examineManager.TryGetIndex("ExternalIndex", out var index)) { var searchTerms = Tokenize(q); var searchFields = new[] { "nodeName", "metaTitle", "description", "shortDescription", "longDescription", "metaDescription", "bodyText", "content" }; var searcher = index.GetSearcher(); var query = new StringBuilder(); query.Append("+__IndexType:content "); // Must be content query.Append("-templateID:0 "); // Must have a template query.Append("-umbracoNaviHide:1 "); // Must no be hidden // Ensure page contains all search terms in some way foreach (var term in searchTerms) { var groupedOr = searchFields.Aggregate(new StringBuilder(), (innerQuery, searchField) => { var format = searchField.Contains(" ") ? @"{0}:""{1}"" " : "{0}:{1}* "; innerQuery.AppendFormat(format, searchField, term); return(innerQuery); }); query.Append("+(" + groupedOr.ToString() + ") "); } // Rank content based on positon of search terms in fields for (var i = 0; i < searchFields.Length; i++) { foreach (var term in searchTerms) { var searchField = searchFields[i]; var format = searchField.Contains(" ") ? @"{0}:""{1}""^{2} " : "{0}:{1}*^{2} "; query.AppendFormat(format, searchField, term, searchFields.Length - i); } } var examineQuery = searcher.CreateQuery().NativeQuery(query.ToString()); var results = examineQuery.Execute(ps * p); var totalResults = results.TotalItemCount; var pagedResults = results.Skip(ps * (p - 1)); result = new PagedResult <IPublishedContent>(totalResults, p, ps) { Items = pagedResults.Select(x => UmbracoContext.Content.GetById(int.Parse(x.Id))) }; } return(PartialView("SearchResults", result)); }
public void Initialize() { if (examineManager.TryGetIndex("ExternalIndex", out IIndex externalIndex)) { externalIndex.FieldDefinitionCollection.AddOrUpdate( new FieldDefinition("articleDate", FieldDefinitionTypes.Long)); ((BaseIndexProvider)externalIndex).TransformingIndexValues += IndexerComponent_TransformingIndexValues; } }
private void ContentCacheRefresher_CacheUpdated(ContentCacheRefresher sender, CacheRefresherEventArgs args) { if (args.MessageType != MessageType.RefreshByPayload) { return; } if (!_fullTextConfig.IsFullTextIndexingEnabled()) { _logger.Debug <UpdateCacheOnPublish>("FullTextIndexing is not enabled"); return; } if (!_examineManager.TryGetIndex("ExternalIndex", out IIndex index)) { _logger.Error <UpdateCacheOnPublish>(new InvalidOperationException("No index found by name ExternalIndex")); return; } foreach (var payload in (ContentCacheRefresher.JsonPayload[])args.MessageObject) { if (payload.ChangeTypes.HasType(TreeChangeTypes.Remove)) { _cacheService.DeleteFromCache(payload.Id); } else if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshAll)) { // just ignore that payload (Umbracos examine implementation does the same) } else // RefreshNode or RefreshBranch (maybe trashed) { _cacheService.AddCacheTask(payload.Id); // branch if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshBranch)) { const int pageSize = 500; var page = 0; var total = long.MaxValue; while (page * pageSize < total) { var descendants = _contentService.GetPagedDescendants(payload.Id, page++, pageSize, out total, //order by shallowest to deepest, this allows us to check it's published state without checking every item ordering: Ordering.By("Path", Direction.Ascending)); foreach (var descendant in descendants) { _cacheService.AddCacheTask(descendant.Id); } } } } } }
private ActionResult ValidateSearcher(string searcherName, out ISearcher searcher) { //try to get the searcher from the indexes if (_examineManager.TryGetIndex(searcherName, out IIndex index)) { searcher = index.Searcher; return(new OkResult()); } //if we didn't find anything try to find it by an explicitly declared searcher if (_examineManager.TryGetSearcher(searcherName, out searcher)) { return(new OkResult()); } var response1 = new BadRequestObjectResult($"No searcher found with name = {searcherName}"); HttpContext.SetReasonPhrase("Searcher Not Found"); return(response1); }
private HttpResponseMessage ValidateSearcher(string searcherName, out ISearcher searcher) { //try to get the searcher from the indexes if (_examineManager.TryGetIndex(searcherName, out var index)) { searcher = index.GetSearcher(); return(Request.CreateResponse(HttpStatusCode.OK)); } //if we didn't find anything try to find it by an explicitly declared searcher if (_examineManager.TryGetSearcher(searcherName, out searcher)) { return(Request.CreateResponse(HttpStatusCode.OK)); } var response1 = Request.CreateResponse(HttpStatusCode.BadRequest); response1.Content = new StringContent($"No searcher found with name = {searcherName}"); response1.ReasonPhrase = "Searcher Not Found"; return(response1); }
public void Initialize() { if (!_examineManager.TryGetIndex(UmbracoIndexes.ExternalIndexName, out IIndex index)) { return; } index.FieldDefinitionCollection.AddOrUpdate( new FieldDefinition("searchableCategories", FieldDefinitionTypes.FullText)); ((BaseIndexProvider)index).TransformingIndexValues += IndexerComponent_TransformingIndexvalues; }
public void Initialize() { if (!_examineManager.TryGetIndex(Constants.UmbracoIndexes.ExternalIndexName, out IIndex index)) { throw new InvalidOperationException($"No index found by name {Constants.UmbracoIndexes.ExternalIndexName}"); } if (!(index is BaseIndexProvider indexProvider)) { throw new InvalidOperationException("Could not cast"); } indexProvider.TransformingIndexValues += IndexProviderTransformingIndexValues; }
private IQuery InitialiseMemberQuery(BooleanOperation operation = BooleanOperation.And, string indexType = UmbracoIndexes.MembersIndexName) { if (examineManager.TryGetIndex(indexType, out var index)) { #if NET5_0_OR_GREATER var searcher = index.Searcher; #else var searcher = index.GetSearcher(); #endif return(searcher.CreateQuery(IndexTypes.Member, defaultOperation: operation)); } logger.LogWarning("Could not retrieve index {indexType}", indexType); return(null); }
public void Initialize() { IIndex externalIndex = null; if (_examineManager.TryGetIndex("ExternalIndex", out externalIndex)) { // FieldDefinitionCollection contains all indexed fields externalIndex.FieldDefinitionCollection.AddOrUpdate(new FieldDefinition("contents", FieldDefinitionTypes.FullText)); ((BaseIndexProvider)externalIndex).TransformingIndexValues += OnTransformingIndexValues; } else { throw new Exception("Index not found"); } }
public void Initialize() { if (!_examineManager.TryGetIndex("ExternalIndex", out IIndex index)) { throw new InvalidOperationException("No index found by name ExternalIndex"); } //we need to cast because BaseIndexProvider contains the TransformingIndexValues event if (!(index is BaseIndexProvider indexProvider)) { throw new InvalidOperationException("Could not cast"); } indexProvider.TransformingIndexValues += IndexProviderTransformingIndexValues; }
public void Initialize() { if (!_examineManager.TryGetIndex("ExternalIndex", out IIndex index)) { _logger.Error <AddFullTextItemsToIndex>(new InvalidOperationException("No index found by name ExternalIndex")); return; } //we need to cast because BaseIndexProvider contains the TransformingIndexValues event if (!(index is BaseIndexProvider indexProvider)) { _logger.Error <AddFullTextItemsToIndex>(new InvalidOperationException("Could not cast ExternalIndex to BaseIndexProvider")); return; } indexProvider.TransformingIndexValues += IndexProviderTransformingIndexValues; }
public override bool PerformRun() { if (!_fullTextConfig.IsFullTextIndexingEnabled()) { return(false); } if (!_examineManager.TryGetIndex("ExternalIndex", out IIndex index)) { _logger.Error <PerformCacheTasks>(new InvalidOperationException("No index found by name ExternalIndex")); return(false); } try { using (_profilingLogger.DebugDuration <PerformCacheTasks>("PerformCacheTasks", "PerformCacheTasks done")) { var tasks = _cacheService.GetCacheTasks(); foreach (var task in tasks) { _cacheService.SetTaskAsStarted(task); } foreach (var task in tasks) { var content = _contentService.GetById(task.NodeId); if (content != null) { _cacheService.AddToCache(task.NodeId); index.IndexItems(_valueSetBuilder.GetValueSets(content)); } else { _cacheService.DeleteFromCache(task.NodeId); } _cacheService.DeleteCacheTask(task.Id); } } } catch (Exception e) { _logger.Error <PerformCacheTasks>(e); } return(true); }
public static IEnumerable <PublishedSearchResult> SearchChildren(this IPublishedContent content, IExamineManager examineManager, IUmbracoContextAccessor umbracoContextAccessor, string term, string indexName = null) { indexName = string.IsNullOrEmpty(indexName) ? Constants.UmbracoIndexes.ExternalIndexName : indexName; if (!examineManager.TryGetIndex(indexName, out var index)) { throw new InvalidOperationException("No index found with name " + indexName); } //var t = term.Escape().Value; //var luceneQuery = "+parentID:" + content.Id + " +" + t; var query = index.Searcher.CreateQuery() .Field("parentID", content.Id) .And() .ManagedQuery(term); var umbracoContext = umbracoContextAccessor.GetRequiredUmbracoContext(); return(query.Execute().ToPublishedSearchResults(umbracoContext.Content)); }
public static IEnumerable <PublishedSearchResult> SearchDescendants(this IPublishedContent content, IExamineManager examineManager, IUmbracoContextAccessor umbracoContextAccessor, string term, string indexName = null) { indexName = string.IsNullOrEmpty(indexName) ? Constants.UmbracoIndexes.ExternalIndexName : indexName; if (!examineManager.TryGetIndex(indexName, out var index)) { throw new InvalidOperationException("No index found with name " + indexName); } //var t = term.Escape().Value; //var luceneQuery = "+__Path:(" + content.Path.Replace("-", "\\-") + "*) +" + t; var query = index.Searcher.CreateQuery() .Field(UmbracoExamineFieldNames.IndexPathFieldName, (content.Path + ",").MultipleCharacterWildcard()) .And() .ManagedQuery(term); var umbracoContext = umbracoContextAccessor.GetRequiredUmbracoContext(); return(query.Execute().ToPublishedSearchResults(umbracoContext.Content)); }
protected virtual ISearcher GetSearcherByIndexName(IExamineManager examineManager, ISearchHelper searchHelper, string indexName) { // Get the index from the Examine manager if (!examineManager.TryGetIndex(indexName, out IIndex index)) { throw new Exception($"Examine index {indexName} not found."); } // Get the searcher from the index ISearcher searcher = index.GetSearcher(); if (searcher == null) { throw new Exception("Examine index {indexName} does not specify a searcher."); } // Return the searcher return(searcher); }
/// <summary>Initializes the component.</summary> public void Initialize() { //get the index if (!_examineManager.TryGetIndex(Constants.UmbracoIndexes.ExternalIndexName, out IIndex index)) { return; } //we need to cast because BaseIndexProvider contains the TransformingIndexValues event if (!(index is BaseIndexProvider indexProvider)) { throw new InvalidOperationException("Could not cast"); } //handler indexProvider.TransformingIndexValues += IndexProviderTransformingIndexValues; //add a new field definition to the index index.FieldDefinitionCollection.TryAdd(new FieldDefinition("blogDateLong", FieldDefinitionTypes.Long)); }
public ISearchResults Search(string searchQuery, int maxResults, float fuzzieness, string indexType, string[] nodeTypes, string[] properties) { if (!examineManager.TryGetIndex(Constants.UmbracoIndexes.ExternalIndexName, out var index)) { throw new InvalidOperationException($"No index found by name {Constants.UmbracoIndexes.ExternalIndexName}"); } var searcher = index.GetSearcher(); var query = searcher.CreateQuery(indexType); var operation = query.GroupedOr(new[] { SearchFields.NodeTypeAlias }, nodeTypes); var queryWords = searchQuery.Split(new char[0], StringSplitOptions.RemoveEmptyEntries); var exactSearchPhrase = new ExactPhraseExamineValue(searchQuery); foreach (var word in queryWords) { operation.And().GroupedOr(properties, word.Fuzzy(fuzzieness), exactSearchPhrase); } return(operation.Execute(maxResults)); }
public bool ReindexNode(string nodeIds) { if (!_fullTextConfig.IsFullTextIndexingEnabled()) { _logger.Debug <IndexController>("FullTextIndexing is not enabled"); return(false); } if (!_examineManager.TryGetIndex("ExternalIndex", out IIndex index)) { _logger.Error <IndexController>(new InvalidOperationException("No index found by name ExternalIndex")); return(false); } if (nodeIds == "*") { foreach (var content in Umbraco.ContentAtRoot()) { _cacheService.AddToCache(content.Id); foreach (var descendant in content.Descendants()) { _cacheService.AddToCache(descendant.Id); } } index.CreateIndex(); _indexRebuilder.RebuildIndex("ExternalIndex"); } else { var ids = nodeIds.Split(',').Select(x => int.Parse(x)); foreach (var id in ids) { _cacheService.AddToCache(id); } index.IndexItems(_valueSetBuilder.GetValueSets(_contentService.GetByIds(ids).ToArray())); } return(true); }
public void Initialize() { // Get the member index if (!_examineManager.TryGetIndex(Constants.UmbracoIndexes.MembersIndexName, out IIndex index)) { return; } // Add a custom fields var skills = new FieldDefinition("skills", FieldDefinitionTypes.FullText); index.FieldDefinitionCollection.AddOrUpdate(skills); var skillKeysValue = new FieldDefinition("skillKeys", FieldDefinitionTypes.InvariantCultureIgnoreCase); index.FieldDefinitionCollection.AddOrUpdate(skillKeysValue); var skillIdsValue = new FieldDefinition("skillIds", FieldDefinitionTypes.InvariantCultureIgnoreCase); index.FieldDefinitionCollection.AddOrUpdate(skillIdsValue); ((BaseIndexProvider)index).TransformingIndexValues += SGFMemberIndexComponent_TransformingIndexValues; }
public IEnumerable <DataListItem> GetItems(Dictionary <string, object> config) { var examineIndex = config.GetValueAs("examineIndex", UmbConstants.UmbracoIndexes.ExternalIndexName); if (_examineManager.TryGetIndex(examineIndex, out var index) == true) { var luceneQuery = config.GetValueAs("luceneQuery", string.Empty); if (string.IsNullOrWhiteSpace(luceneQuery) == false) { var nameField = config.GetValueAs("nameField", _defaultNameField); var valueField = config.GetValueAs("valueField", _defaultValueField); var iconField = config.GetValueAs("iconField", _defaultIconField); var descriptionField = config.GetValueAs("descriptionField", string.Empty); var results = index .GetSearcher() .CreateQuery() .NativeQuery(luceneQuery) // NOTE: For any `OrderBy` complaints, refer to: https://github.com/Shazwazza/Examine/issues/126 .OrderBy(new SortableField(nameField, SortType.String)) .Execute(); if (results?.TotalItemCount > 0) { return(results.Select(x => new DataListItem { Name = x.Values.ContainsKey(nameField) == true ? x.Values[nameField] : x.Values[_defaultNameField], Value = x.Values.ContainsKey(valueField) == true ? x.Values[valueField] : x.Values[_defaultValueField], Icon = x.Values.ContainsKey(iconField) == true ? x.Values[iconField] : x.Values[_defaultIconField], Description = x.Values.ContainsKey(descriptionField) == true ? x.Values[descriptionField] : null, })); } } } return(Enumerable.Empty <DataListItem>()); }
/// <summary> /// Returns the <see cref="ISearcher"/> as specified by the specified <paramref name="options"/>. /// /// If <paramref name="options"/> doesn't specify a searcher, the searcher of <c>ExternalIndex</c> will be used as fallback. /// </summary> /// <param name="options">The search options.</param> /// <returns>The <see cref="ISearcher"/> to be used for the search.</returns> protected virtual ISearcher GetSearcher(ISearchOptions options) { ISearcher searcher; switch (options) { case ISearcherOptions searcherOptions: searcher = searcherOptions.Searcher; if (searcher != null) { return(searcher); } break; case IGetSearcherOptions getSearcherOptions: searcher = getSearcherOptions.GetSearcher(_examine, this); if (searcher != null) { return(searcher); } break; default: if (_examine.TryGetIndex(ExamineConstants.ExternalIndexName, out IIndex index)) { searcher = index.GetSearcher(); if (searcher != null) { return(searcher); } } break; } throw new Exception($"Failed determining searcher from {options.GetType()}"); }
private ISearchResults GetResults() { if (_examineManager.TryGetIndex("ExternalIndex", out var index)) { var query = new StringBuilder(); query.Append("("); switch (_search.SearchType) { case SearchType.MultiRelevance: // We formulate the query differently depending on the input. if (_search.SearchTerm.Contains('"')) { // If the user has enetered double quotes we don't bother // searching for the full string query.Append(QueryAllPropertiesOr(_search.SearchTermSplit, 1)); } else if (!_search.SearchTerm.Contains('"') && !_search.SearchTerm.Contains(' ')) { // if there's no spaces or quotes we don't need to get the quoted term and boost it query.Append(QueryAllPropertiesOr(_search.SearchTermSplit, 1)); } else { // otherwise we search first for the entire query in quotes, // then for each term in the query OR'd together. query.AppendFormat("({0} OR {1})", QueryAllPropertiesOr(_search.SearchTermQuoted, 2) , QueryAllPropertiesOr(_search.SearchTermSplit, 1) ); } break; case SearchType.MultiAnd: if (_search.SearchTerm.Contains('"')) { // If the user has enetered double quotes we don't bother // searching for the full string query.Append(QueryAllPropertiesAnd(_search.SearchTermSplit, 1.0)); } else if (!_search.SearchTerm.Contains('"') && !_search.SearchTerm.Contains(' ')) { // if there's no spaces or quotes we don't need to get the quoted term and boost it query.Append(QueryAllPropertiesAnd(_search.SearchTermSplit, 1)); } else { // otherwise we search first for the entire query in quotes, // then for each term in the query OR'd together. query.AppendFormat("{0} OR {1}", QueryAllPropertiesAnd(_search.SearchTermQuoted, 2) , QueryAllPropertiesAnd(_search.SearchTermSplit, 1) ); } break; case SearchType.SimpleOr: query.Append(QueryAllProperties(_search.SearchTermSplit, 1.0, "OR", true)); break; case SearchType.AsEntered: query.Append(QueryAllPropertiesAnd(_search.SearchTermSplit, 1.0)); break; } query.Append(")"); if (_search.RootNodeIds.Any()) { var pathName = _fullTextConfig.GetPathFieldName(); var rootNodeGroup = string.Join(" OR ", _search.RootNodeIds.Select(x => string.Format("{0}:{1}", pathName, x.ToString()))); query.AppendFormat(" AND ({0})", rootNodeGroup); } query.Append($" AND (__IndexType:content AND __Published_{_search.Culture}:y)"); var searcher = index.GetSearcher(); _logger.Info <SearchService>("Trying to search for {query}", query.ToString()); return(searcher.CreateQuery().NativeQuery(query.ToString()).Execute(_search.PageLength * _currentPage)); } return(null); }
/// <summary> /// Searches Examine for results based on the entity type /// </summary> /// <param name="query"></param> /// <param name="entityType"></param> /// <param name="totalFound"></param> /// <param name="searchFrom"> /// A starting point for the search, generally a node id, but for members this is a member type alias /// </param> /// <param name="pageSize"></param> /// <param name="pageIndex"></param> /// <param name="ignoreUserStartNodes">If set to true, user and group start node permissions will be ignored.</param> /// <returns></returns> public IEnumerable <SearchResultEntity> ExamineSearch( string query, UmbracoEntityTypes entityType, int pageSize, long pageIndex, out long totalFound, string searchFrom = null, bool ignoreUserStartNodes = false) { var sb = new StringBuilder(); string type; var indexName = Constants.UmbracoIndexes.InternalIndexName; var fields = new List <string> { "id", "__NodeId", "__Key" }; // 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... //if (Examine.ExamineExtensions.TryParseLuceneQuery(query)) //{ //} //special GUID check since if a user searches on one specifically we need to escape it if (Guid.TryParse(query, out var g)) { query = "\"" + g.ToString() + "\""; } switch (entityType) { case UmbracoEntityTypes.Member: indexName = Constants.UmbracoIndexes.MembersIndexName; type = "member"; fields.AddRange(new[] { "email", "loginName" }); if (searchFrom != null && searchFrom != Constants.Conventions.MemberTypes.AllMembersListId && searchFrom.Trim() != "-1") { sb.Append("+__NodeTypeAlias:"); sb.Append(searchFrom); sb.Append(" "); } break; case UmbracoEntityTypes.Media: type = "media"; fields.AddRange(new[] { UmbracoExamineIndex.UmbracoFileFieldName }); var allMediaStartNodes = _umbracoContext.Security.CurrentUser.CalculateMediaStartNodeIds(_entityService); AppendPath(sb, UmbracoObjectTypes.Media, allMediaStartNodes, searchFrom, ignoreUserStartNodes, _entityService); break; case UmbracoEntityTypes.Document: type = "content"; var allContentStartNodes = _umbracoContext.Security.CurrentUser.CalculateContentStartNodeIds(_entityService); AppendPath(sb, UmbracoObjectTypes.Document, allContentStartNodes, searchFrom, ignoreUserStartNodes, _entityService); break; default: throw new NotSupportedException("The " + typeof(UmbracoTreeSearcher) + " currently does not support searching against object type " + entityType); } if (!_examineManager.TryGetIndex(indexName, out var index)) { throw new InvalidOperationException("No index found by name " + indexName); } var internalSearcher = index.GetSearcher(); if (!BuildQuery(sb, query, searchFrom, fields, type)) { totalFound = 0; return(Enumerable.Empty <SearchResultEntity>()); } 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 .Execute(Convert.ToInt32(pageSize * (pageIndex + 1))); totalFound = result.TotalItemCount; var pagedResult = result.Skip(Convert.ToInt32(pageIndex)); switch (entityType) { case UmbracoEntityTypes.Member: return(MemberFromSearchResults(pagedResult.ToArray())); case UmbracoEntityTypes.Media: return(MediaFromSearchResults(pagedResult)); case UmbracoEntityTypes.Document: return(ContentFromSearchResults(pagedResult)); default: throw new NotSupportedException("The " + typeof(UmbracoTreeSearcher) + " currently does not support searching against object type " + entityType); } }
public IEnumerable <ISearchResult> Search(string query, UmbracoEntityTypes entityType, int pageSize, long pageIndex, out long totalFound, string searchFrom = null, bool ignoreUserStartNodes = false) { var sb = new StringBuilder(); string type; var indexName = Constants.UmbracoIndexes.InternalIndexName; var fields = _treeSearcherFields.GetBackOfficeFields().ToList(); ISet <string> fieldsToLoad = new HashSet <string>(_treeSearcherFields.GetBackOfficeFieldsToLoad()); // 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... //if (Examine.ExamineExtensions.TryParseLuceneQuery(query)) //{ //} //special GUID check since if a user searches on one specifically we need to escape it if (Guid.TryParse(query, out var g)) { query = "\"" + g.ToString() + "\""; } var currentUser = _backOfficeSecurityAccessor?.BackOfficeSecurity?.CurrentUser; switch (entityType) { case UmbracoEntityTypes.Member: indexName = Constants.UmbracoIndexes.MembersIndexName; type = "member"; fields.AddRange(_treeSearcherFields.GetBackOfficeMembersFields()); foreach (var field in _treeSearcherFields.GetBackOfficeMembersFieldsToLoad()) { fieldsToLoad.Add(field); } if (searchFrom != null && searchFrom != Constants.Conventions.MemberTypes.AllMembersListId && searchFrom.Trim() != "-1") { sb.Append("+__NodeTypeAlias:"); sb.Append(searchFrom); sb.Append(" "); } break; case UmbracoEntityTypes.Media: type = "media"; fields.AddRange(_treeSearcherFields.GetBackOfficeMediaFields()); foreach (var field in _treeSearcherFields.GetBackOfficeMediaFieldsToLoad()) { fieldsToLoad.Add(field); } var allMediaStartNodes = currentUser != null ? currentUser.CalculateMediaStartNodeIds(_entityService, _appCaches) : Array.Empty <int>(); AppendPath(sb, UmbracoObjectTypes.Media, allMediaStartNodes, searchFrom, ignoreUserStartNodes, _entityService); break; case UmbracoEntityTypes.Document: type = "content"; fields.AddRange(_treeSearcherFields.GetBackOfficeDocumentFields()); foreach (var field in _treeSearcherFields.GetBackOfficeDocumentFieldsToLoad()) { fieldsToLoad.Add(field); } var allContentStartNodes = currentUser != null ? currentUser.CalculateContentStartNodeIds(_entityService, _appCaches) : Array.Empty <int>(); AppendPath(sb, UmbracoObjectTypes.Document, allContentStartNodes, searchFrom, ignoreUserStartNodes, _entityService); break; default: throw new NotSupportedException("The " + typeof(BackOfficeExamineSearcher) + " currently does not support searching against object type " + entityType); } if (!_examineManager.TryGetIndex(indexName, out var index)) { throw new InvalidOperationException("No index found by name " + indexName); } if (!BuildQuery(sb, query, searchFrom, fields, type)) { totalFound = 0; return(Enumerable.Empty <ISearchResult>()); } var result = index.Searcher .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(QueryOptions.SkipTake(Convert.ToInt32(pageSize * pageIndex), pageSize)); totalFound = result.TotalItemCount; var pagedResult = result.Skip(Convert.ToInt32(pageIndex)); return(pagedResult); }
public IEnumerable <IPublishedContent> Search(string term, string indexName, int blogArchiveNodeId, int pageSize, int pageIndex, out long totalResults) { var splitSearch = term.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); //The fields to search on and their 'weight' (importance) var fields = new Dictionary <string, int> { { "markdown", 2 }, { "richText", 2 }, { "nodeName", 3 }, { "tags", 1 }, { "categories", 1 }, { "umbracoUrlName", 3 } }; //The multipliers for match types const int exactMatch = 5; const int termMatch = 2; var fieldQuery = new StringBuilder(); //build field query foreach (var field in fields) { //full exact match (which has a higher boost) fieldQuery.Append($"{field.Key}:{"\"" + term + "\""}^{field.Value*exactMatch}"); fieldQuery.Append(" "); //NOTE: Phrase match wildcard isn't really supported unless you use the Lucene // API like ComplexPhraseWildcardSomethingOrOther... //split match foreach (var s in splitSearch) { //match on each term, no wildcard, higher boost fieldQuery.Append($"{field.Key}:{s}^{field.Value*termMatch}"); fieldQuery.Append(" "); //match on each term, with wildcard fieldQuery.Append($"{field.Key}:{s}*"); fieldQuery.Append(" "); } } indexName = indexName.IsNullOrWhiteSpace() ? Constants.UmbracoIndexes.ExternalIndexName : indexName; if (!_examineManager.TryGetIndex(indexName, out var index)) { throw new InvalidOperationException("No index found by name " + indexName); } var searcher = index.GetSearcher(); var criteria = searcher.CreateQuery() .Field("parentID", blogArchiveNodeId) .And() .NativeQuery($" +({fieldQuery})"); var searchResult = criteria.Execute( //don't return more results than we need for the paging pageSize * (pageIndex + 1)); var result = searchResult.ToPublishedSearchResults(_umbracoContext.PublishedSnapshot.Content); totalResults = searchResult.TotalItemCount; return(result.Select(x => x.Content)); }