From 628ce5ea1fb9e7405a90ea593983a68951397c3f Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 26 May 2016 15:30:40 +0200 Subject: [PATCH] Backports some changes from v8 so that we can perform a nice strongly typed query with paging - this is then used for the content indexer to index content via the db for published content instead of the xml cache system. This was already done in v8 but have no backported the logic and fixed up the unit tests. When merging with v8 we will most likely just keep all v8 stuff and discard these changes, but we'll need to compare just in case. All tests pass and re-indexing is working as expected. Also updated the paging count from 1000 to 5000 for reindexing. --- .../Repositories/ContentRepository.cs | 20 +++--- .../Interfaces/IContentRepository.cs | 4 +- .../Repositories/VersionableRepositoryBase.cs | 22 ++++++- src/Umbraco.Core/Services/ContentService.cs | 46 +++++++++++++- src/Umbraco.Core/Services/IContentService.cs | 16 +++++ .../Repositories/ContentRepositoryTest.cs | 8 ++- .../LegacyExamineBackedMediaTests.cs | 20 +++--- .../UmbracoExamine/EventsTest.cs | 28 +++++---- .../UmbracoExamine/ExamineBaseTest.cs | 28 +++++---- .../UmbracoExamine/IndexInitializer.cs | 45 +++++++++++++- src/Umbraco.Tests/UmbracoExamine/IndexTest.cs | 31 +++++----- src/UmbracoExamine/BaseUmbracoIndexer.cs | 30 +++------ src/UmbracoExamine/UmbracoContentIndexer.cs | 62 ++++++++++--------- 13 files changed, 239 insertions(+), 121 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index 5f96cad114..1a1a7b00bf 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -771,22 +771,22 @@ namespace Umbraco.Core.Persistence.Repositories /// Search text filter /// An Enumerable list of objects public IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, - string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "") + string orderBy, Direction orderDirection, bool orderBySystemField, IQuery filter = null) { //NOTE: This uses the GetBaseQuery method but that does not take into account the required 'newest' field which is // what we always require for a paged result, so we'll ensure it's included in the filter - - var args = new List(); - var sbWhere = new StringBuilder("AND (cmsDocument.newest = 1)"); - - if (filter.IsNullOrWhiteSpace() == false) + + var filterSql = new Sql().Append("AND (cmsDocument.newest = 1)"); + if (filter != null) { - sbWhere.Append(" AND (cmsDocument." + SqlSyntax.GetQuotedColumnName("text") + " LIKE @" + args.Count + ")"); - args.Add("%" + filter + "%"); + foreach (var filterClaus in filter.GetWhereClauses()) + { + filterSql.Append(string.Format("AND ({0})", filterClaus.Item1), filterClaus.Item2); + } } - - Func> filterCallback = () => new Tuple(sbWhere.ToString(), args.ToArray()); + + Func> filterCallback = () => new Tuple(filterSql.SQL, filterSql.Arguments); return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, new Tuple("cmsDocument", "nodeId"), diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs index ab176df6d0..c18765239b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs @@ -85,9 +85,9 @@ namespace Umbraco.Core.Persistence.Repositories /// Field to order by /// Direction to order by /// Flag to indicate when ordering by system field - /// Search text filter + /// /// An Enumerable list of objects IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, - string orderBy, Direction orderDirection, bool orderBySystemField, string filter = ""); + string orderBy, Direction orderDirection, bool orderBySystemField, IQuery filter = null); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs index 4b2befb3e3..e062f49235 100644 --- a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs @@ -235,13 +235,29 @@ namespace Umbraco.Core.Persistence.Repositories private Sql GetFilteredSqlForPagedResults(Sql sql, Func> defaultFilter = null) { - //copy to var so that the original isn't changed - var filteredSql = new Sql(sql.SQL, sql.Arguments); + Sql filteredSql; + // Apply filter if (defaultFilter != null) { var filterResult = defaultFilter(); - filteredSql.Append(filterResult.Item1, filterResult.Item2); + + //NOTE: this is certainly strange - NPoco handles this much better but we need to re-create the sql + // instance a couple of times to get the parameter order correct, for some reason the first + // time the arguments don't show up correctly but the SQL argument parameter names are actually updated + // accordingly - so we re-create it again. In v8 we don't need to do this and it's already taken care of. + + filteredSql = new Sql(sql.SQL, sql.Arguments); + var args = filteredSql.Arguments.Concat(filterResult.Item2).ToArray(); + filteredSql = new Sql( + string.Format("{0} {1}", filteredSql.SQL, filterResult.Item1), + args); + filteredSql = new Sql(filteredSql.SQL, args); + } + else + { + //copy to var so that the original isn't changed + filteredSql = new Sql(sql.SQL, sql.Arguments); } return filteredSql; } diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index bbae07eb6a..7fcb915b30 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -536,7 +536,12 @@ namespace Umbraco.Core.Services { query.Where(x => x.ParentId == id); } - var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter); + IQuery filterQuery = null; + if (filter.IsNullOrWhiteSpace() == false) + { + filterQuery = Query.Builder.Where(x => x.Name.Contains(filter)); + } + var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filterQuery); return contents; } @@ -593,12 +598,49 @@ namespace Umbraco.Core.Services { query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar)); } - var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter); + IQuery filterQuery = null; + if (filter.IsNullOrWhiteSpace() == false) + { + filterQuery = Query.Builder.Where(x => x.Name.Contains(filter)); + } + var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filterQuery); return contents; } } + /// + /// Gets a collection of objects by Parent Id + /// + /// Id of the Parent to retrieve Descendants from + /// Page number + /// Page size + /// Total records query would return without paging + /// Field to order by + /// Direction to order by + /// Flag to indicate when ordering by system field + /// Search filter + /// An Enumerable list of objects + public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy, Direction orderDirection, bool orderBySystemField, IQuery filter) + { + Mandate.ParameterCondition(pageIndex >= 0, "pageIndex"); + Mandate.ParameterCondition(pageSize > 0, "pageSize"); + + using (var repository = RepositoryFactory.CreateContentRepository(UowProvider.GetUnitOfWork())) + { + var query = Query.Builder; + + //if the id is System Root, then just get all + if (id != Constants.System.Root) + { + query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar)); + } + var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter); + + return contents; + } + } + /// /// Gets a collection of objects by its name or partial name /// diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index df70fa8094..5e90559233 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Publishing; namespace Umbraco.Core.Services @@ -268,6 +269,21 @@ namespace Umbraco.Core.Services IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection, bool orderBySystemField, string filter); + /// + /// Gets a collection of objects by Parent Id + /// + /// Id of the Parent to retrieve Descendants from + /// Page number + /// Page size + /// Total records query would return without paging + /// Field to order by + /// Direction to order by + /// Flag to indicate when ordering by system field + /// + /// An Enumerable list of objects + IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalRecords, + string orderBy, Direction orderDirection, bool orderBySystemField, IQuery filter); + /// /// Gets a collection of an objects versions by its Id /// diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index d29b073df7..2d036bb620 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -685,8 +685,10 @@ namespace Umbraco.Tests.Persistence.Repositories { // Act var query = Query.Builder.Where(x => x.Level == 2); + var filterQuery = Query.Builder.Where(x => x.Name.Contains("Page 2")); + long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, true, "Page 2"); + var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, true, filterQuery); // Assert Assert.That(totalRecords, Is.EqualTo(1)); @@ -706,8 +708,10 @@ namespace Umbraco.Tests.Persistence.Repositories { // Act var query = Query.Builder.Where(x => x.Level == 2); + var filterQuery = Query.Builder.Where(x => x.Name.Contains("Page")); + long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, true, "Page"); + var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, true, filterQuery); // Assert Assert.That(totalRecords, Is.EqualTo(2)); diff --git a/src/Umbraco.Tests/PublishedContent/LegacyExamineBackedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/LegacyExamineBackedMediaTests.cs index 7b0ffb41d7..8a83bea75a 100644 --- a/src/Umbraco.Tests/PublishedContent/LegacyExamineBackedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/LegacyExamineBackedMediaTests.cs @@ -7,14 +7,17 @@ using NUnit.Framework; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.UmbracoExamine; using umbraco.MacroEngines; +using Umbraco.Core; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.Mappers; namespace Umbraco.Tests.PublishedContent { public class LegacyExamineBackedMediaTests : ExamineBaseTest { - public override void TestSetup() + public override void Initialize() { - base.TestSetup(); + base.Initialize(); var settings = SettingsForTests.GenerateMockSettings(); var contentMock = Mock.Get(settings.Content); @@ -22,13 +25,8 @@ namespace Umbraco.Tests.PublishedContent contentMock.Setup(x => x.UmbracoLibraryCacheDuration).Returns(1800); SettingsForTests.ConfigureSettings(settings); } - - public override void TestTearDown() - { - SettingsForTests.Reset(); - base.TestTearDown(); - } - + + [Test] public void Ensure_Children_Are_Sorted() { @@ -47,7 +45,9 @@ namespace Umbraco.Tests.PublishedContent var children = backedMedia.ChildrenAsList.Value; var currSort = 0; - for (var i = 0; i < children.Count(); i++) + Assert.Greater(children.Count, 0); + + for (var i = 0; i < children.Count; i++) { Assert.GreaterOrEqual(children[i].SortOrder, currSort); currSort = children[i].SortOrder; diff --git a/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs b/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs index d01b298bb4..6bd01c7f1c 100644 --- a/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs @@ -45,19 +45,21 @@ namespace Umbraco.Tests.UmbracoExamine private static UmbracoContentIndexer _indexer; private Lucene.Net.Store.Directory _luceneDir; - public override void TestSetup() - { - base.TestSetup(); - _luceneDir = new RAMDirectory(); - _indexer = IndexInitializer.GetUmbracoIndexer(_luceneDir); - _indexer.RebuildIndex(); - _searcher = IndexInitializer.GetUmbracoSearcher(_luceneDir); - } + public override void Initialize() + { + base.Initialize(); - public override void TestTearDown() - { - base.TestTearDown(); - _luceneDir.Dispose(); - } + _luceneDir = new RAMDirectory(); + _indexer = IndexInitializer.GetUmbracoIndexer(_luceneDir); + _indexer.RebuildIndex(); + _searcher = IndexInitializer.GetUmbracoSearcher(_luceneDir); + } + + public override void TearDown() + { + base.TearDown(); + _luceneDir.Dispose(); + } + } } \ No newline at end of file diff --git a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs index 5fed998194..ec3babc7ab 100644 --- a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs @@ -1,5 +1,9 @@ -using NUnit.Framework; +using Moq; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; +using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; using UmbracoExamine; @@ -7,29 +11,27 @@ using UmbracoExamine; namespace Umbraco.Tests.UmbracoExamine { [TestFixture] - public abstract class ExamineBaseTest : BaseUmbracoConfigurationTest + public abstract class ExamineBaseTest : BaseDatabaseFactoryTest { - - [SetUp] - public virtual void TestSetup() + /// + /// sets up resolvers before resolution is frozen + /// + protected override void FreezeResolution() { UmbracoExamineSearcher.DisableInitializationCheck = true; BaseUmbracoIndexer.DisableInitializationCheck = true; ShortStringHelperResolver.Current = new ShortStringHelperResolver(new DefaultShortStringHelper(SettingsForTests.GetDefault())); - Resolution.Freeze(); + base.FreezeResolution(); } - [TearDown] - public virtual void TestTearDown() + public override void TearDown() { + base.TearDown(); + UmbracoExamineSearcher.DisableInitializationCheck = null; BaseUmbracoIndexer.DisableInitializationCheck = null; - - //reset all resolvers - ResolverCollection.ResetAll(); - //reset resolution itself (though this should be taken care of by resetting any of the resolvers above) - Resolution.Reset(); } + } } \ No newline at end of file diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs index 9990c58a43..b303eed997 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs @@ -10,6 +10,7 @@ using Moq; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Services; using UmbracoExamine; using UmbracoExamine.Config; @@ -41,7 +42,48 @@ namespace Umbraco.Tests.UmbracoExamine } if (contentService == null) { - contentService = Mock.Of(); + long longTotalRecs; + int intTotalRecs; + + var allRecs = dataService.ContentService.GetLatestContentByXPath("//*[@isDoc]") + .Root + .Elements() + .Select(x => Mock.Of( + m => + m.Id == (int)x.Attribute("id") && + m.ParentId == (int)x.Attribute("parentID") && + m.Level == (int)x.Attribute("level") && + m.CreatorId == 0 && + m.SortOrder == (int)x.Attribute("sortOrder") && + m.CreateDate == (DateTime)x.Attribute("createDate") && + m.UpdateDate == (DateTime)x.Attribute("updateDate") && + m.Name == (string)x.Attribute("nodeName") && + m.Path == (string)x.Attribute("path") && + m.Properties == new PropertyCollection() && + m.ContentType == Mock.Of(mt => + mt.Alias == x.Name.LocalName && + mt.Id == (int)x.Attribute("nodeType") && + mt.Icon == "test"))) + .ToArray(); + + + contentService = Mock.Of( + x => x.GetPagedDescendants( + It.IsAny(), It.IsAny(), It.IsAny(), out longTotalRecs, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()) + == + allRecs + && x.GetPagedDescendants( + It.IsAny(), It.IsAny(), It.IsAny(), out longTotalRecs, It.IsAny(), It.IsAny(), It.IsAny()) + == + allRecs + && x.GetPagedDescendants( + It.IsAny(), It.IsAny(), It.IsAny(), out intTotalRecs, It.IsAny(), It.IsAny(), It.IsAny()) + == + allRecs + && x.GetPagedDescendants( + It.IsAny(), It.IsAny(), It.IsAny(), out longTotalRecs, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>()) + == + allRecs); } if (userService == null) { @@ -86,7 +128,6 @@ namespace Umbraco.Tests.UmbracoExamine It.IsAny(), It.IsAny(), It.IsAny(), out intTotalRecs, It.IsAny(), It.IsAny(), It.IsAny()) == allRecs); - } if (dataTypeService == null) { diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs b/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs index a5418649fe..6cef19af9e 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs @@ -142,8 +142,6 @@ namespace Umbraco.Tests.UmbracoExamine { var s = (IndexSearcher)_searcher.GetSearcher(); - - //first delete all 'Content' (not media). This is done by directly manipulating the index with the Lucene API, not examine! var contentTerm = new Term(LuceneIndexer.IndexTypeFieldName, IndexTypes.Content); @@ -207,23 +205,24 @@ namespace Umbraco.Tests.UmbracoExamine private Lucene.Net.Store.Directory _luceneDir; - public override void TestTearDown() - { - base.TestTearDown(); - _luceneDir.Dispose(); + public override void TearDown() + { + base.TearDown(); + _luceneDir.Dispose(); UmbracoExamineSearcher.DisableInitializationCheck = null; BaseUmbracoIndexer.DisableInitializationCheck = null; - } - - public override void TestSetup() - { - base.TestSetup(); - _luceneDir = new RAMDirectory(); - _indexer = IndexInitializer.GetUmbracoIndexer(_luceneDir); - _indexer.RebuildIndex(); - _searcher = IndexInitializer.GetUmbracoSearcher(_luceneDir); - } + } + + public override void Initialize() + { + base.Initialize(); + _luceneDir = new RAMDirectory(); + _indexer = IndexInitializer.GetUmbracoIndexer(_luceneDir); + _indexer.RebuildIndex(); + _searcher = IndexInitializer.GetUmbracoSearcher(_luceneDir); + } + #endregion } diff --git a/src/UmbracoExamine/BaseUmbracoIndexer.cs b/src/UmbracoExamine/BaseUmbracoIndexer.cs index ee77f5d05c..26763bd7cd 100644 --- a/src/UmbracoExamine/BaseUmbracoIndexer.cs +++ b/src/UmbracoExamine/BaseUmbracoIndexer.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Net; using System.Security; @@ -361,10 +362,11 @@ namespace UmbracoExamine /// protected override void PerformIndexAll(string type) { - //NOTE: the logic below is ONLY used for published content, for media and members and non-published content, this method is overridden + //NOTE: the logic below is NOT used, this method is overridden // and we query directly against the umbraco service layer. + // This is here for backwards compat only. - if (!SupportedTypes.Contains(type)) + if (SupportedTypes.Contains(type) == false) return; var xPath = "//*[(number(@id) > 0 and (@isDoc or @nodeTypeAlias)){0}]"; //we'll add more filters to this below if needed @@ -417,16 +419,11 @@ namespace UmbracoExamine AddNodesToIndex(xPath, type); } - /// - /// Returns an XDocument for the entire tree stored for the IndexType specified. - /// - /// The xpath to the node. - /// The type of data to request from the data service. - /// Either the Content or Media xml. If the type is not of those specified null is returned + [Obsolete("This method is not be used, it will be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] protected virtual XDocument GetXDocument(string xPath, string type) { - //TODO: We need to get rid of this! it will now only ever be called for published content - but we're keeping the other - // logic here for backwards compatibility in case inheritors are calling this for some reason. + //TODO: We need to get rid of this! This does not get called by our code if (type == IndexTypes.Content) { @@ -447,12 +444,9 @@ namespace UmbracoExamine } #endregion - #region Private - /// - /// Adds all nodes with the given xPath root. - /// - /// The x path. - /// The type. + + [Obsolete("This method is not be used, it will be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] private void AddNodesToIndex(string xPath, string type) { // Get all the nodes of nodeTypeAlias == nodeTypeAlias @@ -476,9 +470,5 @@ namespace UmbracoExamine } } - - - - #endregion } } diff --git a/src/UmbracoExamine/UmbracoContentIndexer.cs b/src/UmbracoExamine/UmbracoContentIndexer.cs index 613304c4ff..92a1fb776e 100644 --- a/src/UmbracoExamine/UmbracoContentIndexer.cs +++ b/src/UmbracoExamine/UmbracoContentIndexer.cs @@ -25,6 +25,7 @@ using UmbracoExamine.Config; using Examine.LuceneEngine.Providers; using Lucene.Net.Analysis; using umbraco.BasePages; +using Umbraco.Core.Persistence.Querying; using IContentService = Umbraco.Core.Services.IContentService; using UmbracoExamine.LocalStorage; using IMediaService = Umbraco.Core.Services.IMediaService; @@ -348,50 +349,55 @@ namespace UmbracoExamine protected override void PerformIndexAll(string type) { - - const int pageSize = 1000; + const int pageSize = 5000; var pageIndex = 0; switch (type) { case IndexTypes.Content: - if (this.SupportUnpublishedContent == false) + + + var contentParentId = -1; + if (IndexerData.ParentNodeId.HasValue && IndexerData.ParentNodeId.Value > 0) { - //use the base implementation which will use the published XML cache to perform the lookups - base.PerformIndexAll(type); + contentParentId = IndexerData.ParentNodeId.Value; } - else + IContent[] content; + + do { - var contentParentId = -1; - if (IndexerData.ParentNodeId.HasValue && IndexerData.ParentNodeId.Value > 0) + long total; + + IEnumerable descendants; + if (SupportUnpublishedContent) { - contentParentId = IndexerData.ParentNodeId.Value; + descendants = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out total); } - IContent[] content; - - do + else { - long total; - var descendants = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out total); + //add the published filter + var qry = Query.Builder.Where(x => x.Published == true); - //if specific types are declared we need to post filter them - //TODO: Update the service layer to join the cmsContentType table so we can query by content type too - if (IndexerData.IncludeNodeTypes.Any()) - { - content = descendants.Where(x => IndexerData.IncludeNodeTypes.Contains(x.ContentType.Alias)).ToArray(); - } - else - { - content = descendants.ToArray(); - } + descendants = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out total, "Path", Direction.Ascending, true, qry); + } - AddNodesToIndex(GetSerializedContent(content), type); - pageIndex++; + //if specific types are declared we need to post filter them + //TODO: Update the service layer to join the cmsContentType table so we can query by content type too + if (IndexerData.IncludeNodeTypes.Any()) + { + content = descendants.Where(x => IndexerData.IncludeNodeTypes.Contains(x.ContentType.Alias)).ToArray(); + } + else + { + content = descendants.ToArray(); + } + + AddNodesToIndex(GetSerializedContent(content), type); + pageIndex++; - } while (content.Length == pageSize); + } while (content.Length == pageSize); - } break; case IndexTypes.Media: