Sorting and filtering with Client Side Refiner
Client Side Refiner is used to lighten the load on Transformer Refiner by sorting and filtering subsets of data on the client side.
Available from: StreamLinkTS 7.1.16+
Should I use Transformer Refiner or Client Side Refiner?
Client Side Refiner best complements Transformer Refiner when using it to sort and filter small containers with few subjects, particularly when the data is rapidly changing. This means fewer requests to the server, and quicker sort and filter operations.
Client Side Refiner is easier to customise quickly if you value being able to write custom sort and filter functions in TypeScript in the client.
Enabling Client Side Refiner
Client Side Refiner is disabled by default. To enable Client Side Refiner, pass the following arguments to StreamLinkFactory.create
when creating a StreamLink
instance.
var sl = StreamLink.StreamLinkFactory.create({
// This URL is an example – use the Liberator URL according to your setup.
liberator_urls: "ws://localhost:18080",
clientside_refiner_enable: true
})
Configuring Client Side Refiner
Configure Client Side Refiner by setting the following keys in the configuration object you pass to StreamLinkFactory.create
. A full list of configuration-object keys can be found in the documentation for StreamLinkFactory.
- clientside_refiner_enable
-
Default:
false
| Type:boolean
When set to true, enables the Client Side Refiner and allows other arguments to take effect.
- clientside_refiner_fn_use_for
-
Default:
undefined
| Type:function
If
clientside_refiner_enable
is true, this function determines if individual container subscriptions should be refined on the client or server.Returning
true
from this function will enable Client Side Refiner for the container subject matching thesubject
parameter.Example:
Using Client Side Refiner for container subscriptions under EXAMPLES/PRICINGStreamLinkFactory.create({ // ... clientside_refiner_fn_use_for: (subject: String, parameters: SubscriptionParameters): boolean => { return subject.includes("EXAMPLES/PRICING"); } })
- clientside_refiner_custom_sorts
-
Default:
undefined
| Type:object
clientside_refiner_custom_sorts
takes an object consisting of key-value pairs mapping custom sort names to their sort functions.See Refiner subject syntax for how to construct subject sort parameters.
Example:
Sort items containing the text "Inc."const daysOfWeek = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; function sortByDay(a: any, b: any): number { const dayA = daysOfWeek.indexOf(a); const dayB = daysOfWeek.indexOf(b); if (dayA < dayB) { return -1; } else if (dayA > dayB) { return 1; } else { return 0; } } var streamlink = StreamLinkFactory.create({ // ... clientside_refiner_custom_sorts: { sort_by_day: sortByDay } });
- clientside_refiner_custom_filters
-
Default:
undefined
| Type:object
clientside_refiner_custom_filters
takes an object consisting of key-value pairs mapping custom filter names to their filter functions.The filter functions can be one of two types:
-
A comparator function with the signature
(fieldValue: string, filterCriterion: string): number
, similar to the functions provided toclientside_refiner_custom_sorts
.This type should be used when the filter expression is of the form
where:customFilterName:<fieldname>:<operator>:<value>
. -
A function with the signature
(fieldProvider: IFieldProvider): boolean
, wherefieldProvider
contains the methodgetField(fieldName: string): any
, which is used to get a field from the record being filtered.This type should be used when the filter expression is of the form
where:x
.
See Refiner subject syntax for how to construct subject filter parameters.
Examples:
Custom filter by grade (type A)const grades = ['A', 'A+', 'AA-', 'AA', 'AA+', 'AAA']; function gradeFilter(fieldValue: string, filterCriterion: string): number { const fieldValueRank = grades.indexOf(fieldValue); const filterCriterionRank = grades.indexOf(filterCriterion); if (fieldValueRank === filterCriterionRank) { return 0; } else if (fieldValueRank < filterCriterionRank) { return -1; } else { return 1; } } var streamLink = StreamLinkFactory.create({ // ... clientside_refiner_custom_filters: { grade_filter: gradeFilter } });
Custom filter by a combination of fields (type B)function spreadTargetFilter(fieldProvider: { getField: (name: string) => any }): boolean { const bestAsk = Number(fieldProvider.getField("BestAsk")); const bestBid = Number(fieldProvider.getField("BestBid")); const spreadTarget = Number(fieldProvider.getField("SpreadTarget")); return bestAsk - bestBid >= spreadTarget; } var streamLink = StreamLinkFactory.create({ // ... clientside_refiner_custom_filters: { spread_target_filter: spreadTargetFilter } });
-