JavaScripting

The definitive source of the best
JavaScript libraries, frameworks, and plugins.


  • ×

    Sift.js

    filter arrays using mongodb queries
    Filed under  › 

    • 🔾46%Overall
    • 980
    • 10.1 days
    • 🕩77
    • 👥15

    validate objects & filter arrays with mongodb queries

    Build Status

    For extended documentation, checkout http://docs.mongodb.org/manual/reference/operator/query/

    Features:

    Node.js Examples

    import sift from "sift";
    
    //intersecting arrays
    var result = ["hello", "sifted", "array!"].filter(
      sift({ $in: ["hello", "world"] })
    ); //['hello']
    
    //regexp filter
    var result = ["craig", "john", "jake"].filter(sift(/^j/)); //['john','jake']
    
    // function filter
    var testFilter = sift({
      //you can also filter against functions
      name: function(value) {
        return value.length == 5;
      }
    });
    
    var result = [
      {
        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
    

    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">
          //regexp filter
          var sifted = sift(/^j/, ["craig", "john", "jake"]); //['john','jake']
        </script>
      </head>
      <body></body>
    </html>
    

    API

    .sift(query: MongoQuery, options?: SiftOptions): Function

    • query - the filter to use against the target array
    • options - select - value selector - expressions - custom expressions

    With an array:

    ["craig", null].filter(sift({ $exists: true })); //['craig']
    

    Without an array, a sifter is returned:

    var existsFilter = sift({ $exists: true });
    
    existsFilter("craig"); //true
    existsFilter(null); //false
    ["craig", null].filter(existsFilter); //['craig']
    

    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); //false
    siftExists("craig"); //true
    

    Supported Operators:

    See MongoDB's advanced queries for more info.

    \$in

    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"] } })
    );
    

    \$nin

    Opposite of \$in:

    //filtered: ['Haiti','Peru','Chile']
    ["Brazil", "Haiti", "Peru", "Chile"].filter(
      sift({ $nin: ["Costa Rica", "Brazil"] })
    );
    

    \$exists

    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: 'Craig', city: 'Minneapolis' }]
    [{ name: "Craig", city: "Minneapolis" }, { name: "Tim" }].filter(
      sift({ city: { $exists: false } })
    );
    

    \$gte

    Checks if a number is >= value:

    //filtered: [2, 3]
    [0, 1, 2, 3].filter(sift({ $gte: 2 }));
    

    \$gt

    Checks if a number is > value:

    //filtered: [3]
    [0, 1, 2, 3].filter(sift({ $gt: 2 }));
    

    \$lte

    Checks if a number is <= value.

    //filtered: [0, 1, 2]
    [0, 1, 2, 3].filter(sift({ $lte: 2 }));
    

    \$lt

    Checks if number is < value.

    //filtered: [0, 1]
    [0, 1, 2, 3].filter(sift({ $lt: 2 }));
    

    \$eq

    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" })
    );
    

    \$ne

    Checks if query !== value.

    //filtered: [{ state: 'CA' }, { state: 'WI'}]
    [{ state: "MN" }, { state: "CA" }, { state: "WI" }].filter(
      sift({ state: { $ne: "MN" } })
    );
    

    \$mod

    Modulus:

    //filtered: [300, 600]
    [100, 200, 300, 400, 500, 600].filter(sift({ $mod: [3, 0] }));
    

    \$all

    values must match everything in array:

    //filtered: [ { tags: ['books','programming','travel' ]} ]
    [
      { 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.

    //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

    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" }] }));
    

    \$nor

    opposite of or:

    //filtered: [ { name: 'Tim', state: 'MN' }, { name: 'Joe', state: 'CA' }]
    [
      { 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:

    //filtered: ['food','cooking']
    [{ 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 })); //returns single date
    [new Date(), 4342, "hello world"].filter(sift({ $type: String })); //returns ['hello world']
    

    \$regex

    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"]
    

    \$where

    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"]
    

    \$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 }
          }
        }
      })
    ); // {month:'august', casts:[{id:3, value: 1000},{id: 4, value: 4000}]}
    

    \$not

    Not expression:

    ["craig", "tim", "jake"].filter(sift({ $not: { $in: ["craig", "tim"] } })); //['jake']
    ["craig", "tim", "jake"].filter(sift({ $not: { $size: 5 } })); //['tim','jake']
    

    Custom expressions

    var filter = sift(
      {
        $customMod: 2
      },
      {
        expressions: {
          $customMod: function(query, value) {
            return query % value;
          }
        }
      }
    );
    
    [1, 2, 3, 4, 5].filter(filter); // 1, 3, 5
    

    MongoDB behavior differences

    There are some cases where Sift behaves a bit differently than Mongodb.

    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") } })
    );
    
    Show All