Installation: npm install sift
, or yarn add sift
Sift is a tiny library for using MongoDB queries in Javascript
For extended documentation, checkout http://docs.mongodb.org/manual/reference/operator/query/
Features:
- 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)
Examples
import sift from "sift";
const result1 = ["hello", "sifted", "array!"].filter(
sift({ $in: ["hello", "world"] }),
);
const result2 = ["craig", "john", "jake"].filter(sift(/^j/));
const testFilter = sift({
name: function (value) {
return value.length == 5;
},
});
const result3 = [
{
name: "craig",
},
{
name: "john",
},
{
name: "jake",
},
].filter(testFilter);
testFilter({ name: "sarah" });
testFilter({ name: "tim" });
API
sift(query: MongoQuery, options?: Options): Function
Creates a filter with all the built-in MongoDB query operations.
query
- the filter to use against the target arrayoptions
Example:
import sift from "sift";
const test = sift({ $gt: 5 });
console.log(test(6));
console.log(test(4));
[3, 4, 5, 6, 7].filter(test);
createQueryTester(query: Query, options?: Options): Function
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 } });
createEqualsOperation(params: any, ownerQuery: Query, options: Options): Operation
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);
filter(11);
Supported Operators
See MongoDB's advanced queries for more info.
$in
array value must be $in the given query:
Intersecting two arrays:
["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"] } }),
);
$nin
Opposite of $in:
["Brazil", "Haiti", "Peru", "Chile"].filter(
sift({ $nin: ["Costa Rica", "Brazil"] }),
);
$exists
Checks if whether a value exists:
sift({ $exists: true })(["Craig", null, "Tim"]);
You can also filter out values that don't exist
[{ name: "Craig", city: "Minneapolis" }, { name: "Tim" }].filter(
sift({ city: { $exists: false } }),
);
$gte
Checks if a number is >= value:
[0, 1, 2, 3].filter(sift({ $gte: 2 }));
$gt
Checks if a number is > value:
[0, 1, 2, 3].filter(sift({ $gt: 2 }));
$lte
Checks if a number is <= value.
[0, 1, 2, 3].filter(sift({ $lte: 2 }));
$lt
Checks if number is < value.
[0, 1, 2, 3].filter(sift({ $lt: 2 }));
$eq
Checks if query === value
. Note that $eq can be omitted. For $eq, and $ne
[{ state: "MN" }, { state: "CA" }, { state: "WI" }].filter(
sift({ state: { $eq: "MN" } }),
);
Or:
[{ state: "MN" }, { state: "CA" }, { state: "WI" }].filter(
sift({ state: "MN" }),
);
$ne
Checks if query !== value
.
[{ state: "MN" }, { state: "CA" }, { state: "WI" }].filter(
sift({ state: { $ne: "MN" } }),
);
$mod
Modulus:
[100, 200, 300, 400, 500, 600].filter(sift({ $mod: [3, 0] }));
$all
values must match everything in array:
[
{ tags: ["books", "programming", "travel"] },
{ tags: ["travel", "cooking"] },
].filter(sift({ tags: { $all: ["books", "programming"] } }));
$and
ability to use an array of expressions. All expressions must test true.
[
{ name: "Craig", state: "MN" },
{ name: "Tim", state: "MN" },
{ name: "Joe", state: "CA" },
].filter(sift({ $and: [{ name: "Craig" }, { state: "MN" }] }));
$or
OR array of expressions.
[
{ name: "Craig", state: "MN" },
{ name: "Tim", state: "MN" },
{ name: "Joe", state: "CA" },
].filter(sift({ $or: [{ name: "Craig" }, { state: "MN" }] }));
$nor
opposite of or:
[
{ name: "Craig", state: "MN" },
{ name: "Tim", state: "MN" },
{ name: "Joe", state: "CA" },
].filter(sift({ $nor: [{ name: "Craig" }, { state: "MN" }] }));
$size
Matches an array - must match given size:
[{ tags: ["food", "cooking"] }, { tags: ["traveling"] }].filter(
sift({ tags: { $size: 2 } }),
);
$type
Matches a values based on the type
[new Date(), 4342, "hello world"].filter(sift({ $type: Date }));
[new Date(), 4342, "hello world"].filter(sift({ $type: String }));
$regex
Matches values based on the given regular expression
["frank", "fred", "sam", "frost"].filter(
sift({ $regex: /^f/i, $nin: ["frank"] }),
);
["frank", "fred", "sam", "frost"].filter(
sift({ $regex: "^f", $options: "i", $nin: ["frank"] }),
);
$where
Matches based on some javascript comparison
[{ name: "frank" }, { name: "joe" }].filter(
sift({ $where: "this.name === 'frank'" }),
);
[{ name: "frank" }, { name: "joe" }].filter(
sift({
$where: function () {
return this.name === "frank";
},
}),
);
$elemMatch
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 },
},
},
}),
);
$not
Not expression:
["craig", "tim", "jake"].filter(sift({ $not: { $in: ["craig", "tim"] } }));
["craig", "tim", "jake"].filter(sift({ $not: { $size: 5 } }));
Date comparison
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") } }),
);
Custom behavior
Sift works like MongoDB out of the box, but you're also able to modify the behavior to suite your needs.
Custom operations
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);
Omitting built-in operations
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.