Filtering
To quickly add filtering capabilities to your collection fields use the UseFilter()
field extension.
schema.ReplaceField("people",
ctx => ctx.People,
"Return a list of people. Optional filtered")
.UseFilter();
If you are using the SchemaBuilder.FromObject
you can use the UseFilterAttribute
on your collection properties.
public class DemoContext : DbContext
{
[UseFilter]
public DbSet<Movie> Movies { get; set; }
[UseFilter]
public DbSet<Person> People { get; set; }
[UseFilter]
public DbSet<Actor> Actors { get; set; }
}
This field extension can only be used on a field that has a Resolve
expression that is assignable to IEnumerable
- I.e. collections. The extension adds an argument called filter: String
.
Note: When using with the paging or sort extensions ensure you call UseFilter
before both others. If you are using the attribute, then ensure the Filter attribute comes before the other attributes.
The filter
argument takes a string that will be compiled to an expression and inserted into a Where()
call. The expression is compiled against your schema and the context is the type of elements in the collection.
For example, given ctx => ctx.People
returns a IEnumerable<Person>
and Person
is defined as:
public class Person
{
public uint Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Dob { get; set; }
public List<Actor> ActorIn { get; set; }
public List<Writer> WriterOf { get; set; }
public List<Movie> DirectorOf { get; set; }
public DateTime? Died { get; set; }
public bool IsDeleted { get; set; }
}
We can write some filter expressions like so:
{
people(filter: "id == 12 || id == 10") {
firstName
}
}
{
deletedPeople: people(filter: "isDeleted == true") {
firstName
}
}
{
people(filter: "dob > \"2010-08-11T00:00:00\" && isDeleted == false") {
firstName
}
}
The expression language supports the following constants:
- Booleans -
true
&false
- Integers - e.g.
2
,-8
- Floats - e.g.
0.2
,-8.3
null
- Strings -
"within double quotes"
; when representing a date, use an ISO 8601 format such as"2022-07-31T20:00:00"
The expression language supports the following operators:
-
- Subtraction+
- Addition*
- Multiply/
- Divide%
- Mod^
- Power==
- Equals!=
- Not Equals<=
- Less than or equal to>=
- Greater than or equal to<
- Less than>
- Greater thanor
or||
- Orand
or&&
- And
The expression language supports the following methods, these are called against fields within the filter context:
List.any(filter)
- Returntrue
if any of the items in the list match the filter. The filter withinany
is on the context of the list item type. Otherwisefalse
{
# In C# - people.Where(p => p.ActorIn.Any(a => a.Name == "Star Wars"))
people(filter: "actorIn.any(name == \"Star Wars\")") { ... }
}
List.count(filter?)
- Return the count of a list. Optionally counting items that match a filter
{
# No filter - all people that acted in 3 movies
people(filter: "actorIn.count() == 3") { ... }
# Count only those that match the filter - all people that acted in any movie starting with "Star"
people(filter: "actorIn.count(name.startsWith(\"Star\")) > 0") { ... }
}
List.first(filter?)
/List.firstOrDefault(filter?)
- Return the first item from a list. Optionally by a filterList.last(filter?)
/List.lastOrDefault(filter?)
- Return the last item from a list. Optionally by a filterList.take(int)
- Return the firstx
itemsList.skip(int)
- Return the items afterx
List.orderBy(field)
- Order the list by a given fieldList.orderByDesc(field)
- Order the list in reverse by a given fieldList.where(filter)
, orList.filter(filter)
- Filter the liststring.contains(string)
- Returntrue
if the specified string occurs in this string instance
{
people(filter: "firstName.contains(\"o\")") { ... }
}
string.startsWith(string)
- Returntrue
if the beginning of this string instance matches the specified string
{
people(filter: "firstName.startsWith(\"b\")") { ... }
}
string.endsWith(string)
- Returntrue
if the end of this string instance matches the specified string
{
people(filter: "firstName.endsWith(\"b\")") { ... }
}
string.toLower()
- Return the string converted to lowercase
{
people(filter: "firstName.toLower() == \"bob\"") { ... }
}
string.toUpper()
- Return the string converted to uppercase
{
people(filter: "firstName.toUpper() == \"BOB\"") { ... }
}
<scalar>.isAny([])
- Returntrue
if the scalar value (string
,int
, etc.) equals any of the values provided in the array argument of the method call.
{
people(filter: "firstName.isAny([\"Bob\", \"Bobby\"])") { ... }
}
The expression language supports ternary and conditional:
__ ? __ : __
if __ then __ else __