Add ability to sort on multiple fields
This commit is contained in:
parent
2a5891322d
commit
760b925e2a
|
|
@ -107,7 +107,7 @@ public static class ParameterizedQueryBuilderExtensions
|
|||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Appends a negating AND clause to the query if the value is not null.
|
||||
/// </summary>
|
||||
|
|
@ -231,6 +231,21 @@ public static class ParameterizedQueryBuilderExtensions
|
|||
return query;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends an ORDER BY clause to the query.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="orderFields">The fields by which to order.</param>
|
||||
public static ParameterizedQuery OrderBy(this ParameterizedQuery query, params OrderField[] orderFields)
|
||||
{
|
||||
if (!orderFields.Any())
|
||||
return query;
|
||||
|
||||
var clauses = string.Join(",", orderFields.Select(x => $"{x.Field} {(x.Direction == OrderDirection.Ascending ? "asc" : "desc")}"));
|
||||
query.Sql.AppendLine($"order by {clauses}");
|
||||
return query;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends an OFFSET clause to the query.
|
||||
/// </summary>
|
||||
|
|
|
|||
10
src/modules/Elsa.Dapper/Models/OrderField.cs
Normal file
10
src/modules/Elsa.Dapper/Models/OrderField.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
using Elsa.Common.Entities;
|
||||
|
||||
namespace Elsa.Dapper.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a field by which to order.
|
||||
/// </summary>
|
||||
/// <param name="Field">The field.</param>
|
||||
/// <param name="Direction">The direction.</param>
|
||||
public record OrderField(string Field, OrderDirection Direction);
|
||||
|
|
@ -8,5 +8,6 @@ internal class WorkflowStateRecord
|
|||
public string? CorrelationId { get; set; }
|
||||
public string Status { get; set; } = default!;
|
||||
public string SubStatus { get; set; } = default!;
|
||||
public long ExecutionLogSequence { get; set; }
|
||||
public string Props { get; set; } = default!;
|
||||
}
|
||||
|
|
@ -79,6 +79,19 @@ public class Store<T> where T : notnull
|
|||
public async Task<Page<T>> FindManyAsync(Action<ParameterizedQuery> filter, PageArgs pageArgs, string orderKey, OrderDirection orderDirection, CancellationToken cancellationToken = default) =>
|
||||
await FindManyAsync<T>(filter, pageArgs, orderKey, orderDirection, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a page of records in the specified shape.
|
||||
/// </summary>
|
||||
/// <param name="filter">The conditions to apply to the query.</param>
|
||||
/// <param name="pageArgs">The page arguments.</param>
|
||||
/// <param name="orderFields">The fields by which to order the results.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A page of records.</returns>
|
||||
public async Task<Page<T>> FindManyAsync(Action<ParameterizedQuery> filter, PageArgs pageArgs, IEnumerable<OrderField> orderFields, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await FindManyAsync<T>(filter, pageArgs, orderFields, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a page of records in the specified shape.
|
||||
/// </summary>
|
||||
|
|
@ -90,12 +103,26 @@ public class Store<T> where T : notnull
|
|||
/// <typeparam name="TShape">The shape type.</typeparam>
|
||||
/// <returns>A page of records.</returns>
|
||||
public async Task<Page<TShape>> FindManyAsync<TShape>(Action<ParameterizedQuery> filter, PageArgs pageArgs, string orderKey, OrderDirection orderDirection, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await FindManyAsync<TShape>(filter, pageArgs, new[] { new OrderField(orderKey, orderDirection) }, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a page of records in the specified shape.
|
||||
/// </summary>
|
||||
/// <param name="filter">The conditions to apply to the query.</param>
|
||||
/// <param name="pageArgs">The page arguments.</param>
|
||||
/// <param name="orderFields">The fields by which to order the results.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <typeparam name="TShape">The shape type.</typeparam>
|
||||
/// <returns>A page of records.</returns>
|
||||
public async Task<Page<TShape>> FindManyAsync<TShape>(Action<ParameterizedQuery> filter, PageArgs pageArgs, IEnumerable<OrderField> orderFields, CancellationToken cancellationToken = default)
|
||||
{
|
||||
using var connection = _dbConnectionProvider.GetConnection();
|
||||
|
||||
var query = _dbConnectionProvider.CreateQuery().From(TableName);
|
||||
filter(query);
|
||||
query = query.OrderBy(orderKey, orderDirection).Page(pageArgs);
|
||||
query = query.OrderBy(orderFields.ToArray()).Page(pageArgs);
|
||||
|
||||
var countQuery = _dbConnectionProvider.CreateQuery().Count(TableName);
|
||||
filter(countQuery);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using Elastic.Clients.Elasticsearch.QueryDsl;
|
|||
using Elsa.Common.Entities;
|
||||
using Elsa.Common.Models;
|
||||
using Elsa.Elasticsearch.Common;
|
||||
using Elsa.Elasticsearch.Shared.Models;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Runtime.Contracts;
|
||||
using Elsa.Workflows.Runtime.Entities;
|
||||
|
|
@ -64,11 +65,21 @@ public class ElasticWorkflowExecutionLogStore : IWorkflowExecutionLogStore
|
|||
|
||||
private static SearchRequestDescriptor<WorkflowExecutionLogRecord> Sort<TProp>(SearchRequestDescriptor<WorkflowExecutionLogRecord> descriptor, WorkflowExecutionLogRecordOrder<TProp> order)
|
||||
{
|
||||
var sortDescriptor = new SortOptionsDescriptor<WorkflowExecutionLogRecord>();
|
||||
var propName = order.KeySelector.GetProperty()!.Name;
|
||||
var sortOrder = order.Direction == OrderDirection.Ascending ? SortOrder.Asc : SortOrder.Desc;
|
||||
sortDescriptor.Field(propName, f => f.Order(sortOrder));
|
||||
|
||||
var orderField = new OrderField(propName, order.Direction);
|
||||
return Sort(descriptor, orderField);
|
||||
}
|
||||
|
||||
private static SearchRequestDescriptor<WorkflowExecutionLogRecord> Sort(SearchRequestDescriptor<WorkflowExecutionLogRecord> descriptor, params OrderField[] orderFields)
|
||||
{
|
||||
var sortDescriptor = new SortOptionsDescriptor<WorkflowExecutionLogRecord>();
|
||||
|
||||
foreach (var orderField in orderFields)
|
||||
{
|
||||
var sortOrder = orderField.Direction == OrderDirection.Ascending ? SortOrder.Asc : SortOrder.Desc;
|
||||
sortDescriptor.Field(orderField.Field, f => f.Order(sortOrder));
|
||||
}
|
||||
|
||||
descriptor.Sort(sortDescriptor);
|
||||
return descriptor;
|
||||
}
|
||||
|
|
|
|||
10
src/modules/Elsa.Elasticsearch/Shared/Models/OrderField.cs
Normal file
10
src/modules/Elsa.Elasticsearch/Shared/Models/OrderField.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
using Elsa.Common.Entities;
|
||||
|
||||
namespace Elsa.Elasticsearch.Shared.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a field by which to order.
|
||||
/// </summary>
|
||||
/// <param name="Field">The field.</param>
|
||||
/// <param name="Direction">The direction.</param>
|
||||
public record OrderField(string Field, OrderDirection Direction);
|
||||
|
|
@ -19,7 +19,11 @@ internal class Response
|
|||
public WorkflowSubStatus SubStatus { get; set; }
|
||||
public string? CorrelationId { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public IDictionary<string, object> Properties { get; set; }
|
||||
|
||||
[Obsolete("Use WorkflowState.Properties instead.")]
|
||||
public IDictionary<string, object> Properties { get; set; } = new Dictionary<string, object>();
|
||||
|
||||
[Obsolete("Use WorkflowState.Fault instead.")]
|
||||
public WorkflowFaultState? Fault { get; set; }
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
public DateTimeOffset? LastExecutedAt { get; set; }
|
||||
|
|
|
|||
|
|
@ -5,8 +5,16 @@ using Elsa.Workflows.Runtime.Entities;
|
|||
// ReSharper disable once CheckNamespace
|
||||
namespace Elsa.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="StoredTrigger"/>.
|
||||
/// </summary>
|
||||
public static class WorkflowTriggerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Filters a collection of <see cref="StoredTrigger"/> by trigger type.
|
||||
/// </summary>
|
||||
/// <param name="triggers">The collection of triggers to filter.</param>
|
||||
/// <typeparam name="T">The trigger type.</typeparam>
|
||||
public static IEnumerable<StoredTrigger> Filter<T>(this IEnumerable<StoredTrigger> triggers) where T : ITrigger
|
||||
{
|
||||
var triggerName = ActivityTypeNameHelper.GenerateTypeName<T>();
|
||||
|
|
|
|||
Loading…
Reference in a new issue