npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mongoose-advanced-query-string

v1.0.4

Published

A wrapper for mongoose query functions: find() and aggregate() to let users be able to do query strings dynamically with find() and aggregate(). It lets them use dynamic filtering, sorting, projecting and paginating

Downloads

37

Readme

mongoose-advanced-query-string

Query any Model, quickly, dynamically and with a lot of options without writing code related to collections.

It helps making advanced query strings that uses mongoose queries: find() and aggregate(), and gives the possibility to use and chain dynamic filtering, sorting, projecting and paginating using query strings.

It handles query strings containing: fields, sort, limit and page keywords and filter keywords like: gt, gte, lt and lte.

Installation

$ npm install mongoose-advanced-query-string

Usage

const { ApiFeatures } = require('mongoose-advanced-query-string'); // for Find() queries
const { AggregateFeatures } = require('mongoose-advanced-query-string'); // for Aggregate queries

// 1) Example of ApiFeature Call on a mongoose "Model". 
const features = new ApiFeatures(Model.find(), req.query)
      .filter()
      .sort('createdAt')
      .limitFields('-email', '-age')
      .paginate(1, 100);

// Await the query to execute it and get the result.
const docs = await features.query;

/***********************************************************/
/***********************************************************/
// 2) Example of AggregateFeature Call on a mongoose "Model".
const aggFeatures = new AggregateFeatures(
      Model.aggregate([
        {...},
        {...},
        {...},
        {...},
      ]),
      req.query)
      .sort('slug')
      .limitFields('-__v')
      .paginate();

// Await the query to execute it and get the result.
const docs= await aggFeatures.aggregate;

Features

Dynamic querying a mongoose model with a query string, just by chaining functions, and they can be used with any Mongoose.Model.


ApiFeatures:

Here, the ApiFeatures constructor takes as first argument: Model.find() which is a query Mongoose query object. The second parameter is the query object that comes with the request (req.query).

Available functions that can be chained in any order: filter, sort, limiFields, paginate

const myQuery = Model.find(); //

const features = new ApiFeatures(myQuery, req.query)
      .filter()
      .sort()
      .limitFields()
      .paginate();

// Await the query to execute it and get the result.
const docs = await features.query;

AggregateFeatures:

Available functions that can be chained in any order: sort, limiFields, paginate

const myAggregation = Model.aggregate([{...},...,{...}]); //

const aggFeatures = new AggregateFeatures(myAggregation, req.query)
      .sort()
      .limitFields()
      .paginate();

// Await the query to execute it and get the result.
const docs= await aggFeatures.aggregate;

Details

Examples will be given, using a simple endpoint: Thread. It represents a simple thread model of a blog, having as fields: name, slug, type, members, online...

{{URL}}/threads //endpoints that gives all existing threads in database (triggers Thread.find()).

filter() : available only with Find()


Allows to filter documents, by the fields of the collection included in the query string. Example: domain.com/api/users?age=25&city=New+York.

  • Equality request?field=value;
  • Greater than/Greater than or equal request?field[gt]=value request?field[gte]=;
  • Lesser than/Lesser than or equal request?field[lt]=value request?field[lte]=;
const { ApiFeatures } = require('mongoose-advanced-query-string');

const features = new ApiFeatures(Model.find(), req.query).filter();

// Get threads that correspond to the query string.
const threads = await features.query;

Query string:

{{URL}}/threads?type=show // find all threads with type equals "show".
{{URL}}/threads?members[gte]=500&type=game // find threads with members count >= 500 AND type equals "game".
{{URL}}/threads?online[lt]=230&type=movie // find threads with curently online members <= 230 AND type equals "game".

sort(defaultSort):


Allows to sort the result in ascending/descending order, if "sort" parameter is included in the query string. If not, defaultSort is the default sort fields (can be separated by comma).

  • Asc: request?sort=field
  • Desc: request?sort=-field
  • Multiple sort: request?sort=field1,field2,-field3
const { ApiFeatures } = require('mongoose-advanced-query-string'); // for Find() queries
const { AggregateFeatures } = require('mongoose-advanced-query-string'); // for Aggregate queries

const features = new ApiFeatures(Model.find(), req.query).sort(); // will sort depending on the sort parameter in the query string.
//OR
const features = new AggregateFeatures (Model.aggregate(), req.query).sort('-createdAt'); // If no "sort" parameter, will sort by createdAt in descending order.

// Get threads that correspond to the query string.
const threads = await features.query;

Query string:

{{URL}}/threads?sort=postedAt // sort threads with postedAt in ascending order.
{{URL}}/threads?type=show&sort=members // find all threads with type equals "show" and sort by members number in descending order.
{{URL}}/threads?type=game&sort=-postedAt,-members // find threads with type equals "game", and sort by "posted at" first, then in case of equality, will sort by "members number".

limitFields(...defaultExcludedFields):


Allows to do a project on the resulting set. In other words, it allows to select what fields to output in result. It handles "projection" if "fields" parameter is used in the query string.

...defaultExcludedFields: A list of default fields to be excluded if no "fields" is specified in the query sting

  • Select fields: request?fields=field1,field2,field3: Will output a result with only "field1 field2 and field3" in the result.
  • Select All except: request?fields=-field1,-field2...: Will output a result with all the fields except for "field1 and field2" in the result.
const { ApiFeatures } = require('mongoose-advanced-query-string'); // for Find() queries
const { AggregateFeatures } = require('mongoose-advanced-query-string'); // for Aggregate queries

const features = new ApiFeatures(Model.find(), req.query).limitFields(); // will sort depending on the sort parameter in the query string.
//OR
const features = new AggregateFeatures (Model.aggregate(), req.query).limitFields('__v', '-_id'); // If no "fields" parameter, will exclude by default from the result __v and _id.

// Get threads that correspond to the query string.
const threads = await features.query;

Query string:

{{URL}}/threads?fields=-postedAt,-__v // will exclude "postedAt" and "__v" from the result.
{{URL}}/threads?fields=postedAt,__v // will select only "postedAt" and "__v" in the result.

N.B: Mixed values are not accepted.

paginate(defaultPage = 1, defaultLimit = 100)


Allow to do a get a subset of the resulting set, depending on the parameters used. It takes as parameters: page and limit.

  • Select fields: request?page=2&limit=10: Will output a result with values starting from the 11th element to the 20th. (Starts at page 2, not 1).
const { ApiFeatures } = require('mongoose-advanced-query-string'); // for Find() queries
const { AggregateFeatures } = require('mongoose-advanced-query-string'); // for Aggregate queries

const features = new ApiFeatures(Model.find(), req.query).paginate(); // will sort depending on the sort parameter in the query string.
//OR
const features = new AggregateFeatures (Model.aggregate(), req.query).paginate(2, 50); // If no "page" and "limit" parameters, will use pagination with inputted parameters.

// Get threads that correspond to the query string.
const threads = await features.query;

Query string:

{{URL}}/threads // will use pagination by default, where "page = 1" and "limit = 100"
{{URL}}/threads?page=2&limit=20 // will use pagination with "page = 2" and "limit = 20", i.e: documents from 21 to 40.

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change or add.

I'm open to optimize the project as much as it could be.

License

ISC