What is the benefit of defining filters via Filter

#1

We know that it is possible to define filters both directly, e.g. “field1 == 123” and via Filter type, e.g. Filter.eq(‘field1’,123). The latter is the recommended/preferred way. Could someone explain the benefits of using Filter? Thanks.

0 Likes

#2

IMO, the 2 biggest benefits of using C3’s Filter helper are:

Cleaner code

A :+1::

Filter.eq('name', spec.searchQuery).and.intersects('id', idsArray)

vs. B :-1::

'name == "' + spec.searchQuery + '" && intersects(id, ["' + idsArray.join('","') + '"])'

String concatenation like this is very prone to mistakes with mismatching single/double quotes, parentheses, and square brackets. And what if idsArray is empty? JSON.stringify(idsArray) could solve that, but we’d still have to rely on string concatenation.

Proper escaping of quote characters

In the above example, if spec.searchQuery or any value in idsArray contains a double quote character, the filter will be invalid and an exception will be thrown. In fact, the proper way (without any C3 helpers) to write filter B above is:

'name == "' + spec.searchQuery.replace('"', '\\"') + '" && intersects(id, ' + JSON.stringify(idsArray) + ')

or

'name == ' + JSON.stringify(spec.searchQuery) + ' && intersects(id, ' + JSON.stringify(idsArray) + ')

This is especially important if you use user input in filter expressions, as improper handling of quotes can be exploited in a manner similar to SQL injection (e.g. spec.searchQuery = 'whatever" || 1 == 1 || name == "') to return unintended data*.


TL;DR: C3’s Filter helper makes writing non-trivial filter expressions painless, and for consistency’s sake I use it for trivial expressions too.

Footnotes

* Note that fetch will only ever return data in your tag**, and it would not be a security issue per se since you should have implemented ACLs to properly protect sensitive information, but such a filter would be buggy nonetheless.

** Ignoring facaded types

1 Like

Constructing good filters using Filter