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

pouchdb-gql

v1.0.0

Published

Google Query language plugin for pouchdb

Downloads

24

Readme

GQL

The Google Query Language (GQL) interface provides an alternative method for accessing data. The version of GQL implemented here is based on the Google Visualization API Query Language (https://developers.google.com/chart/interactive/docs/querylanguage). The syntax of GQL queries should be familiar to those who have used SQL, but the capabilities of GQL are much more limited.

GQL queries are performed by passing a query object to the gql method along with a callback. Callbacks are in the node.js idiom of function(err, data) Where the first argument will be undefined unless there is an error, and further arguments specify the result. Note that only identifiers and string literals are case-sensitive.

Usage

In the browser simply add pouchdb.gql.js in a script tag after the pouchdb script tag, otherwise in node or with AMD after getting GQL in scope (i.e. var GQL = require('GQL');) then you must register the plugin with PouchDB.plugin({ gql: GQL });

Language Syntax

Perform a Query

db.gql(query, [options], [callback])

Although only the query is mandatory, the callback is required to access the query result. Currently no query options are implemented.

var pouchdb;
PouchDB('idb://test', function(err, db) {
   pouchdb = db;
  // Use pouchdb to call further functions
    db.gql({select: "*", where: "type='Fire' and name is not null"}, function(err, result){
        if(!err){
        // Use the results of the query here
        }
      }
})

Select

db.gql({select: "`name!`, price-discount, upper(vendor)"}, callback)

Select returns an object for each document in the database (unless limited by another clause). Each of these objects will be populated with the properties specified in the select clause. Arithmetic operators, aggregation functions, and scalar functions are all fair game. Properties that are missing from an object in the database are assigned null.

With these documents in the database

{name!: "pencil", price: 2, discount: 0.7, vendor: "store1"},
{name!: "pen", price:3, discount: 2, vendor: "store2"}

The above query will return

{name!: "pen", price - discount: 1, upper(vendor): "STORE2"},
{name!: "pencil", price - discount: 1.3, upper(vendor): "STORE1"}

Where

db.gql({select: "*", where: "type='Fire' and name is not null"}, callback)

Where allows filtering of the objects that are passed to the select clause. In this way, unwanted documents can be excluded from the query result. The where clause is composed of conditions which are joined by the logical operators AND and OR. An additional operator, NOT, provides negation.

Comparison operators can be used in conditions to perform comparisons. The supported comparison operators are <=, <, >, >=, !=, and <>. != and <> are equivalent. Null is treated slightly differently; to check if something is null IS NULL is used. To check if something is not null, IS NOT NULL is used.

With these documents in the database

{name: "charmander", type: "Fire"},
{type: "Fire", attack:"tail whip"},
{name: "charizard", type: "Fire", attack:"slash"}

The above query will return

{_id: "0D715E2C-CEDD-46B4-A060-9C9C290BEBE8", _rev: "1-71d1e0f8ab00cf432306890a4116602b",
attack: "slash", name: "charizard", type: "Fire"},
{_id: "3153F94B-0568-4D4C-BFA1-83EDF6185915" _rev: "1-d24f7405c5a63943391eaff9a260139c",
name: "charmander", type: "Fire"}

Note the inclusion of the _rev and _id fields. This is the result of using 'select *' instead of naming the desired fields explicitly.

Group By

db.gql({select: "max(charizard), charmeleon", groupBy: "charmeleon"}, callback)

Group by creates one object for each unique combination of values in the group by clause. For the query above, if every document in the database had the value "Level 22" for the property "charmeleon", only a single object would be generated.

If a group by clause is present, every identifier in the select clause must either be the argument of an aggregation function or present in the group by clause. Otherwise, the composite objects formed by the group by clause could have multiple values for some identifiers.

With these documents in the database

{charizard: 50, charmander: 24, charmeleon: 2, haunter:true},
{charizard: 40, charmeleon: 2, charmander: 50},
{charizard: 7, charmeleon: 20, charmander: 15}

The above query will return

{charmeleon: 2, max(charizard): 50}
{charmeleon: 20, max(charizard): 7}

Pivot

 db.gql({select: "max(charizard)", pivot: "charmeleon"}, callback)

Pivot is essentially group by for properties. Each distinct value in the pivot clause gets its own property. Unless used with group by, the result will have only a single document.

The same restriction for group by applies here; every identifier in the select clause must either be the argument of an aggregation function or preset in the group by clause. Additionally, identifiers in the pivot clause may not be used in the group by clause.

Note that using pivot will generate novel property names. See below for an example.

With these documents in the database

{charizard: 50, charmeleon: "hello"},
{charizard: 40, charmeleon: "hello"},
{charizard: 7, charmeleon: "world", charmander: 15}

The above query will return

{'hello max(charizard)': 50, 'world max(charizard)': 7}

Label

 db.gql({select: 'upper(dept), charizard',
 label: "upper(dept) 'Department', charizard 'Maximum Charizard!'"}, callback)

Label is used to transform cryptic identifiers into something that can be displayed directly to the end user. Items in the label clause can be identifiers, aggregation functions, scalar functions, or operators. The label clause is composed of any number of statement label pairs, where the statement corresponds to some statement in the select clause and the label is a string literal.

With these documents in the database

{charizard: 50, dept: "eng", lunch:"2"},
{charizard: 40, lunch: "1", dept: "market"},·
{charizard: 99, dept: "eng", lunch: 1},
{charizard: 7, dept: "eng", lunch: 2}

The above query will return

{Department: "ENG", Maximum Charizard!: 7},
{Department: "ENG", Maximum Charizard!: 99},
{Department: "MARKET", Maximum Charizard!: 40},
{Department: "ENG", Maximum Charizard!: 50}

Functions

GQL contains a number of operators and functions that can operate on retrived documents.

Aggregation Functions

db.gql({select: "max(charizard), min(charizard), average(charizard), count(charizard), sum(charizard)"},
callback)

The currently supported aggregation functions are avg, count, max, min, and sum. Each of these takes a single statement as an argument. A statement can be composed of one or more identifiers joined by operators. Avg and sum expect their arguments to evaluate to numbers; the other aggregators will accept any type of input. Aggregation functions operate on entire identifiers, returning only a single property. Aggregation functions may only appear in the select and label clauses.

With these documents in the database

{charizard: 50},
{charizard: 40},
{charizard: 7}

The above query will return

{average(charizard): 32.333333333333336, count(charizard): 3, max(charizard): 50,
min(charizard): 7, sum(charizard): 97}

Scalar Functions

db.gql({select: "`name!`, price-discount, upper(vendor)"}, callback)

Currently only two scalar functions are supported, upper and lower. These change the characters in their inputs to uppercase and lowercase respectively. Unlike aggregator functions, scalar functions take only a single identifier as their input. Scalar functions may only appear in the select and label clauses.

With these documents in the database

{name!: "pencil", price: 2, discount: 0.7, vendor: "store1"},
{name!: "pen", price:3, discount: 2, vendor: "store2"}

The above query will return

{name!: "pen", price - discount: 1, upper(vendor): "STORE2"},
{name!: "pencil", price - discount: 1.3, upper(vendor): "STORE1"}

Arithmetic Operators

db.gql({select: "*", where: "charizard <=charmander * charmeleon + 2 and (charmander - 7 !=  24/3)"},
callback)

Arithmetic operators are used to perform basic math on the values from documents. Their arguments must be numbers. Arithmetic operators may only appear in the select, label, and where clauses. The arguments are implicitly upcast to floats if necessary. The supported arithmetic operators are:

  • Addition: '+'
  • Subtraction: '-'
  • Multiplication: '*'
  • Division: '/'

With these documents in the database

{charizard: 50, charmander: 24, charmeleon: 2, haunter:true},
{charizard: 40, charmeleon: .5, charmander: 50},
{charizard: 7, charmeleon: 20, charmander: 15}

The above query will return

{charizard: 50, charmander: 24, charmeleon: 2, haunter: true}

Miscellaneous

Some features that are not covered in other sections.

Literals

Literals are used for comparison or arithmetic. These are the supported literals:

  • string: Any characters surrounded by single or double quotes
  • number: Numbers in regular decimal form. They may have a single period, a single negative sign, and no commas
  • boolean: Either true or false

Identifiers

Identifiers correspond to the properties of documents in the database. There are strict rules governing the way that identifiers can be expressed in queries. If your identifier has spaces, is a reserved word, contains any characters that are not letters or numbers or underscores, or starts with a digit, it must be surrounded by backquotes (`identifier`).

Reserved Words

This is the current list of reserved words. Because the GQL implementation is currently under development, this list is likely to grow over time.

and
asc
by
date
datetime
desc
false
format
group
label
limit
not
offset
options
or
order
pivot
select
timeofday
timestamp
true
where