diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs index 860dcd46f8..2a3dc1819b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs @@ -89,7 +89,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// An Enumerable list of objects IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, - string orderBy, Direction orderDirection, bool orderBySystemField, string filter, object[] filterArgs); + string orderBy, Direction orderDirection, bool orderBySystemField, string filter = null, object[] filterArgs = null); /// /// Returns the persisted content's preview XML structure diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMediaRepository.cs index 816cb12f44..bf7ae1472d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMediaRepository.cs @@ -35,9 +35,10 @@ 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, string filter = null, object[] filterArgs = null); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs index 62257f08e2..c10c11e992 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -489,15 +489,18 @@ 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 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, string filter = null, object[] filterArgs = null) { - var filterSql = filter.IsNullOrWhiteSpace() - ? null - : Sql().Append("AND (umbracoNode." + SqlSyntax.GetQuotedColumnName("text") + " LIKE @0)", "%" + filter + "%"); - + Sql filterSql = null; + if (filter.IsNullOrWhiteSpace() == false) + { + filterSql = Sql().Append($"AND ({filter})", filterArgs); + } + return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, MapQueryDtos, orderBy, orderDirection, orderBySystemField, filterSql); diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 8df66ddf87..e404a53616 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -506,7 +506,7 @@ namespace Umbraco.Core.Services if (filter.IsNullOrWhiteSpace() == false) { //add the default text filter - f = $"cmsDocument.{RepositoryFactory.SqlSyntax.GetQuotedColumnName("text")}=@0"; + f = $"cmsDocument.{RepositoryFactory.SqlSyntax.GetQuotedColumnName("text")} LIKE @0"; fa = new object[] { $"%{filter}%" }; } return GetPagedChildren(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, f, fa); @@ -564,7 +564,7 @@ namespace Umbraco.Core.Services if (filter.IsNullOrWhiteSpace() == false) { //add the default text filter - f = $"cmsDocument.{RepositoryFactory.SqlSyntax.GetQuotedColumnName("text")}=@0"; + f = $"cmsDocument.{RepositoryFactory.SqlSyntax.GetQuotedColumnName("text")} LIKE @0"; fa = new object[] { $"%{filter}%" }; } return GetPagedDescendants(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, f, fa); diff --git a/src/Umbraco.Core/Services/IMediaService.cs b/src/Umbraco.Core/Services/IMediaService.cs index 645bcfd1e0..18505a7bfa 100644 --- a/src/Umbraco.Core/Services/IMediaService.cs +++ b/src/Umbraco.Core/Services/IMediaService.cs @@ -142,10 +142,11 @@ namespace Umbraco.Core.Services /// 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 GetPagedChildren(int id, long pageIndex, int pageSize, out long totalRecords, - string orderBy, Direction orderDirection, bool orderBySystemField, string filter); + string orderBy, Direction orderDirection, bool orderBySystemField, string filter, object[] filterArgs); /// /// Gets a collection of objects by Parent Id @@ -171,10 +172,11 @@ namespace Umbraco.Core.Services /// 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 GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalRecords, - string orderBy, Direction orderDirection, bool orderBySystemField, string filter); + string orderBy, Direction orderDirection, bool orderBySystemField, string filter, object[] filterArgs); /// /// Gets descendants of a object by its Id diff --git a/src/Umbraco.Core/Services/MediaService.cs b/src/Umbraco.Core/Services/MediaService.cs index 2a459174c0..84e090aecf 100644 --- a/src/Umbraco.Core/Services/MediaService.cs +++ b/src/Umbraco.Core/Services/MediaService.cs @@ -409,7 +409,15 @@ namespace Umbraco.Core.Services public IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy, Direction orderDirection, string filter = "") { - return GetPagedChildren(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filter); + string f = filter; + object[] fa = null; + if (filter.IsNullOrWhiteSpace() == false) + { + //add the default text filter + f = $"umbracoNode.{RepositoryFactory.SqlSyntax.GetQuotedColumnName("text")} LIKE @0"; + fa = new object[] { $"%{filter}%" }; + } + return GetPagedChildren(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, f, fa); } /// @@ -422,10 +430,11 @@ namespace Umbraco.Core.Services /// Field to order by /// Direction to order by /// Flag to indicate when ordering by system field - /// Search text filter + /// + /// /// An Enumerable list of objects public IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren, - string orderBy, Direction orderDirection, bool orderBySystemField, string filter) + string orderBy, Direction orderDirection, bool orderBySystemField, string filter, object[] filterArgs) { Mandate.ParameterCondition(pageIndex >= 0, "pageIndex"); Mandate.ParameterCondition(pageSize > 0, "pageSize"); @@ -453,7 +462,15 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "") { - return GetPagedDescendants(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filter); + string f = filter; + object[] fa = null; + if (filter.IsNullOrWhiteSpace() == false) + { + //add the default text filter + f = $"umbracoNode.{RepositoryFactory.SqlSyntax.GetQuotedColumnName("text")} LIKE @0"; + fa = new object[] { $"%{filter}%" }; + } + return GetPagedDescendants(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, f, fa); } /// @@ -466,9 +483,10 @@ namespace Umbraco.Core.Services /// Field to order by /// Direction to order by /// Flag to indicate when ordering by system field - /// Search text filter + /// + /// /// An Enumerable list of objects - public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy, Direction orderDirection, bool orderBySystemField, string filter) + public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy, Direction orderDirection, bool orderBySystemField, string filter, object[] filterArgs) { Mandate.ParameterCondition(pageIndex >= 0, "pageIndex"); Mandate.ParameterCondition(pageSize > 0, "pageSize"); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index f9244c3987..a47e3ac7d6 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -699,7 +699,10 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = repository.Query.Where(x => x.Level == 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, + $"cmsDocument.{SqlSyntax.GetQuotedColumnName("text")} LIKE @0", + new object[] { "%Page 2%" }); // Assert Assert.That(totalRecords, Is.EqualTo(1)); @@ -720,7 +723,9 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = repository.Query.Where(x => x.Level == 2); 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, + $"cmsDocument.{SqlSyntax.GetQuotedColumnName("text")} LIKE @0", + new object[] { "%Page%" }); // Assert Assert.That(totalRecords, Is.EqualTo(2)); diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index 116dd2e582..5d31d3cabc 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -424,7 +424,9 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = new Query(SqlSyntax, MappingResolver).Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, true, "File"); + var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, true, + $"umbracoNode.{SqlSyntax.GetQuotedColumnName("text")} LIKE @0", + new object[] { "%File%" }); // Assert Assert.That(totalRecords, Is.EqualTo(1)); @@ -445,7 +447,9 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = new Query(SqlSyntax, MappingResolver).Where(x => x.Level == 2); long totalRecords; - var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, true, "Test"); + var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, true, + $"umbracoNode.{SqlSyntax.GetQuotedColumnName("text")} LIKE @0", + new object[] { "%Test%" }); // Assert Assert.That(totalRecords, Is.EqualTo(2)); diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs index 4667b0f301..7d78e33e04 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs @@ -68,8 +68,15 @@ namespace Umbraco.Tests.UmbracoExamine x => x.GetPagedDescendants( It.IsAny(), It.IsAny(), It.IsAny(), out totalRecs, It.IsAny(), It.IsAny(), It.IsAny()) == - allRecs); - } + allRecs + + && + + x.GetPagedDescendants( + It.IsAny(), It.IsAny(), It.IsAny(), out totalRecs, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()) + == + allRecs); + } if (userService == null) { userService = Mock.Of(x => x.GetProfileById(It.IsAny()) == Mock.Of(p => p.Id == (object)0 && p.Name == "admin")); @@ -105,6 +112,13 @@ namespace Umbraco.Tests.UmbracoExamine x => x.GetPagedDescendants( It.IsAny(), It.IsAny(), It.IsAny(), out totalRecs, It.IsAny(), It.IsAny(), It.IsAny()) == + allRecs + + && + + x.GetPagedDescendants( + It.IsAny(), It.IsAny(), It.IsAny(), out totalRecs, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()) + == allRecs); } diff --git a/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs b/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs index b85e8cc2ea..55e9bdec50 100644 --- a/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs +++ b/src/Umbraco.Tests/UmbracoExamine/SearchTests.cs @@ -49,7 +49,7 @@ namespace Umbraco.Tests.UmbracoExamine .ToArray(); var contentService = Mock.Of( x => x.GetPagedDescendants( - It.IsAny(), It.IsAny(), It.IsAny(), out totalRecs, It.IsAny(), It.IsAny(), It.IsAny()) + It.IsAny(), It.IsAny(), It.IsAny(), out totalRecs, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()) == allRecs); diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 95884774a5..1e1590bf7a 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -195,7 +195,7 @@ namespace Umbraco.Web.Editors if (filter.IsNullOrWhiteSpace() == false) { //add the default text filter - f = $"cmsDocument.{DatabaseContext.SqlSyntax.GetQuotedColumnName("text")}=@0"; + f = $"cmsDocument.{DatabaseContext.SqlSyntax.GetQuotedColumnName("text")} LIKE @0"; fa = new object[] { $"%{filter}%" }; } diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index ca1f9ec251..6150c13dff 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -390,9 +390,10 @@ namespace Umbraco.Web.Editors sb.Append(type); - var raw = internalSearcher.CreateCriteria().RawQuery(sb.ToString()).MaxCount(200); + var raw = internalSearcher.CreateCriteria().RawQuery(sb.ToString()) + //limit results to 200 to avoid huge over processing (CPU) + .MaxCount(200); - //limit results to 200 to avoid huge over processing (CPU) var result = internalSearcher.Find(raw); switch (entityType) diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index dbdd9bea40..a7536cbd6b 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -186,9 +186,21 @@ namespace Umbraco.Web.Editors IMedia[] children; if (pageNumber > 0 && pageSize > 0) { + string f = filter; + object[] fa = null; + if (filter.IsNullOrWhiteSpace() == false) + { + //add the default text filter + f = $"umbracoNode.{DatabaseContext.SqlSyntax.GetQuotedColumnName("text")} LIKE @0"; + fa = new object[] { $"%{filter}%" }; + } + children = Services.MediaService - .GetPagedChildren(id, (pageNumber - 1), pageSize, out totalChildren - , orderBy, orderDirection, orderBySystemField, filter).ToArray(); + .GetPagedChildren( + id, (pageNumber - 1), pageSize, + out totalChildren, + orderBy, orderDirection, orderBySystemField, + f, fa).ToArray(); } else { diff --git a/src/UmbracoExamine/UmbracoContentIndexer.cs b/src/UmbracoExamine/UmbracoContentIndexer.cs index 0c84efc586..7c6a64e4f5 100644 --- a/src/UmbracoExamine/UmbracoContentIndexer.cs +++ b/src/UmbracoExamine/UmbracoContentIndexer.cs @@ -168,13 +168,7 @@ namespace UmbracoExamine protected set { _parentId = value; } } - protected override IEnumerable SupportedTypes - { - get - { - return new[] { IndexTypes.Content, IndexTypes.Media }; - } - } + protected override IEnumerable SupportedTypes => new[] {IndexTypes.Content, IndexTypes.Media}; #endregion @@ -194,14 +188,14 @@ namespace UmbracoExamine public override void DeleteFromIndex(string nodeId) { //find all descendants based on path - var descendantPath = string.Format(@"\-1\,*{0}\,*", nodeId); - var rawQuery = string.Format("{0}:{1}", IndexPathFieldName, descendantPath); + var descendantPath = $@"\-1\,*{nodeId}\,*"; + var rawQuery = $"{IndexPathFieldName}:{descendantPath}"; var searcher = GetSearcher(); var c = searcher.CreateCriteria(); var filtered = c.RawQuery(rawQuery); var results = searcher.Find(filtered); - ProfilingLogger.Logger.Debug(GetType(), string.Format("DeleteFromIndex with query: {0} (found {1} results)", rawQuery, results.TotalItemCount)); + ProfilingLogger.Logger.Debug(GetType(), $"DeleteFromIndex with query: {rawQuery} (found {results.TotalItemCount} results)"); //need to create a delete queue item for each one found foreach (var r in results)