Isomorphic fluent interface for building query objects

npm install mekanika-query
4 downloads in the last week
6 downloads in the last month


query is an isomorphic interface for building Query Objects.

Alpha release version

Code Climate

query()                  // Create query
  .from( 'user' )        // Resource to execute on
  .where( 'name' )       // Constraint field
    .in( ['Tom','Bob'] ) //  - operator and conditions
  .and( 'age' )          // AND constraint (also supports `.or()`)
    .gt( 25 )            //  - operator and conditions
  .limit( 20 )           // Number of results
  .offset( 5 )           // Result offset (used for paging)
  .done( callback );     // Execute and return `callback( err, res )`


  npm install --production


Initiate a query:

  // -> new Query

Queries require setting:

  • .{action}(...) - {action} to execute (find, save, etc)

Execute a query with .done( cb ). Calls can be chained to this query# instance and executed by calling:

    .from( 'users' )
    .done( cb );
    // `cb` is required callback, passed `cb( err, res, query )`

Query actions (Query#action)

The available actions supported by query are:

  • create
  • save
  • update
  • remove
  • find

Setting match constraints

Constraints are set using the .where( field ).<operator>( condition ) pattern.

The field is the named target to apply an operator (the criteria) and condition to. Operators include:

  • .eq( value ) - Equality (exact) match. Alias: .is().
  • .neq( value ) - Not equal to. Alias not().
  • .in( array ) - Where field value is in the array.
  • .nin( array ) - Where field value is not in the array.
  • .all( array ) - everything in the list
  • .lt( number ) - Less than number.
  • .gt( number ) - More (greater) than than number.
  • .lte( number ) - Less than or equal to number.
  • .gte( number ) - More (greater) than or equal to number.


query().where( 'name' ).is( 'Mordecai' );
// Match any record with `{name: 'Mordecai'}`

query().where( 'age' ).gte( 21 );
// Match records where `age` is 21 or higher


query supports pre and post processing middleware, and:

  • is only executed if an adapter is set
  • can add multiple methods to pre and post
  • executes in the order it is added


Pre-processing middleware is executed before the query is handed to its adapter, and are passed fn( query ) with this query as their only parameter.

This enables you to modify the query prior to adapter execution.

There are no special requirements for pre-middleware functions.

  function preHandler( qry ) {
    qry.resource += ':magic_suffix';
    // Example modification of the query passed to the adapter

  query().pre( preHandler );
  // Adds `preHandler` to the pre-processing queue

Also supports adding multiple middleware methods

  query().pre( fn1 ).pre( fn2 ); // etc


Post-processing middleware is run after the adapter execution is complete, and are passed fn( err, res, query ), where err and res are responses from the adapter, and query is this query.

This enables you to modify the results from the server.

Post middleware functions must return an [error, results] array, which will presumably include your modifications.

  function postHandler( err, res, qry ) {
    // MUST return [err, res] array
    err = 'My modified error';
    res = 'Custom results!';
    return [err, res];

  query().post( postHandler );
  // Adds `postHandler` to post-processing queue

Also supports adding multiple middleware methods:

  query().post( fn1 ).post( fn2 ); // etc


query can optionally delegate execution to an adapter.

This means that calling .done( cb ) on a query will delegate to:

  query#adapter.exec( query, cb );

Setting an adapter

Pass an adapter directly to each query:

  var myadapter = require('my-adapter');
  query( myadapter );

This is syntactic sugar for the identical call:

  query().useAdapter( myadapter );

See for more details on adapters.

Advanced: Custom adapter classes

You may also specify a custom adapter class handler on the query class itself (note the lack of query() parentheses):

  query.adapterClass( adapter.Adapter );

This exposes the adapter cache via adapter( 'adapterName' ).

Adapter references may then be passed as strings, and are retrieved from the adapter cache:

  query( 'adapterName' );

Which is syntactic sugar for:

  query().use( 'adapterName' );


Ensure you have installed the development dependencies:

  make install

To run the tests:

  make test

Test Coverage

To generate a coverage.html report, run:

make coverage


If you find a bug, report it.


GNU Lesser General Public License, either version 3 of the License, or (at your option) any later version (LGPL3+). See the License. files for full details.

npm loves you