Universe
The easiest and fastest way to explore your data
Before Universe, exploring and filtering large datasets in javascript meant constant data looping, complicated indexing, and countless lines of code to dissect your data.
With Universe, you can be there in just a few lines of code. You've got better things to do than write intense map-reduce functions or learn the intricate inner-workings of Crossfilter ;)
Features
- Simple, yet powerful query syntax
- Built on, and tightly integrated with Crossfilter, and Reductio - the fastest multi-dimensional JS data frameworks available
- Real-time updates to query results as you filter
- Flexible filtering system
- Automatic and invisible management of data indexing and memory
- Post Aggregation
Features in the Pipeline
Demos
- Basic Usage (Codepen)
API
Getting Started
Installation
NPM
npm install universe --save
CDN or Download from the npmcdn load or download universe.js or universe.min.js file as part of your application.
Create a new Universe
Pass universe
an array of objects or a Crossfilter instance:
var universe = var myUniverse =
Query your data
Use your data
Explore your data
As you filter your data on the universe level, every query's result is updated in real-time to reflect changes in aggregation
// Filter records where 'type' === 'visa' // Filter records where 'type' === 'visa' or 'tab' // Filter records where 'total' is between 50 and 100 // Filter records using an expressive and JSON friendly query syntax // Or if you're feeling powerful, just write your own custom filter function // Clear the filters for the 'type' column // Apply many filters in one go // Clear all of the filters
Clean Up
// Remove a column index // Remove all columns
API #
universe( [data] , {config} ) #
-
Description
- Creates a new universe instance
-
Parameters
[data]
- An array of objects{config}
- Optional configurations for this Universe instance{generatedColumns}
- An object of keys and their respective accessor functions used to dynamically generate columns.
-
Returns a
promise
that is resolved with the universe instance -
- Generated Columns Example
- Generated Columns Example
.query( {queryObject} ) #
-
Description
- Creates a new query from a universe instance
-
Parameters
queryObject
:groupBy
- Property name, property string representation, or even a function! (see.column()
method),select
- An object of column aggregations and/or column names$aggregation
- Aggregations are prefixed with a$
columnName
- Creates a nested column with the name provided
filter
- A filter object that is applied to the query (similar to awhere
clause in mySQL)
-
Returns
promise
, resolved with a query results objectdata
- The result of the querygroup
- The crossfilter/reductio group used to build the querydimension
- The crossfilter dimension used to build the querycrossfilter
- The crossfilter that runs this universeuniverse
- The current instance of the universe. Return this to keep chaining via promises
.filter( columnKey, filterObject, isArray, replace ) #
-
Description
- Filters everything in the universe to only include rows that match certain conditions. Queries automatically and instantaneously update their values and aggregations.
-
Parameters
columnKey
- The object property to filter on,
-
Returns
promise
resolved with- universe instance
.filterAll() #
- Description
- Clears all filters accross all dimensiona.
- Returns
promise
resolved with- universe instance
.column( columnKey/columnObject ) #
-
Description
- Use to optionally pre-index a column. Accepts either:
- String or number corresponding to the key or index of the column. eg.
propertyName
or2
- A nested string representation of the property. eg.
a.nested.property
,a.nested[number]
- Multiple singular key shorthand eg.
['prop1', 'prop2', 'prop3']
- A callback function that returns the key (very powerful) eg.
function(d){return d.myProperty}
- String or number corresponding to the key or index of the column. eg.
- Use to optionally pre-index a column. Accepts either:
-
Parameters
columnKey
- the column property or array index you would like to pre-compile eg.
columnObject
allows you to override the column type, otherwise it is calculated automatically:
-
Returns
promise
resolved with- universe instance
.clear( columnKey/columnObject/[columnKeys/columnObjects] ) #
-
Description
- Clears individual or all column defenitions and indexes
-
Parameters
columnKey
- the column property or array of columns you would like to clear eg.
-
Returns
promise
resolved with- universe instance
.add( [data] ) #
- Description
- Adds additional data to a universe instance. This data will be indexed, aggregated and queries/filters immediately updated when added.
- Parameters
[data]
- An new array of objects similar to the original dataset
- Returns
promise
resolved with- universe instance
Post Aggregation #
Post aggregation methods can be run on query results to further modify your data. Just like queries, the results magically and instantly respond to filtering.
- Each post aggregation is very powerful, but not all post aggregations can be chained together.
Locking a query
A majority of the time, you're probably only interested in the end result of a query chain. For this reason, Post Aggregations default to mutating the data of their direct parent (unless the parent is the original query), thereby avoiding unnecessary copying of data.
On the other hand, if you plan on accessing data at any point in the middle of a query chain, you will need to lock()
that query's results. This ensure's it won't be overwritten or mutated by any further post aggregation.
Note: Running more than 1 post aggregation on a query will automatically lock the parent query.
Without locking the above query before using .limit(5)
, the all
data array would have been mutated by .limit(5)
.sortByKey(descending) #
- Description
- Sort results by key (ascending or descending)
- Parameters
descending
- Pass true to sortKeys in descending order
- Returns
promise
resolved with- query instance
.limit(n, n2) #
- Description
- Limit results to those between
n
andn2
. Ifn2
is not passed, will limit to the firstn
records
- Limit results to those between
- Parameters
n
- Start index. Defaults to 0 ifnull
orundefined
,n2
- End index. Defaults toquery.data.length
ifnull
. Ifundefined
, will limit to the firstn
records instead.
- Returns
promise
resolved with- query instance
.squash(n, n2, aggregationMap, keyName) #
-
Description
- Takes records from
n
ton2
and reduces them to a single record using the aggregationMap
- Takes records from
-
Parameters
n
- Start index. Defaults to0
iffalse
-yn2
- End index. Defaults toquery.data.length
iffalse
-yaggregationMap
- A 1:1 map of property to the aggregation to be used when combining the recordskeyName
(optional) - The key to be used for the new record. Defaults toOther
-
Returns
promise
resolved with- query instance
.change(n, n2, changeFields) #
-
Description
- Determines the change from the
n
ton2
using the keys inchangeFields
- Determines the change from the
-
Parameters
n
- Start index. Defaults to0
iffalse
-yn2
- End index. Defaults toquery.data.length
iffalse
-ychangeFields
- An object or array, referencing the fields to measure for change
-
Returns
promise
resolved with- query instance
query.data
is now an object:
key: 'nKey' 'n2Key'value:sumChange: 7otherColumn:avgChange: 4
- query instance
.changeMap(changeMapObj) #
-
Description
- Determines incremental change for each record across the fields defined in
changeMapObj
- Determines incremental change for each record across the fields defined in
-
Parameters
changeMapObj
- An object or array, referencing the fields to measure for change
-
Returns
promise
resolved with- query instance
query.data
records are now decorated with incremental change data:
...key: 'tag5'value:sum: 5sumChange: 7sumChangeFromStart: 0sumChangeFromEnd: 30otherColumn:avgChange: 4avgChangeFromStart: -4avgChangeFromEnd: -20...
- query instance
.post(callback) #
- Description
- Use a custom callback function to perform your own post aggregations.
- Parameters
callback
- the callback function to execute. It accepts the following parameters:query
- the new query object. A fresh reference (or copy, if the parent is locked) is located atquery.data
. It is highly discouraged to change any other property on this objectparentQuery
- the parent query.
- You may optionally return a promise-like value for asynchronous processing
- Returns
promise
resolved with- query instance
Pro Tips #
No Arrays Necessary
Don’t want to use arrays in your aggregations? No problem, because this:
… is now easier written like this:
No Objects Necessary, either!
What’s that? Don’t like the verbosity of objects or arrays? Use the new string syntax!
Pre-compile Columns
Pro-Tip: You can also pre-compile column indices before querying. Otherwise, ad-hoc indices are created and managed automagically for you anyway.