pdevito3 / QueryKit

🎛️ QueryKit is a .NET library that makes it easier to query your data by providing a fluent and intuitive syntax for filtering and sorting.
Apache License 2.0
147 stars 13 forks source link

Support for custom sort filter #50

Open ChasakisD opened 2 months ago

ChasakisD commented 2 months ago

Hey!

Sieve feature of custom sort/filter methods is a pretty handy feature where it comes to support custom or complex queries. https://github.com/Biarity/Sieve?tab=readme-ov-file#add-custom-sortfilter-methods

Is there any plan to support such a feature?

pdevito3 commented 2 months ago

First, I'm seeing this honestly. What api might you expect with QueryKit? Could you show an example of it in use?

ChasakisD commented 2 months ago

Here is an example using where I would like to query Books table and sort/fitler the sold units.

It may become very complex to fit all the cases for filtering (nested, complex queries), so providing custom operators could be very handy.

In the example below, let's say that we want to filter on the property SoldUnits which is the sum of the quantity of ordered books in each order. Or let's say we want to filter on the sum of the quantity of ordered books in each order in the past 10 days.

public class Book
{
    public int Id { get; set; }

    public string Title { get; set; }
    public string Author { get; set; }

    public List<BookOrder> Orders { get; set; }
}

public class BookOrder
{
    public int Id { get; set; }
    public Book Book { get; set; }

    public int Quantity { get; set; }

    public DateTime OrderDate { get; set; }
}

// Lets say that we map it to a dto as follows
public class BookDto
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Author { get; set; }

    public int TotalOrders { get; set; }
    public int SoldUnits { get; set; }
}

// Now we can use the following query to get the data
await DataContext.Books
    .Select(b => new BookDto
    {
        Id = b.Id,
        Title = b.Title,
        Author = b.Author,
        TotalOrders = b.Orders.Count(),
        SoldUnits = b.Orders.Sum(o => o.Quantity)
    })
    .ToListAsync();

// So lets say that we want to filter on the soldUnits
// We can do it as follows
private static readonly QueryKitConfiguration QueryConfiguration = new(
    config =>
    {
        config.CustomProperty<Book>(x => x.Orders.Sum(o => o.Quantity));
            .HasQueryName("SoldUnits");

        // or a more complex one
        config.CustomOperation<Book>((x, op, value) => x.Orders.Where(y => y.OrderDate > DateTime.UtcNow.AddDays(-10)).Sum(o => o.Quantity) > value);
            .HasQueryName("SoldUnitsMore10InTheLastDays");
    });
ChasakisD commented 2 months ago

So as the application scales, and more data needed, it would be very useful to have the ability to define your custom operations

pdevito3 commented 2 months ago

Got it. Thanks for the examples! I could see adding this but probably isn't something I'm going to do immediately. Will put it in the backlog though and I'm open to a PR if you're interested. The recent derivation property PRs below might give a bit of idea a similar flavor of change for reference