Query Syntax

JSData provides DS#filter for pulling collections of items out of the data store. DS#filter understands a query syntax that will allow you to filter, sort, offset & limit data. If your server or persistence layer can be taught to understand the same syntax, then you should be able to pass the same parameters to DS#findAll and then DS#filter and get the same data. All of the JSData Adapters except the http adapter understand this query syntax. I don't write your server code, so it's up to you on how your server returns data. If you don't want to mess with your server code, then you can provide JSData with a different implementation of the defaultFilter that follows your own query syntax.

The source code for JSData's defaultFilter implementation can be viewed here.

Filtering (where clause)

Filtering reduces data to a subset of the data according to some criteria. This is like your WHERE clause in SQL.

Operators

All operators work like this: match all items where item[field] operator criteriaValue is true. By default all clauses are ANDed together. You can turn a particular clause into an OR by prefixing the operator with a pipe (|).

Apply multiple filters to the same field

// Get all users where age is between 30 and 33
Users.filter({
  where: {
    'age': {
      '>=': 30,
      '<=': 33
    }
  }
});

Supports nested fields:

// Get all users where user.name.first is in ['John', 'Johnny']
Users.filter({
  where: {
    'name.first': {
      'in': ['John', 'Johnny']
    }
  }
});
==

Uses JavaScript's == operator to check for equality.

// Get all comments where comment.userId == 5
Comment.filter({
  where: {
    userId: {
      '==': 5
    }
  }
});

Shorthand for the == operator:

// Get all comments where comment.userId == 5
Comment.filter({
  userId: 5
});
===

Uses JavaScript's === operator to check for strict equality.

// Get all comments where comment.userId === 5
Comment.filter({
  where: {
    userId: {
      '===': 5
    }
  }
});
!=

Uses JavaScript's != operator to check for inequality.

// Get all comments where comment.userId != 5
Comment.filter({
  where: {
    userId: {
      '!=': 5
    }
  }
});
!==

Uses JavaScript's !== operator to check for strict inequality.

// Get all comments where comment.userId !== 5
Comment.filter({
  where: {
    userId: {
      '!==': 5
    }
  }
});
>

Uses JavaScript's > operator.

// Get all users where user.age > 30
User.filter({
  where: {
    age: {
      '>': 30
    }
  }
});
>=

Uses JavaScript's >= operator.

// Get all users where user.age >= 30
User.filter({
  where: {
    age: {
      '>=': 30
    }
  }
});
<

Uses JavaScript's < operator.

// Get all users where user.age < 30
User.filter({
  where: {
    age: {
      '<': 30
    }
  }
});
<=

Uses JavaScript's <= operator.

// Get all users where user.age <= 30
User.filter({
  where: {
    age: {
      '<=': 30
    }
  }
});
isectEmpty

Looks for items where item[field] does not intersect the given array.

// Get all posts where post.tags does not intersect ['baseball', 'football']
Post.filter({
  where: {
    tags: {
      'isectEmpty': ['baseball', 'football']
    }
  }
});
isectNotEmpty

Looks for items where item[field] intersects the given array.

// Get all posts where post.tags intersects ['baseball', 'football']
Post.filter({
  where: {
    tags: {
      'isectNotEmpty': ['baseball', 'football']
    }
  }
});
in

Looks for items where item[field] is in the given term, which can be a string or an array.

// Get all users where user.name is in "John Anderson"
User.filter({
  where: {
    name: {
      'in': 'John Anderson'
    }
  }
});

// Get all users where user.role is in ["admin", "owner"]
User.filter({
  where: {
    role: {
      'in': ['admin', 'owner']
    }
  }
});
notIn

Looks for items where item[field] is not in the given term, which can be a string or an array.

// Get all users where user.name is NOT in "John Anderson"
User.filter({
  where: {
    name: {
      'notIn': 'John Anderson'
    }
  }
});

// Get all users where user.role is NOT in ["admin", "owner"]
User.filter({
  where: {
    role: {
      'notIn': ['admin', 'owner']
    }
  }
});
contains

Looks for items where item[field] (which can be a string or an array) contains the given term.

// Get all users where user.name contains "John"
User.filter({
  where: {
    name: {
      'contains': 'John'
    }
  }
});

// Get all users where user.roles contains "admin"
User.filter({
  where: {
    roles: {
      'contains': 'admin'
    }
  }
});
notContains

Looks for items where item[field] (which can be a string or an array) does not contain the given term.

// Get all users where user.name does NOT contain "John"
User.filter({
  where: {
    name: {
      'notContains': 'John'
    }
  }
});

// Get all users where user.roles does NOT contain "admin"
User.filter({
  where: {
    roles: {
      'notContains': 'admin'
    }
  }
});
like

Looks for items where item[field] (a string) matches a wildcard search term.

You can append RegExp modifiers to the operator (i, U, etc).

// Get all users where user.name matches "john" in any letter case combination.
User.filter({
  where: {
    name: {
      'likei': 'john'
    }
  }
});

// Get all users where user.name contains "john" and "doe" anywhere in the name.
User.filter({
  where: {
    name: {
      'like': '%john%doe%'
    }
  }
});

Sorting (sort/orderBy)

Sorting orders the filtered data by a particular field or fields. This is like your ORDER BY clause in SQL.

// Sorts users by age in ascending order
User.filter({
  orderBy: 'age'
});

// Sorts users by age and then name in ascending order
User.filter({
  orderBy: ['age', 'name']
});

// Sorts users by age in descending order
User.filter({
  orderBy: [
    ['age', 'DESC']
  ]
});

// Sorts users by age in descending order and then sort by name in ascending order to break a tie
User.filter({
  orderBy: [
    ['age', 'DESC'],
    ['name', 'ASC']
  ]
});

Paging (offset/skip & limit)

Paging involves skipping and limiting data filtered and sorted data. This is like your OFFSET and LIMIT clauses in SQL.

var PAGE_SIZE = 20;
var currentPage = 1;

// Grab the first "page" of posts
Post.filter({
  offset: PAGE_SIZE * (currentPage - 1),
  limit: PAGE_SIZE
});