/// <summary> /// This is used to refresh content indexers IndexData based on the DataService whenever a content type is changed since /// properties may have been added/removed /// </summary> /// <param name="sender"></param> /// <param name="e"></param> /// <remarks> /// See: http://issues.umbraco.org/issue/U4-4798 /// </remarks> static void ContentTypeCacheRefresherCacheUpdated(ContentTypeCacheRefresher sender, CacheRefresherEventArgs e) { var indexersToUpdated = ExamineManager.Instance.IndexProviderCollection.OfType <UmbracoContentIndexer>(); foreach (var provider in indexersToUpdated) { provider.RefreshIndexerDataFromDataService(); } }
/// <summary> /// Updates indexes based on content type changes /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void ContentTypeCacheRefresherUpdated(ContentTypeCacheRefresher sender, CacheRefresherEventArgs args) { if (Suspendable.ExamineEvents.CanIndex == false) { return; } if (args.MessageType != MessageType.RefreshByPayload) { throw new NotSupportedException(); } var changedIds = new Dictionary <string, (List <int> removedIds, List <int> refreshedIds, List <int> otherIds)>(); foreach (var payload in (ContentTypeCacheRefresher.JsonPayload[])args.MessageObject) { if (!changedIds.TryGetValue(payload.ItemType, out var idLists)) { idLists = (removedIds : new List <int>(), refreshedIds : new List <int>(), otherIds : new List <int>()); changedIds.Add(payload.ItemType, idLists); } if (payload.ChangeTypes.HasType(ContentTypeChangeTypes.Remove)) { idLists.removedIds.Add(payload.Id); } else if (payload.ChangeTypes.HasType(ContentTypeChangeTypes.RefreshMain)) { idLists.refreshedIds.Add(payload.Id); } else if (payload.ChangeTypes.HasType(ContentTypeChangeTypes.RefreshOther)) { idLists.otherIds.Add(payload.Id); } } const int pageSize = 500; foreach (var ci in changedIds) { if (ci.Value.refreshedIds.Count > 0 || ci.Value.otherIds.Count > 0) { switch (ci.Key) { case var itemType when itemType == typeof(IContentType).Name: RefreshContentOfContentTypes(ci.Value.refreshedIds.Concat(ci.Value.otherIds).Distinct().ToArray()); break; case var itemType when itemType == typeof(IMediaType).Name: RefreshMediaOfMediaTypes(ci.Value.refreshedIds.Concat(ci.Value.otherIds).Distinct().ToArray()); break; case var itemType when itemType == typeof(IMemberType).Name: RefreshMemberOfMemberTypes(ci.Value.refreshedIds.Concat(ci.Value.otherIds).Distinct().ToArray()); break; } } //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 <IUmbracoIndex>()) { var searcher = index.GetSearcher(); var page = 0; var total = long.MaxValue; while (page * pageSize < total) { //paging with examine, see https://shazwazza.com/post/paging-with-examine/ var results = searcher.CreateQuery().Field("nodeType", id.ToInvariantString()).Execute(maxResults: pageSize * (page + 1)); total = results.TotalItemCount; var paged = results.Skip(page * pageSize); foreach (var item in paged) { if (int.TryParse(item.Id, out var contentId)) { DeleteIndexForEntity(contentId, false); } } page++; } } } } }
/// <summary> /// This is used to refresh content indexers IndexData based on the DataService whenever a content type is changed since /// properties may have been added/removed, then we need to re-index any required data if aliases have been changed /// </summary> /// <param name="sender"></param> /// <param name="e"></param> /// <remarks> /// See: http://issues.umbraco.org/issue/U4-4798, http://issues.umbraco.org/issue/U4-7833 /// </remarks> static void ContentTypeCacheRefresherCacheUpdated(ContentTypeCacheRefresher sender, CacheRefresherEventArgs e) { if (Suspendable.ExamineEvents.CanIndex == false) { return; } var indexersToUpdated = ExamineManager.Instance.IndexProviderCollection.OfType <UmbracoContentIndexer>(); foreach (var provider in indexersToUpdated) { provider.RefreshIndexerDataFromDataService(); } if (e.MessageType == MessageType.RefreshByJson) { var contentTypesChanged = new HashSet <string>(); var mediaTypesChanged = new HashSet <string>(); var memberTypesChanged = new HashSet <string>(); var payloads = ContentTypeCacheRefresher.DeserializeFromJsonPayload(e.MessageObject.ToString()); foreach (var payload in payloads) { if (payload.IsNew == false && (payload.WasDeleted || payload.AliasChanged || payload.PropertyRemoved || payload.PropertyTypeAliasChanged)) { //if we get here it means that some aliases have changed and the indexes for those particular doc types will need to be updated if (payload.Type == typeof(IContentType).Name) { //if it is content contentTypesChanged.Add(payload.Alias); } else if (payload.Type == typeof(IMediaType).Name) { //if it is media mediaTypesChanged.Add(payload.Alias); } else if (payload.Type == typeof(IMemberType).Name) { //if it is members memberTypesChanged.Add(payload.Alias); } } } //TODO: We need to update Examine to support re-indexing multiple items at once instead of one by one which will speed up // the re-indexing process, we don't want to revert to rebuilding the whole thing! if (contentTypesChanged.Count > 0) { foreach (var alias in contentTypesChanged) { var ctType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(alias); if (ctType != null) { var contentItems = ApplicationContext.Current.Services.ContentService.GetContentOfContentType(ctType.Id); foreach (var contentItem in contentItems) { ReIndexForContent(contentItem, contentItem.HasPublishedVersion && contentItem.Trashed == false); } } } } if (mediaTypesChanged.Count > 0) { foreach (var alias in mediaTypesChanged) { var ctType = ApplicationContext.Current.Services.ContentTypeService.GetMediaType(alias); if (ctType != null) { var mediaItems = ApplicationContext.Current.Services.MediaService.GetMediaOfMediaType(ctType.Id); foreach (var mediaItem in mediaItems) { ReIndexForMedia(mediaItem, mediaItem.Trashed == false); } } } } if (memberTypesChanged.Count > 0) { foreach (var alias in memberTypesChanged) { var ctType = ApplicationContext.Current.Services.MemberTypeService.Get(alias); if (ctType != null) { var memberItems = ApplicationContext.Current.Services.MemberService.GetMembersByMemberType(ctType.Id); foreach (var memberItem in memberItems) { ReIndexForMember(memberItem); } } } } } }