validate objects & filter arrays with mongodb queries
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
- sub object searching
- dot notation searching
- Supports node.js, and web
- Small (2 kb minified) library
- Custom Expressions
- filtering of immutable datastructures
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 = sift(/^j/, ["craig", "john", "jake"]);
</script>
</head>
<body></body>
</html>
API
.sift(query: MongoQuery, options?: SiftOptions): Function
query
- the filter to use against the target arrayoptions
select
- value selectorexpressions
- custom expressionscompare
- compares difference between two valuescomparable
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 a selector:
var omitNameFilter = sift({ $exists: true }, function(user) {
return !!user.name;
});
[
{
name: "Craig"
},
{
name: null
}
].filter(omitNameFilter);
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 } }));
MongoDB behavior differences
There are some cases where Sift behaves a bit differently than Mongodb.
Adding custom behavior
Sift works like MongoDB out of the box, but you're also able to modify the behavior to suite your needs.
Expressions
Sift comes with expressions like $not
, $eq
, and others, but you can also add your own.
var filter = sift(
{
$customMod: 2
},
{
expressions: {
$customMod: function(query, value) {
return query % value;
}
}
}
);
[1, 2, 3, 4, 5].filter(filter);
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") } })
);