这个问题基于https://github.com/ChilliCream/hotchocolate/issues/924中的讨论——这也是我获得灵感的地方。
我有一个系统,其中我保留了一份员工名单。每个员工都有一个 WorkHours 属性,表示您每周工作多少小时。
我还有一系列需要由前面提到的员工解决的任务。
该关联是通过分配类处理的。此类包含两个 unix 时间戳 Start 和 End ,表示员工在哪个时间段内处理特定任务。此外,他们有一个 HoursPerWeek 属性,表示员工每周必须在给定任务上花费多少小时,HoursPerWeek 是必要的,因为只要 Allocation.HoursPerWeek 的总和,员工就可以在同一时间段内与多个任务相关联不超过 Employee.WorkHours。
本质上,我想按照这个 LINQ 查询的方式实现一些目标
var ts = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
employees.Where(e =>
e.Allocations
.Where(a => a.Start < ts && a.End > ts)
.Sum(a => a.HoursPerWeek)
< e.WorkHours);
这将有效地给我任何在这个时间点剩余工作时间的员工。
我无法在我的查询中直接引用employee.WorkHours,但我试图让它与双打相比工作。这就是我现在已经走了多远
public class CustomFilterConventionExtension : FilterConventionExtension
{
protected override void Configure(IFilterConventionDescriptor descriptor)
{
descriptor.Operation(CustomFilterOperations.Sum)
.Name("sum");
descriptor.Configure<ListFilterInputType<FilterInputType<Allocation>>>(descriptor =>
{
descriptor
.Operation(CustomFilterOperations.Sum)
.Type<ComparableOperationFilterInputType<double>>();
});
descriptor.AddProviderExtension(new QueryableFilterProviderExtension(
y =>
{
y.AddFieldHandler<EmployeeAllocationSumOperationHandler>();
}));
}
}
public class EmployeeAllocationSumOperationHandler : FilterOperationHandler<QueryableFilterContext, Expression>
{
public override bool CanHandle(ITypeCompletionContext context, IFilterInputTypeDefinition typeDefinition,
IFilterFieldDefinition fieldDefinition)
{
return context.Type is IListFilterInputType &&
fieldDefinition is FilterOperationFieldDefinition { Id: CustomFilterOperations.Sum };
}
public override bool TryHandleEnter(QueryableFilterContext context, IFilterField field, ObjectFieldNode node, [NotNullWhen(true)] out ISyntaxVisitorAction? action)
{
var ts = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var property = context.GetInstance();
Expression<Func<ICollection<Allocation>, double>> expression = _ => _
.Where(_ => _.Start < ts && _.End > ts)
.Sum(_ => _.HoursPerWeek);
var invoke = Expression.Invoke(expression, property);
context.PushInstance(invoke);
action = SyntaxVisitor.Continue;
return true;
}
}
services.AddGraphQLServer()
.AddQueryType<EmployeeQuery>()
.AddType<EmployeeType>()
.AddProjections()
.AddFiltering()
.AddConvention<IFilterConvention, CustomFilterConventionExtension>()
.AddSorting();
有了它,我然后尝试编写我的查询
employees (where: {allocations: {sum: {gt: 5}}}) {
nodes{
id, name
}
}
但是,此实现会不断抛出异常,因为它无法从System.Obejct
to 转换System.Generic.IEnumerable
。
但是在最终版本中,我希望能够不使用 const 编号而是使用 Employee WorkHours 进行查询
employees (where: {allocations: {sum: {gt: workHours}}}) {
nodes{
id, name
}
}
谁能协助创建一个过滤器操作?也许你做过类似的事情,或者知道这实际上是不可能的。
如果有人想玩它,我已经将我所有的代码都放在了 GitHub 存储库中https://github.com/LordLyng/sum-filter-example