Installation: npm install sift
, or yarn add sift
For extended documentation, checkout http://docs.mongodb.org/manual/reference/operator/query/
- Supported operators: $in, $nin, $exists, $gte, $gt, $lte, $lt, $eq, $ne, $mod, $all, $and, $or, $nor, $not, $size, $type, $regex, $where, $elemMatch
- Regexp searches
- Supports node.js, and web
- Custom Operations
- Tree-shaking (omitting functionality from web app bundles)
import sift from "sift";
// intersecting arrays
const result1 = ["hello", "sifted", "array!"].filter(
sift({ $in: ["hello", "world"] }),
); // ['hello']
// regexp filter
const result2 = ["craig", "john", "jake"].filter(sift(/^j/)); //['john','jake']
// function filter
const testFilter = sift({
//you can also filter against functions
name: function (value) {
return value.length == 5;
},
});
const result3 = [
{
name: "craig",
},
{
name: "john",
},
{
name: "jake",
},
].filter(testFilter); // filtered: [{ name: 'craig' }]
// you can test *single values* against your custom sifter
testFilter({ name: "sarah" }); //true
testFilter({ name: "tim" }); //false
Creates a filter with all the built-in MongoDB query operations.
query
- the filter to use against the target arrayoptions
operations
- custom operationscompare
- compares difference between two values
Example:
import sift from "sift";
const test = sift({ $gt: 5 });
console.log(test(6)); // true
console.log(test(4)); // false
[3, 4, 5, 6, 7].filter(test); // [6, 7]
Creates a filter function without built-in MongoDB query operations. This is useful if you're looking to omit certain operations from application bundles. See Omitting built-in operations for more info.
import { createQueryTester, $eq, $in } from "sift";
const filter = createQueryTester({ $eq: 5 }, { operations: { $eq, $in } });
Used for custom operations.
import { createQueryTester, createEqualsOperation, $eq, $in } from "sift";
const filter = createQueryTester(
{ $mod: 5 },
{
operations: {
$something(mod, ownerQuery, options) {
return createEqualsOperation(
(value) => value % mod === 0,
ownerQuery,
options,
);
},
},
},
);
filter(10); // true
filter(11); // false
See MongoDB's advanced queries for more info.
array value must be $in the given query:
Intersecting two arrays:
// filtered: ['Brazil']
["Brazil", "Haiti", "Peru", "Chile"].filter(
sift({ $in: ["Costa Rica", "Brazil"] }),
);
Here's another example. This acts more like the $or operator:
[{ name: "Craig", location: "Brazil" }].filter(
sift({ location: { $in: ["Costa Rica", "Brazil"] } }),
);
Opposite of $in:
// filtered: ['Haiti','Peru','Chile']
["Brazil", "Haiti", "Peru", "Chile"].filter(
sift({ $nin: ["Costa Rica", "Brazil"] }),
);
Checks if whether a value exists:
// filtered: ['Craig','Tim']
sift({ $exists: true })(["Craig", null, "Tim"]);
You can also filter out values that don't exist
// filtered: [{ name: "Tim" }]
[{ name: "Craig", city: "Minneapolis" }, { name: "Tim" }].filter(
sift({ city: { $exists: false } }),
);
Checks if a number is >= value:
// filtered: [2, 3]
[0, 1, 2, 3].filter(sift({ $gte: 2 }));
Checks if a number is > value:
// filtered: [3]
[0, 1, 2, 3].filter(sift({ $gt: 2 }));
Checks if a number is <= value.
// filtered: [0, 1, 2]
[0, 1, 2, 3].filter(sift({ $lte: 2 }));
Checks if number is < value.
// filtered: [0, 1]
[0, 1, 2, 3].filter(sift({ $lt: 2 }));
Checks if query === value
. Note that $eq can be omitted. For $eq, and $ne
// filtered: [{ state: 'MN' }]
[{ state: "MN" }, { state: "CA" }, { state: "WI" }].filter(
sift({ state: { $eq: "MN" } }),
);
Or:
// filtered: [{ state: 'MN' }]
[{ state: "MN" }, { state: "CA" }, { state: "WI" }].filter(
sift({ state: "MN" }),
);
Checks if query !== value
.
// filtered: [{ state: 'CA' }, { state: 'WI'}]
[{ state: "MN" }, { state: "CA" }, { state: "WI" }].filter(
sift({ state: { $ne: "MN" } }),
);
Modulus:
// filtered: [300, 600]
[100, 200, 300, 400, 500, 600].filter(sift({ $mod: [3, 0] }));
values must match everything in array:
// filtered: [ { tags: ['books','programming','travel' ]} ]
[
{ tags: ["books", "programming", "travel"] },
{ tags: ["travel", "cooking"] },
].filter(sift({ tags: { $all: ["books", "programming"] } }));
ability to use an array of expressions. All expressions must test true.
// filtered: [ { name: 'Craig', state: 'MN' }]
[
{ name: "Craig", state: "MN" },
{ name: "Tim", state: "MN" },
{ name: "Joe", state: "CA" },
].filter(sift({ $and: [{ name: "Craig" }, { state: "MN" }] }));
OR array of expressions.
// filtered: [ { name: 'Craig', state: 'MN' }, { name: 'Tim', state: 'MN' }]
[
{ name: "Craig", state: "MN" },
{ name: "Tim", state: "MN" },
{ name: "Joe", state: "CA" },
].filter(sift({ $or: [{ name: "Craig" }, { state: "MN" }] }));
opposite of or:
// filtered: [{ name: 'Joe', state: 'CA' }]
[
{ name: "Craig", state: "MN" },
{ name: "Tim", state: "MN" },
{ name: "Joe", state: "CA" },
].filter(sift({ $nor: [{ name: "Craig" }, { state: "MN" }] }));
Matches an array - must match given size:
// filtered: ['food','cooking']
[{ tags: ["food", "cooking"] }, { tags: ["traveling"] }].filter(
sift({ tags: { $size: 2 } }),
);
Matches a values based on the type
[new Date(), 4342, "hello world"].filter(sift({ $type: Date })); // returns single date
[new Date(), 4342, "hello world"].filter(sift({ $type: String })); // returns ['hello world']
Matches values based on the given regular expression
["frank", "fred", "sam", "frost"].filter(
sift({ $regex: /^f/i, $nin: ["frank"] }),
); // ["fred", "frost"]
["frank", "fred", "sam", "frost"].filter(
sift({ $regex: "^f", $options: "i", $nin: ["frank"] }),
); // ["fred", "frost"]
Matches based on some javascript comparison
[{ name: "frank" }, { name: "joe" }].filter(
sift({ $where: "this.name === 'frank'" }),
); // ["frank"]
[{ name: "frank" }, { name: "joe" }].filter(
sift({
$where: function () {
return this.name === "frank";
},
}),
); // ["frank"]
Matches elements of array
var bills = [
{
month: "july",
casts: [
{
id: 1,
value: 200,
},
{
id: 2,
value: 1000,
},
],
},
{
month: "august",
casts: [
{
id: 3,
value: 1000,
},
{
id: 4,
value: 4000,
},
],
},
];
var result = bills.filter(
sift({
casts: {
$elemMatch: {
value: { $gt: 1000 },
},
},
}),
); // {month:'august', casts:[{id:3, value: 1000},{id: 4, value: 4000}]}
Not expression:
["craig", "tim", "jake"].filter(sift({ $not: { $in: ["craig", "tim"] } })); // ['jake']
["craig", "tim", "jake"].filter(sift({ $not: { $size: 5 } })); // ['tim','jake']
Mongodb allows you to do date comparisons like so:
db.collection.find({ createdAt: { $gte: "2018-03-22T06:00:00Z" } });
In Sift, you'll need to specify a Date object:
collection.find(
sift({ createdAt: { $gte: new Date("2018-03-22T06:00:00Z") } }),
);
Sift works like MongoDB out of the box, but you're also able to modify the behavior to suite your needs.
You can register your own custom operations. Here's an example:
import sift, { createEqualsOperation } from "sift";
var filter = sift(
{
$customMod: 2,
},
{
operations: {
$customMod(params, ownerQuery, options) {
return createEqualsOperation(
(value) => value % params !== 0,
ownerQuery,
options,
);
},
},
},
);
[1, 2, 3, 4, 5].filter(filter); // [1, 3, 5]
You can create a filter function that omits the built-in operations like so:
import { createQueryTester, $in, $all, $nin, $lt } from "sift";
const test = createQueryTester(
{
$eq: 10,
},
{ operations: { $in, $all, $nin, $lt } },
);
[1, 2, 3, 4, 10].filter(test);
For bundlers like Webpack
and Rollup
, operations that aren't used are omitted from application bundles via tree-shaking.