Change EntityService GetDescendents to lookup the item path to use in the LIKE query to be a 'prefix' query not a 'contains' query which will be much better for SQL

This commit is contained in:
Shannon
2017-08-31 22:19:01 +10:00
parent 57a8df8309
commit ecc761a232
2 changed files with 48 additions and 6 deletions

View File

@@ -349,10 +349,20 @@ namespace Umbraco.Core.Services
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
//lookup the path so we can use it in the prefix query below
var itemPath = repository.GetAllPaths(objectTypeId, id).ToArray();
if (itemPath.Length == 0)
{
totalRecords = 0;
return Enumerable.Empty<IUmbracoEntity>();
}
var query = Query<IUmbracoEntity>.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));
{
query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", itemPath[0].Path), TextColumnType.NVarchar));
}
IQuery<IUmbracoEntity> filterQuery = null;
if (filter.IsNullOrWhiteSpace() == false)
@@ -381,15 +391,25 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var query = Query<IUmbracoEntity>.Builder;
if (idsA.All(x => x != Constants.System.Root))
{
//lookup the paths so we can use it in the prefix query below
var itemPaths = repository.GetAllPaths(objectTypeId, idsA).ToArray();
if (itemPaths.Length == 0)
{
totalRecords = 0;
return Enumerable.Empty<IUmbracoEntity>();
}
var clauses = new List<Expression<Func<IUmbracoEntity, bool>>>();
foreach (var id in idsA)
{
var path = itemPaths.FirstOrDefault(x => x.Id == id);
if (path == null) continue;
var qid = id;
clauses.Add(x => x.Path.SqlContains(string.Format(",{0},", qid), TextColumnType.NVarchar) || x.Path.SqlEndsWith(string.Format(",{0}", qid), TextColumnType.NVarchar));
clauses.Add(x => x.Path.SqlStartsWith(string.Format("{0},", path), TextColumnType.NVarchar) || x.Path.SqlEndsWith(string.Format(",{0}", qid), TextColumnType.NVarchar));
}
query.WhereAny(clauses);
}
@@ -443,6 +463,21 @@ namespace Umbraco.Core.Services
}
}
/// <inheritdoc />
public virtual IEnumerable<IUmbracoEntity> GetAncestors(int id)
{
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var entity = repository.Get(id);
var pathMatch = entity.Path + ",";
var query = Query<IUmbracoEntity>.Builder.Where(x => x.Path.StartsWith(pathMatch) && x.Id != id);
var entities = repository.GetByQuery(query);
return entities;
}
}
/// <summary>
/// Gets a collection of descendents by the parents Id
/// </summary>
@@ -601,13 +636,13 @@ namespace Umbraco.Core.Services
return repository.GetAllPaths(objectTypeId, keys);
}
}
/// <summary>
/// Gets a collection of <see cref="IUmbracoEntity"/>
/// Gets a collection of <see cref="T:Umbraco.Core.Models.EntityBase.IUmbracoEntity" />
/// </summary>
/// <param name="objectTypeId">Guid id of the UmbracoObjectType</param>
/// <param name="ids"></param>
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
/// <returns>An enumerable list of <see cref="T:Umbraco.Core.Models.EntityBase.IUmbracoEntity" /> objects</returns>
public virtual IEnumerable<IUmbracoEntity> GetAll(Guid objectTypeId, params int[] ids)
{
var umbracoObjectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(objectTypeId);

View File

@@ -203,6 +203,13 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
IEnumerable<IUmbracoEntity> GetDescendents(int id);
/// <summary>
/// Gets a collection of ancestors by the parents Id
/// </summary>
/// <param name="id">Id of entity to retrieve ancestors for</param>
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
IEnumerable<IUmbracoEntity> GetAncestors(int id);
/// <summary>
/// Gets a collection of descendents by the parents Id
/// </summary>