{"id":23705704,"url":"https://github.com/pouchdb/gql","last_synced_at":"2025-09-03T11:30:51.534Z","repository":{"id":12810568,"uuid":"15485516","full_name":"pouchdb/GQL","owner":"pouchdb","description":"Google Query Language (GQL) interface for PouchDB","archived":false,"fork":false,"pushed_at":"2017-03-07T07:14:02.000Z","size":50,"stargazers_count":36,"open_issues_count":13,"forks_count":12,"subscribers_count":12,"default_branch":"master","last_synced_at":"2024-12-17T12:48:36.741Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://pouchdb.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pouchdb.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-12-28T02:10:01.000Z","updated_at":"2022-12-24T06:03:54.000Z","dependencies_parsed_at":"2022-08-26T22:23:59.744Z","dependency_job_id":null,"html_url":"https://github.com/pouchdb/GQL","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pouchdb%2FGQL","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pouchdb%2FGQL/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pouchdb%2FGQL/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pouchdb%2FGQL/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pouchdb","download_url":"https://codeload.github.com/pouchdb/GQL/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231874121,"owners_count":18439218,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-30T14:56:50.794Z","updated_at":"2024-12-30T14:56:51.350Z","avatar_url":"https://github.com/pouchdb.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GQL\n\nThe Google Query Language (GQL) interface provides an alternative method for accessing data.\nThe version of GQL implemented here is based on the Google Visualization API Query Language\n(https://developers.google.com/chart/interactive/docs/querylanguage).\nThe syntax of GQL queries should be familiar to those who have used SQL,\nbut the capabilities of GQL are much more limited.\n\nGQL queries are performed by passing a query object to the gql method along with a callback.\nCallbacks are in the node.js idiom of `function(err, data)` Where the first argument will be undefined\nunless there is an error, and further arguments specify the result.\nNote that only identifiers and string literals are case-sensitive.\n\n## Usage\n\nIn 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 });`\n\n### Language Syntax\n\n * [Select](#select)\n * [Where](#where)\n * [Group By](#groupBy)\n * [Pivot](#pivot)\n * [Label](#label)\n * [Functions](#functions)\n  * [Aggregation Functions](#aggregation_functions)\n  * [Scalar Functions](#scalar_functions)\n  * [Arithmetic Operators](#arithmetic_operators)\n * [Miscellaneous](#miscellaneous)\n  * [Literals](#literals)\n  * [Identifiers](#identifiers)\n  * [Reserved Words](#reserved_words)\n\n## Perform a Query\n\n    db.gql(query, [options], [callback])\n\nAlthough only the query is mandatory, the callback is required to access the query result.\nCurrently no query options are implemented.\n\n    var pouchdb;\n    PouchDB('idb://test', function(err, db) {\n       pouchdb = db;\n      // Use pouchdb to call further functions\n        db.gql({select: \"*\", where: \"type='Fire' and name is not null\"}, function(err, result){\n            if(!err){\n            // Use the results of the query here\n            }\n          }\n    })\n\n## Select\n\n    db.gql({select: \"`name!`, price-discount, upper(vendor)\"}, callback)\n\nSelect returns an object for each document in the database (unless limited by another clause).\nEach of these objects will be populated with the properties specified in the select clause.\nArithmetic operators, aggregation functions, and scalar functions are all fair game.\nProperties that are missing from an object in the database are assigned null.\n\nWith these documents in the database\n\n    {name!: \"pencil\", price: 2, discount: 0.7, vendor: \"store1\"},\n    {name!: \"pen\", price:3, discount: 2, vendor: \"store2\"}\n\nThe above query will return\n\n    {name!: \"pen\", price - discount: 1, upper(vendor): \"STORE2\"},\n    {name!: \"pencil\", price - discount: 1.3, upper(vendor): \"STORE1\"}\n\n\n## Where\n\n    db.gql({select: \"*\", where: \"type='Fire' and name is not null\"}, callback)\n\nWhere allows filtering of the objects that are passed to the select clause.  In this way, unwanted documents\ncan be excluded from the query result.  The where clause is composed of conditions which are joined by the\nlogical operators AND and OR.  An additional operator, NOT, provides negation.\n\nComparison operators can be used in conditions to perform comparisons.  The supported comparison operators are\n\u003c=, \u003c, \u003e, \u003e=, !=, and \u003c\u003e.  != and \u003c\u003e are equivalent.  Null is treated slightly differently; to check if\nsomething is null IS NULL is used.  To check if something is not null, IS NOT NULL is used.\n\nWith these documents in the database\n\n    {name: \"charmander\", type: \"Fire\"},\n    {type: \"Fire\", attack:\"tail whip\"},\n    {name: \"charizard\", type: \"Fire\", attack:\"slash\"}\n\nThe above query will return\n\n    {_id: \"0D715E2C-CEDD-46B4-A060-9C9C290BEBE8\", _rev: \"1-71d1e0f8ab00cf432306890a4116602b\",\n    attack: \"slash\", name: \"charizard\", type: \"Fire\"},\n    {_id: \"3153F94B-0568-4D4C-BFA1-83EDF6185915\" _rev: \"1-d24f7405c5a63943391eaff9a260139c\",\n    name: \"charmander\", type: \"Fire\"}\n\nNote the inclusion of the \\_rev and \\_id fields.  This is the result of using 'select \\*' instead of naming the\ndesired fields explicitly.\n\n## Group By\n\n    db.gql({select: \"max(charizard), charmeleon\", groupBy: \"charmeleon\"}, callback)\n\nGroup by creates one object for each unique combination of values in the group by clause. For the query above,\nif every document in the database had the value \"Level 22\" for the property \"charmeleon\", only a single\nobject would be generated.\n\nIf a group by clause is present, every identifier in the select clause must either be the argument of an\naggregation function or present in the group by clause.  Otherwise, the composite objects formed by the group by\nclause could have multiple values for some identifiers.\n\nWith these documents in the database\n\n    {charizard: 50, charmander: 24, charmeleon: 2, haunter:true},\n    {charizard: 40, charmeleon: 2, charmander: 50},\n    {charizard: 7, charmeleon: 20, charmander: 15}\n\nThe above query will return\n\n    {charmeleon: 2, max(charizard): 50}\n    {charmeleon: 20, max(charizard): 7}\n\n## Pivot\n\n     db.gql({select: \"max(charizard)\", pivot: \"charmeleon\"}, callback)\n\nPivot is essentially group by for properties.  Each distinct value in the pivot clause gets its own property.\nUnless used with group by, the result will have only a single document.\n\nThe same restriction for group by applies here; every identifier in the select clause must either be the\nargument of an aggregation function or preset in the group by clause.  Additionally, identifiers in the pivot\nclause may not be used in the group by clause.\n\nNote that using pivot will generate novel property names.  See below for an example.\n\nWith these documents in the database\n\n    {charizard: 50, charmeleon: \"hello\"},\n    {charizard: 40, charmeleon: \"hello\"},\n    {charizard: 7, charmeleon: \"world\", charmander: 15}\n\nThe above query will return\n\n    {'hello max(charizard)': 50, 'world max(charizard)': 7}\n\n## Label\n\n     db.gql({select: 'upper(dept), charizard',\n     label: \"upper(dept) 'Department', charizard 'Maximum Charizard!'\"}, callback)\n\nLabel is used to transform cryptic identifiers into something that can be displayed directly to the end user.\nItems in the label clause can be identifiers, aggregation functions, scalar functions, or operators.  The label\nclause is composed of any number of statement label pairs, where the statement corresponds to some statement in\nthe select clause and the label is a string literal.\n\nWith these documents in the database\n\n    {charizard: 50, dept: \"eng\", lunch:\"2\"},\n    {charizard: 40, lunch: \"1\", dept: \"market\"},·\n    {charizard: 99, dept: \"eng\", lunch: 1},\n    {charizard: 7, dept: \"eng\", lunch: 2}\n\nThe above query will return\n\n    {Department: \"ENG\", Maximum Charizard!: 7},\n    {Department: \"ENG\", Maximum Charizard!: 99},\n    {Department: \"MARKET\", Maximum Charizard!: 40},\n    {Department: \"ENG\", Maximum Charizard!: 50}\n\n## Functions\n\nGQL contains a number of operators and functions that can operate on retrived documents.\n\n### Aggregation Functions\n\n    db.gql({select: \"max(charizard), min(charizard), average(charizard), count(charizard), sum(charizard)\"},\n    callback)\n\nThe currently supported aggregation functions are avg, count, max, min, and sum.  Each of these takes a single\nstatement as an argument.  A statement can be composed of one or more identifiers joined by operators.\nAvg and sum expect their arguments to evaluate to numbers; the other aggregators will accept any type of input.\nAggregation functions operate on entire identifiers, returning only a single property. Aggregation functions\nmay only appear in the select and label clauses.\n\nWith these documents in the database\n\n    {charizard: 50},\n    {charizard: 40},\n    {charizard: 7}\n\nThe above query will return\n\n    {average(charizard): 32.333333333333336, count(charizard): 3, max(charizard): 50,\n    min(charizard): 7, sum(charizard): 97}\n\n### Scalar Functions\n\n    db.gql({select: \"`name!`, price-discount, upper(vendor)\"}, callback)\n\nCurrently only two scalar functions are supported, upper and lower.  These change the characters in their inputs\nto uppercase and lowercase respectively.  Unlike aggregator functions, scalar functions take only a single\nidentifier as their input.  Scalar functions may only appear in the select and label clauses.\n\nWith these documents in the database\n\n    {name!: \"pencil\", price: 2, discount: 0.7, vendor: \"store1\"},\n    {name!: \"pen\", price:3, discount: 2, vendor: \"store2\"}\n\nThe above query will return\n\n    {name!: \"pen\", price - discount: 1, upper(vendor): \"STORE2\"},\n    {name!: \"pencil\", price - discount: 1.3, upper(vendor): \"STORE1\"}\n\n\n### Arithmetic Operators\n\n    db.gql({select: \"*\", where: \"charizard \u003c=charmander * charmeleon + 2 and (charmander - 7 !=  24/3)\"},\n    callback)\n\nArithmetic operators are used to perform basic math on the values from documents.  Their arguments must be\nnumbers.  Arithmetic operators may only appear in the select, label, and where clauses.  The arguments are\nimplicitly upcast to floats if necessary. The supported arithmetic operators are:\n\n* Addition: '+'\n* Subtraction: '-'\n* Multiplication: '\\*'\n* Division: '/'\n\n\nWith these documents in the database\n\n    {charizard: 50, charmander: 24, charmeleon: 2, haunter:true},\n    {charizard: 40, charmeleon: .5, charmander: 50},\n    {charizard: 7, charmeleon: 20, charmander: 15}\n\nThe above query will return\n\n    {charizard: 50, charmander: 24, charmeleon: 2, haunter: true}\n\n## Miscellaneous\n\nSome features that are not covered in other sections.\n\n### Literals\n\nLiterals are used for comparison or arithmetic.  These are the supported literals:\n\n* string: Any characters surrounded by single or double quotes\n* number: Numbers in regular decimal form.  They may have a single period, a single negative sign, and no commas\n* boolean: Either true or false\n\n### Identifiers\n\nIdentifiers correspond to the properties of documents in the database.  There are strict rules governing the\nway that identifiers can be expressed in queries.  If your identifier has spaces, is a reserved word, contains\nany characters that are not letters or numbers or underscores, or starts with a digit, it must be surrounded\nby backquotes \\(\\`identifier\\`\\).\n\n### Reserved Words\n\nThis is the current list of reserved words.  Because the GQL implementation is currently under development,\nthis list is likely to grow over time.\n\n    and\n    asc\n    by\n    date\n    datetime\n    desc\n    false\n    format\n    group\n    label\n    limit\n    not\n    offset\n    options\n    or\n    order\n    pivot\n    select\n    timeofday\n    timestamp\n    true\n    where\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpouchdb%2Fgql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpouchdb%2Fgql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpouchdb%2Fgql/lists"}