-
Notifications
You must be signed in to change notification settings - Fork 34
Using
This wiki page will go into detail about the usage of the QueryEngine API.
QueryEngine is incredibly powerful, and pretty easy to use once you understand the key concepts behind it which we'll detail her. Firstly, there is the QueryCollection class which extends the Backbone Collection functionality with our special sauce. QueryCollections can be in one of two states, live or not live. QueryEngine also provides a few different ways of querying our collections to discover the models that pass our selection criteria. QueryEngine supports the following types of selection criteria: Queries, Filters, Pills and SearchStrings all serving their own purpose.
Not Live collections behave very traditionally, in the sense that you have a collection that contains all your models, and you want to check every single one of them against a particular criteria, and return the models which passed the criteria. While being the most straightforward, it is also vastly inefficient, as every single time we query, we have to scan all the models all over again. It also has the problem that if one of our passed models changes, and no longer matches our criteria, we wouldn't care. These down-sides make it very hard to code real-time auto-updating dynamic applications.
Live collections step in where Not Live collections fall short. Live collections listen to the Collections Events to automatically check that the added, changed or removed model matches our criteria, if it does, then it will add or keep it, if it doesn't it will remove it. This is magical and highly efficient, as it means we our Live collections are always up to date with the correct models applied, and our adding and removing of models happens automatically in the most efficient way possible. It's efficient as instead of querying our entire collection's models every time we want results, it only performs the queries for each model once, and then again when an event fires.
Standard collections do not having any collection hierarchy, and all models inside the standard collection are their own. If they are a live collection, then they only subscribe to their own events.
Child and Parent collections are useful when it comes to notion of sub-collections. For instance, if in our navigation we have the following filters "My Tasks", and then "My Backlogged Tasks". The most efficient and and amazing way to code this would be to have the following:
- a global task collection that contains all the tasks, with no selection criteria
- a my tasks live collection, which uses the global task collection as a parent, and applies the selection criteria
userId: myUserIdto it - a my backlogged tasks live collection, which uses the my tasks collection as a parent, and applies the selection criteria
status: 'backlogged'to it
So, now say if we create a new backlogged task, we would simply add it to the global task collection, and then our my tasks live collection would automatically detect the addition to the global task collection, and check if the model passes our criteria, if it does, then it will add it to its collection. If added, our my backlogged tasks live collection would then automatically pick up the add event on its parent, and check if the model passes it's criteria, and if so add it to its own collection. If the event is a change, the same process occurs and will also remove if it no longer supports the criteria. If the event is a remove, it is removed from all collections.
This is quite amazing, as with minimal effort we have coded a waterfall of incredibly efficient data hierarchy which always stays in sync automatically. Amazing.
There are the four concepts that make up our selection criteria.
The Query criteria provides us with NoSQL like querying. For instance allows us to do url: $startsWith: '/blog' to find all the models which URL starts with '/blog'. It more or less follows the MongoDB query spec, but with a improvements.
A Filter is a custom function that we apply to our collection. When a query is performed, our filter will be passed the model, and cleanedSearchString as its arguments. It will then return whether or not the model passed or failed by returning true or false respectively.
Pills allow us to specify search criteria when using strings. They come in the format of "#{prefix}#{value}", and can have many supported prefixes. For instance you could do ['user:','@'] to match against both "user:ben" and "@ben", where "ben" would be extracted as the value, and passed to our pill's callback function. In this instance, the callback function would probably look like this: callback: (model,value) -> return model.getUser().get('name') is value
A Search String is type of selection criteria defined by a search box on your webpage. It takes in a string, which is then used by our Filters and Pills. For example, we could have the search string chocolate type:black. Indicates that we are searching for the text "chocolate" and applying the criteria of type is black. The text "chocolate" is then sent to our filters as the cleanedSearchString argument. Note: "type:black" would only be extracted from the search string, if there is a pill looking for that. If no pill is looking for that, then it will not be extracted.
These are the methods which are exposed to you via window.QueryEngine for client-side, and require('query-engine') for server-side.
QueryCollection is a Backbone Collection with extra functionality to provide the goodness of QueryEngine. You can create a new QueryCollection instance via queryEngineInstance = new QueryEngine.QueryCollection(models,options). And extend the QueryCollection by doing class MyQueryCollection extends QueryEngine.QueryCollection with CoffeeScript, or var MyQueryCollection = QueryEngine.QueryCollection.extend({}) with JavaScript.
Alternatively, we also provide a method to create our QueryCollections for us. You can use it via queryEngineInstance = new QueryEngine.createCollection(models,options). The arguments for this function are the same as those specified on the Backbone Collection Constructor documentation.
Returns: QueryCollection instance
createLiveCollection is the same as createCollection, however will turn on the live collection abilities. Returns: QueryCollection instance
These are the methods which are exposed to you via our Query Collections.
The QueryCollection accepts two arguments; models and options which are both optional. Models can be an array, or an object in the format of {modelId:{key1:value1,key2:value2}}. Options are an object, with support for the following options:
- filters: a javascript object of the filters to apply, in the format of
{filterName: filterFunction}, passed tosetfilters - queries: a javascript object of the queries to apply, in the format of
{queryName: queryObject}or{queryName: queryClassInstance}, passed tosetQueries - pills: a javascript object of the pills to apply, in the format of
{pillName: pillObject}or{pillName: pillClassInstance}, passed tosetPills - searchString: a string to use as the search string for our collection, passed to
setSearchString - parentCollection: a parent collection to subscribe to, must at least be a Backbone Collection
- live: a boolean value of whether or not to enable live support for our collection
Returns the filter function for the specified filterName, otherwise returns undefined.
Returns an object containing all the filters, indexed by the filter names, and valued by the filter functions.
Sets the filters for the current collection. Filters are an object indexed by the filter names, and valued by the filter functions. Returns chain.