Installation: npm install sift
, or yarn add sift
validate objects & filter arrays with mongodb queries
![Build Status](https://secure.travis-ci.org/crcn/sift.js.png)
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
- Function filtering
- dot notation searching
- Supports node.js, and web
- Custom Operations
Node.js Examples
import sift from "sift";
var result = ["hello", "sifted", "array!"].filter(
sift({ $in: ["hello", "world"] })
);
var result = ["craig", "john", "jake"].filter(sift(/^j/));
var testFilter = sift({
name: function(value) {
return value.length == 5;
}
});
var result = [
{
name: "craig"
},
{
name: "john"
},
{
name: "jake"
}
].filter(testFilter);
testFilter({ name: "sarah" });
testFilter({ name: "tim" });
Browser Examples
<html>
<head>
<script
src="https://raw.github.com/crcn/sift.js/master/sift.min.js"
type="text/javascript"
></script>
<script type="text/javascript">
var sifted = ["craig", "john", "jake"].filter(sift(/^j/));
</script>
</head>
<body></body>
</html>
API
.sift(query: MongoQuery, options?: SiftOptions): Function
query
- the filter to use against the target arrayoptions
expressions
- custom expressionscompare
- compares difference between two values
With an array:
["craig", null].filter(sift({ $exists: true }));
Without an array, a sifter is returned:
var existsFilter = sift({ $exists: true });
existsFilter("craig");
existsFilter(null);
["craig", null].filter(existsFilter);
With your sifter, you can also test values:
siftExists(null);
siftExists("craig");
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, { EqualsOperation } from "sift";
var filter = sift(
{
$customMod: 2
},
{
operations: {
$customMod(params, ownerQuery, options) {
return new EqualsOperation(
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 } from "sift";
import { $in, $all, $nin, $lt } from "sift/operations";
const test = createQueryTester(
{
$eq: 10
},
{ $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.