Skip to content

vazco/sparrowql

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

vazco/sparrowql

Logo

Declarative MongoDB aggregations.

Contribute | Usage | Documentation | FAQ

Coverage License Downloads GitHub Discussions Version Status

What's included?

  • Automatic $lookup only if needed
  • Declarative pipelines generation
  • Optimized for multi-collection queries

Reasons to use SparrowQL

SparrowQL was created to make your work with multi-collection queries much easier and convenient. SparrowQL is an alternative way to make your aggregation pipeline easier to read and maintain. The most significant profits are the less time spent on pipelining queries and a boost on performace.

Installation

npm install sparrowql

Usage

Here are a few easy steps to start your work with sparrowql.

If you want to create new queries with SparrowQL, you need a query build function

import { build } from "sparrowql";

How to build sparrowql query?

Basic example

Imagine you have a simple db model:
Simple graph db model

And a some fixtures for it:

const blogs = [{ _id: 0, ownerId: 3, topic: "Best blog!" }];
const posts = [
  { _id: 0, authorId: 0, blogId: 0, title: "Being fast for dummies" },
  { _id: 1, authorId: 0, blogId: 0, title: "Being declarative" },
  { _id: 2, authorId: 1, blogId: 0, title: "Amazing!" },
  { _id: 3, authorId: 2, blogId: 0, title: "A sparrow, really?" },
  { _id: 4, authorId: 1, blogId: 0, title: "Best!" },
  { _id: 5, authorId: 1, blogId: 0, title: "Superb!" }
];
const users = [
  { _id: 0, name: "SparrowQL", about: "Declarative aggregations" },
  { _id: 1, name: "Random #1", about: "Node.js developer" },
  { _id: 2, name: "Random #2", about: "Bird lover" },
  { _id: 3, name: "BlogOwner", about: "Owner of the blog" }
];

Now you want to create a query to get all the data you need e.g. Let's say you want to receive all the posts' titles written on blogs with blogs' topics. What do we need to make it work? To build a simple pipeline, you need a few arguments to the build function:

  • projection - pick the fields you need
const projection = {
  blogTopic: "Blogs.topic",
  postTitle: "Posts.title"
};
  • relations - define relations between collections
const relations = [
  { to: "Blogs", from: "Posts", foreign: "_id", local: "blogId" },
  { to: "Users", from: "Blogs", foreign: "_id", local: "ownerId" },
  { to: "Users", from: "Posts", foreign: "_id", local: "authorId" }
];
  • start - what is the main collection you want to start from
const start = "Posts";

Now you only need to build your new pipeline:

const pipeline = build({ projection, relations, start });
const results = await Posts.aggregate(pipeline).toArray();
// Results
[
  { blogTopic: "Best blog!", postTitle: "Being fast for dummies" },
  { blogTopic: "Best blog!", postTitle: "Being declarative" },
  { blogTopic: "Best blog!", postTitle: "Amazing!" },
  { blogTopic: "Best blog!", postTitle: "A sparrow, really?" }
];

Aliases - example

SparrowQL works correctly only on directed trees - in this case, you want to create a query which takes all the posts that were posted on someone's blog and the name of the blog owner. To make it work, you need to use aliases. Here is an example:

Simple db graph model with aliases

The only thing to do is to create aliases:

const aliases = {
  Authors: "Users",
  Owners: "Users"
};

And here is the rest of the query:

const projection = {
  ownerName: "Owners.name",
  postTitle: "Posts.title"
};
const start = "Posts";
const pipeline = build({ aliases, projection, relations, start });
const results = await Posts.aggregate(pipeline).toArray();
// Results
[
  { ownerName: "BlogOwner", postTitle: "Being fast for dummies" },
  { ownerName: "BlogOwner", postTitle: "Being declarative" },
  { ownerName: "BlogOwner", postTitle: "Amazing!" },
  { ownerName: "BlogOwner", postTitle: "A sparrow, really?" }
];

SparrowQL also may provide you with few other stages you might want to use:

  • sort - handle sort, which maps to $sort directly
  • query - handle query, which maps to $match directly*
  • limit - handle limit, which maps to $limit and $skip directly*

* They may result in more than one phase.

More complex example with other stages

Example
const limit = 1;
const projection = {
  blogOwnerName: "Owners.name",
  postAuthorName: "Authors.name",
  postTitle: "Posts.title"
};
const query = { "Authors.name": "Random #1" };
const skip = 1;
const sort = { "Posts.title": -1 };
const start = "Posts";
const pipeline = build({
  aliases,
  limit,
  projection,
  query,
  relations,
  skip,
  sort,
  start
});
const results = await Posts.aggregate(pipeline).toArray();
[
  {
    blogOwnerName: "BlogOwner",
    postAuthorName: "Random #1",
    postTitle: "Best!"
  }
];

If you want to see a more detailed description, please see this article or check all the examples to get familiar with SparrowQL

License

Like every package maintained by Vazco, sparrowql package is MIT licensed.

About

Declarative MongoDB aggregations.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks