Difference between revisions of "Filters"
(→Arrays) |
|||
| Line 24: | Line 24: | ||
Filters can also be constructed by the frontend, most often by [[Loop]]. In this scenario, a convenience filter notation is also available - it'll take the object notation you provide, and then convert it into the textual format with arguments. Here's some examples: | Filters can also be constructed by the frontend, most often by [[Loop]]. In this scenario, a convenience filter notation is also available - it'll take the object notation you provide, and then convert it into the textual format with arguments. Here's some examples: | ||
<syntaxhighlight lang="js"> | |||
<Loop over="page" filter={ | |||
{ | |||
where: { | |||
userId: 14 | |||
} | |||
} | |||
}> | |||
{page => { return <p>{page.url}</p>; }} | |||
</Loop> | |||
</syntaxhighlight> | |||
<syntaxhighlight lang="js"> | |||
import webRequest from 'UI/Functions/WebRequest'; | |||
webRequest("page/list", { | |||
where: { | |||
userId: 14 | |||
} | |||
}).then(response => { | |||
// response.json contains the set of pages made by user #14 | |||
}) | |||
</syntaxhighlight> | |||
The filter object itself: | |||
<syntaxhighlight lang="js"> | <syntaxhighlight lang="js"> | ||
| Line 78: | Line 109: | ||
args: [14] | args: [14] | ||
} | } | ||
</syntaxhighlight> | |||
Query/args being passed in to webRequest and Loop: | |||
<syntaxhighlight lang="js"> | |||
import webRequest from 'UI/Functions/WebRequest'; | |||
webRequest("page/list", { | |||
query: "UserId=?", | |||
args: [14] | |||
}).then(response => { | |||
// response.json contains the set of pages made by user #14 | |||
}) | |||
<Loop over='page' filter={{query: "UserId=?", | |||
args: [14]}}> ... | |||
</Loop> | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Revision as of 23:28, 25 October 2022
Filters are a query-like mechanism for filtering out results from a list endpoint. At their core, they are textual and support a set of arguments.
Filter examples
A textual filter with arguments is like so:
(UserId=? or UserId=?) and CreatedUtc>?
It is not case sensitive. Filters in the permission system do not support these ? arguments (as it wouldn't know where to bind the value from).
Typically you'll see this textual form of filter inside a Where() call in the C# API:
uint userId = 14;
var listOfThingsByThisUser = await Where("UserId=?").Bind(userId).ListAll(context);
.Bind() is used to bind the actual value of an argument. Values are bound in this way such that the filter string is a constant and can benefit from being precompiled. Indeed, the whole filter system is built to be entirely non-allocating, as the Bind calls internally set your provided value onto an compiled object field, with that object originating from a pool for the given cached filter.
JS filter notation
Filters can also be constructed by the frontend, most often by Loop. In this scenario, a convenience filter notation is also available - it'll take the object notation you provide, and then convert it into the textual format with arguments. Here's some examples:
<Loop over="page" filter={
{
where: {
userId: 14
}
}
}>
{page => { return <p>{page.url}</p>; }}
</Loop>
import webRequest from 'UI/Functions/WebRequest';
webRequest("page/list", {
where: {
userId: 14
}
}).then(response => {
// response.json contains the set of pages made by user #14
})
The filter object itself:
{
where: {
userId: 14
}
}
#Operators can be used by passing an object:
{
where: {
userId: {
greaterThan: 14
}
}
}
Or statements are represented with an array:
{
where: [{
userId: 14
},
{
userId: 16
}]
}
And statements are performed by providing multiple field values:
{
where: {
userId: 14,
createdUtc: {
greaterThan: yesterday /* yesterday is a JS Date */
}
}
}
If you need more expressive power, you can also directly specify the query and args:
{
query: "UserId=?",
args: [14]
}
Query/args being passed in to webRequest and Loop:
import webRequest from 'UI/Functions/WebRequest';
webRequest("page/list", {
query: "UserId=?",
args: [14]
}).then(response => {
// response.json contains the set of pages made by user #14
})
<Loop over='page' filter={{query: "UserId=?",
args: [14]}}> ...
</Loop>
Operators
Filters support a variety of operators for comparisons:
- Greater than
* Field>? (query notation)
* {greaterThan: x} (JS notation)
- Less than
* Field<? (query notation)
* {lessThan: x} (JS notation)
- Greater than or equal
* Field>=? (query notation)
* {greaterThanOrEqual: x} (JS notation)
* {geq: x} (JS notation)
- Less than or equal
* Field<=? (query notation)
* {lessThanOrEqual: x} (JS notation)
* {leq: x} (JS notation)
- Equals
* Field=? (query notation)
* x (JS notation)
* {equals: x} (JS notation)
- Not
* Field!=? (query notation)
* !( .... ) (query notation)
* {not: x} (JS notation)
- Starts with (textual values only)
* Field startsWith ? (query notation)
* {startsWith: x} (JS notation)
- Ends with (textual values only)
* Field endsWith ? (query notation)
* {endsWith: x} (JS notation)
- Contains (textual values only)
* Field contains ? (query notation)
* {contains: x} (JS notation)
Arrays
If you provide an array of values you must tell the query system that you are doing so by surrounding your ? arg with square brackets, like this:
Name=[?]
This syntax exists such that the precompiled filter is ready to receive a set of values rather than just one.
If you're doing this in C# you can then bind any IEnumerable like so, provided its data type matches that of the target field:
var nameList = new List<string>() { "Dave", "Steve" };
var resultsWithEitherName = await Where("Name=[?]").Bind(nameList).ListAll(context);
From javascript you can just pass an array inside your args like so:
{
"query": "Name=[?]",
"args": [
["Dave", "Steve"]
]
}
Filter functions
Most often seen in the permission system. These are functions used within a query filter. Filter functions are generic and can also be custom defined by installable modules if you need another. Example code which adds a filter function can be seen on the context extensions page. Variations of UserPermits ("CompanyPermits" etc) are quite common.
- IsSelf()
- HasUserPermit()
- HasRolePermits()
- IsIncluded()
- On(...)
Todo: describing the above, particularly On and IsIncluded