{"id":735024,"url":"https://beautifulinteractions.github.io/node-quadstore","last_synced_at":"2025-08-26T13:31:16.008Z","repository":{"id":41079606,"uuid":"84123508","full_name":"quadstorejs/quadstore","owner":"quadstorejs","description":"A LevelDB-backed graph database for JS runtimes (Node.js, Deno, browsers, ...) supporting SPARQL queries and the RDF/JS interface.","archived":false,"fork":false,"pushed_at":"2024-12-02T08:24:24.000Z","size":2850,"stargazers_count":206,"open_issues_count":2,"forks_count":14,"subscribers_count":15,"default_branch":"master","last_synced_at":"2024-12-22T09:42:54.669Z","etag":null,"topics":["database","deno","graph","graph-database","linked-data","nodejs","quadstore","rdf","rdfjs","sparql","triplestore"],"latest_commit_sha":null,"homepage":"https://github.com/quadstorejs/quadstore","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quadstorejs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-06T21:38:56.000Z","updated_at":"2024-12-02T08:24:28.000Z","dependencies_parsed_at":"2024-01-06T13:11:19.446Z","dependency_job_id":"2f0e7ca0-5c5a-4ebc-a3f4-dd4750059a4e","html_url":"https://github.com/quadstorejs/quadstore","commit_stats":null,"previous_names":["jacoscaz/quadstore","belayeng/quadstore","beautifulinteractions/node-quadstore","quadstorejs/quadstore"],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quadstorejs%2Fquadstore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quadstorejs%2Fquadstore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quadstorejs%2Fquadstore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quadstorejs%2Fquadstore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quadstorejs","download_url":"https://codeload.github.com/quadstorejs/quadstore/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231040728,"owners_count":18318980,"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":["database","deno","graph","graph-database","linked-data","nodejs","quadstore","rdf","rdfjs","sparql","triplestore"],"created_at":"2024-01-11T18:16:57.220Z","updated_at":"2024-12-24T02:31:05.499Z","avatar_url":"https://github.com/quadstorejs.png","language":"JavaScript","readme":"\n![Logo](https://github.com/quadstorejs/quadstore/blob/master/logo.png?raw=true)\n\n# QUADSTORE\n\nQuadstore is a LevelDB-backed RDF graph database / triplestore for JavaScript\nruntimes (browsers, Node.js, Deno, Bun, ...) written in TypeScript.\n\n- Implements the `Sink`, `Source` and `Store` [RDF/JS interfaces][z0]\n  for maximum interoperability with other RDF libraries\n- Supports SPARQL queries via [quadstore-comunica][z2], a tailored\n  configuration and distribution of the [Comunica querying framework][z1]\n- Natively capable of querying across named graphs\n\n[z0]: https://rdf.js.org\n[z1]: https://comunica.dev\n[z2]: https://www.npmjs.com/package/quadstore-comunica\n\n## Table of contents\n\n- [QUADSTORE](#quadstore)\n  - [Table of contents](#table-of-contents)\n  - [Example of basic usage](#example-of-basic-usage)\n  - [Status](#status)\n    - [Changelog](#changelog)\n    - [Roadmap](#roadmap)\n    - [Notes](#notes)\n  - [Usage](#usage)\n    - [Parsing and serializing RDF](#parsing-and-serializing-rdf)\n    - [Storage backends](#storage-backends)\n    - [Data model and return values](#data-model-and-return-values)\n    - [Quadstore class](#quadstore-class)\n        - [opts.backend](#optsbackend)\n        - [opts.dataFactory](#optsdatafactory)\n        - [opts.indexes](#optsindexes)\n        - [opts.prefixes](#optsprefixes)\n    - [Access to the backend](#access-to-the-backend)\n    - [Quadstore.prototype.open()](#quadstoreprototypeopen)\n    - [Quadstore.prototype.close()](#quadstoreprototypeclose)\n    - [Quadstore.prototype.get()](#quadstoreprototypeget)\n    - [Range matching](#range-matching)\n    - [Quadstore.prototype.put()](#quadstoreprototypeput)\n    - [Quadstore.prototype.multiPut()](#quadstoreprototypemultiput)\n    - [Quadstore.prototype.del()](#quadstoreprototypedel)\n    - [Quadstore.prototype.multiDel()](#quadstoreprototypemultidel)\n    - [Quadstore.prototype.patch()](#quadstoreprototypepatch)\n    - [Quadstore.prototype.multiPatch()](#quadstoreprototypemultipatch)\n    - [Quadstore.prototype.getStream()](#quadstoreprototypegetstream)\n    - [Quadstore.prototype.putStream()](#quadstoreprototypeputstream)\n    - [Quadstore.prototype.delStream()](#quadstoreprototypedelstream)\n    - [Quadstore.prototype.match()](#quadstoreprototypematch)\n    - [Quadstore.prototype.import()](#quadstoreprototypeimport)\n    - [Quadstore.prototype.remove()](#quadstoreprototyperemove)\n    - [Quadstore.prototype.removeMatches()](#quadstoreprototyperemovematches)\n  - [Blank nodes and quad scoping](#blank-nodes-and-quad-scoping)\n    - [Quadstore.prototype.initScope()](#quadstoreprototypeinitscope)\n    - [Quadstore.prototype.loadScope()](#quadstoreprototypeloadscope)\n    - [Quadstore.prototype.deleteScope()](#quadstoreprototypedeletescope)\n    - [Quadstore.prototype.deleteAllScopes()](#quadstoreprototypedeleteallscopes)\n  - [SPARQL](#sparql)\n  - [Browser usage](#browser-usage)\n  - [Deno usage](#deno-usage)\n  - [Performance](#performance)\n  - [LICENSE](#license)\n\n## Example of basic usage\n\n```typescript\nimport { MemoryLevel } from 'memory-level';\nimport { DataFactory } from 'rdf-data-factory';\nimport { Quadstore } from 'quadstore';\nimport { Engine } from 'quadstore-comunica';\n\n// Any implementation of AbstractLevel can be used.\nconst backend = new MemoryLevel();\n\n// Implementation of the RDF/JS DataFactory interface\nconst df = new DataFactory();           \n\n// Store and query engine are separate modules\nconst store = new Quadstore({backend, dataFactory: df});\nconst engine = new Engine(store);\n\n// Open the store\nawait store.open();\n\n// Put a single quad into the store using Quadstore's API\nawait store.put(df.quad(                      \n  df.namedNode('http://example.com/subject'),\n  df.namedNode('http://example.com/predicate'),\n  df.namedNode('http://example.com/object'),\n  df.defaultGraph(),\n));\n\n// Retrieves all quads using Quadstore's API  \nconst { items } = await store.get({});\n\n// Retrieves all quads using RDF/JS Stream interfaces\nconst quadsStream = store.match(undefined, undefined, undefined, undefined);\nquadsStream.on('data', quad =\u003e console.log(quad));\n\n// Queries the store via RDF/JS Query interfaces\nconst bindingsStream = await engine.queryBindings('SELECT * {?s ?p ?o}');\nbindingsStream.on('data', binding =\u003e console.log(binding));\n```\n\n## Status\n\nActive, under development.\n\n### Changelog\n\nSee [CHANGELOG.md](./CHANGELOG.md).\n\n### Roadmap\n\nWe're currently working on the following features:\n\n- optimizing SPARQL performance by pushing filters down from the engine\n  to the persistence layer\n\nWe're also evaluating the following features for future developments:\n\n- [RDF*][r1] (see also [these slides][r2])\n\n[r1]: https://blog.liu.se/olafhartig/2019/01/10/position-statement-rdf-star-and-sparql-star/\n[r2]: http://olafhartig.de/slides/W3CWorkshop2019RDFStarAndSPARQLStar.pdf\n\n### Notes\n\n- uses [Semantic Versioning](https://semver.org), pre-releases are tagged\n  accordingly;\n- requires Node.js \u003e= 18.0.0.\n\n## Usage\n\n### Parsing and serializing RDF\n\n`quadstore` is compatible with all parsers and serializers implementing the\nrelevant [RDF/JS interfaces][r0], such as [n3][r1] and [@rdfjs/formats][r2].\nSee [https://rdf.js.org][r0] for an open list of such libraries.\n\nFor example, here is how to use [n3][r1] in order to parse a [Turtle][r3] file\ninto an instance of `Quadstore` in a streaming fashion, with full backpressure\nhandling, using `classic-level` as the backend:\n\n```typescript\nimport { Quadstore } from 'quadstore';\nimport { ClassicLevel } from 'classic-level';\nimport { DataFactory, StreamParser } from 'n3';\nconst store = new Quadstore({\n  backend: new ClassicLevel('/path/to/db'),\n  dataFactory: DataFactory,\n});\nawait store.open();\nconst reader = fs.createReadStream('/path/to/file.ttl');\nconst parser = new StreamParser({ format: 'text/turtle' });\nawait store.putStream(reader.pipe(parser), { batchSize: 100 });\nawait store.close();\n```\n\n`quadstore` does not include any RDF parsing and/or serialization capability\nby choice as no subset of formats would meet the requirements of every use \ncase and shipping support for all mainstream RDF formats would result in \nexceedingly high bundle sizes.\n\n[r0]: https://rdf.js.org\n[r1]: https://www.npmjs.com/package/n3\n[r2]: https://www.npmjs.com/package/@rdfjs/formats\n[r3]: https://www.w3.org/TR/turtle/ \n\n### Storage backends\n\n`quadstore` can work with any storage backend that implements the \n[`AbstractLevel` interface][db1]. An incomplete list of available backends\nis available at [level/awesome#stores][db6].\n\nOur test suite focuses on the following backends:\n\n- [`classic-level`][db2] for persistent, on-disk storage using [LevelDB][db0]\n- [`memory-level`][db3] for volatile in-memory storage using red-black trees\n- [`browser-level`][db9] for browser-side persistent storage using\n  [IndexedDB][db10]. For more information about browser-side usage, see the\n  [Browser usage section](#browser-usage)\n\n[db0]: http://leveldb.org\n[db1]: https://github.com/level/abstract-level\n[db2]: https://github.com/level/classic-level\n[db3]: https://github.com/level/memory-level\n[db4]: https://github.com/level/rocksdb\n[db5]: https://rocksdb.org\n[db6]: https://github.com/level/awesome#storage\n[db7]: https://github.com/nxtedition/rocks-level\n[db8]: https://github.com/level\n[db9]: https://github.com/Level/browser-level\n[db10]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API\n[db11]: https://github.com/quadstorejs/quadstore/issues/168\n\n### Data model and return values\n\nExcept for those related to the [RDF/JS stream interfaces][dm-2], `quadstore`'s\nAPI is promise-based and all methods return objects that include both the actual\nquery results and the relevant metadata.\n\nObjects returned by `quadstore`'s APIs have the `type` property set to one of\nthe following values:\n\n- `\"VOID\"` - when there's no data returned by the database, such as with the\n  `put` method;\n- `\"QUADS\"` - when a query returns a collection of quads;\n- `\"APPROXIMATE_SIZE\"` - when a query returns an approximate count of how many\n  matching items are present.\n\nFor those methods that return objects with the `type` property set to\n`\"QUADS\"`, `quadstore` provides query results either in streaming mode or in\nnon-streaming mode. \n  \nStreaming methods such as `getStream` return objects with the `iterator`\nproperty set to an instance of [`AsyncIterator`][dm-4], an implementation of a\nsubset of the `stream.Readable` interface.\n\nNon-streaming methods such as `get` return objects with the `items` property\nset to an array of quads.\n\nQuads are returned as and expected to be instances of the\n [RDF/JS `Quad` interface][dm-1] as produced by the implementation of the \n [RDF/JS `DataFactory` interface][dm-1] passed to the `Quadstore` constructor.\n\nMatching patterns, such as those used in the `get` and `getStream` methods, \nare expected to be maps of term names to instances of the\n[RDF/JS Term interface][dm-1].\n\n[dm-1]: https://rdf.js.org/data-model-spec/\n[dm-2]: https://rdf.js.org/stream-spec/\n[dm-3]: https://github.com/rdfjs-base/data-model\n[dm-4]: https://github.com/RubenVerborgh/AsyncIterator#readme\n\n### Quadstore class\n\n```js\nconst Quadstore = require('quadstore').Quadstore;\nconst store = new Quadstore(opts);\n```\n\nInstantiates a new store. Supported properties for the `opts` argument \nare:\n\n##### opts.backend\n\nThe `opts.backend` option **must** be an instance of a leveldb backend.\nSee [storage backends](#storage-backends).\n\n##### opts.dataFactory\n\nThe `dataFactory` option *must* be an implementation of the \n[RDF/JS DataFactory interface][dm-1]. Some of the available\nimplementations: \n\n- [rdf-data-factory](https://www.npmjs.com/package/rdf-data-factory)\n- [@rdfjs/data-model](https://www.npmjs.com/package/@rdfjs/data-model)\n- [N3.DataFactory](https://www.npmjs.com/package/n3)\n\n##### opts.indexes\n\nThe `opts.indexes` option allows users to configure which indexes will be used\nby the store. If not set, the store will default to the following indexes:\n\n```js\n[\n  ['subject', 'predicate', 'object', 'graph'],\n  ['object', 'graph', 'subject', 'predicate'],\n  ['graph', 'subject', 'predicate', 'object'],\n  ['object', 'subject', 'predicate', 'graph'],\n  ['predicate', 'object', 'graph', 'subject'],\n  ['graph', 'predicate', 'object', 'subject'],\n]; \n```\n\nThis option, if present, **must** be set to an array of term arrays, each of \nwhich **must** represent one of the 24 possible permutations of the four terms \n`subject`, `predicate`, `object` and `graph`. Partial indexes are not \nsupported.\n\nThe store will automatically select which index(es) to use for a given query \nbased on the available indexes and the query itself. **If no suitable index is\nfound for a given query, the store will throw an error**.\n\n##### opts.prefixes\n\nAlso, `Quadstore` can be configured with a `prefixes` object that defines a\nreversible mapping of IRIs to abbreviated forms, with the intention of reducing\nthe storage cost where common HTTP prefixes are known in advance.\n\nThe `prefixes` object defines a bijection using two functions `expandTerm` and\n`compactIri`, both of which take a string parameter and return a string, as in\nthe following example:\n\n```js\nopts.prefixes = {\n  expandTerm: term =\u003e term.replace(/^ex:/, 'http://example.com/'),\n  compactIri: iri =\u003e iri.replace(/^http:\\/\\/example\\.com\\//, 'ex:'),\n}\n```\n\nThis will replace the IRI `http://example.com/a` with `ex:a` in storage.\n\n### Access to the backend\n\nThe backend of a `quadstore` can be accessed with the `db` property, to perform\nadditional storage operations independently of quads.\n\nIn order to perform write operations atomically with quad storage, the `put`,\n`multiPut`, `del`, `multiDel`, `patch` and `multiPatch` methods accept a\n`preWrite` option which defines a procedure to augment the batch, as in the\nfollowing example:\n\n```js\nawait store.put(dataFactory.quad(/* ... */), {\n  preWrite: batch =\u003e batch.put('my.key', Buffer.from('my.value'))\n});\n```\n\n### Quadstore.prototype.open()\n\nThis method opens the store and throws if the open operation fails for any reason.\n\n### Quadstore.prototype.close()\n\nThis method closes the store and throws if the open operation fails for any reason.\n\n### Quadstore.prototype.get()\n\n```js\nconst pattern = {graph: dataFactory.namedNode('ex://g')};\nconst { items } = await store.get(pattern);\n```\n\nReturns an array of all quads within the store matching the specified terms.\n\nThis method also accepts an optional `opts` parameter with the following \noptional properties:\n\n- `opts.order`: array of term names (e.g. `['object']`) that represents the\n  desired ordering criteria of returned quads. Equivalent to the `ORDER BY`\n  clause in `SQL`.\n- `opts.reverse`: boolean value that indicates whether to return quads in \n  ascending or descending order. Equivalent to `ASC` / `DESC` modifiers in\n  `SQL`.\n- `opts.limit`: limit the number of returned quads to the specified value.\n  Equivalent to `LIMIT` clause in `SQL`.\n\n### Range matching\n\n`quadstore` supports range-based matching in addition to value-based matching. \nRanges can be defined using the `gt`, `gte`, `lt`, `lte` properties: \n\n```js\nconst pattern = {\n  object: {\n    termType: 'Range',\n    gt: dataFactory.literal('7', 'http://www.w3.org/2001/XMLSchema#integer')\n  }\n};\nconst { items } = await store.get(matchTerms);\n```\n    \nValues for literal terms with the following numeric datatypes are matched\nagainst their numerical values rather than their literal representations:\n\n```\nhttp://www.w3.org/2001/XMLSchema#integer\nhttp://www.w3.org/2001/XMLSchema#decimal\nhttp://www.w3.org/2001/XMLSchema#double\nhttp://www.w3.org/2001/XMLSchema#nonPositiveInteger\nhttp://www.w3.org/2001/XMLSchema#negativeInteger\nhttp://www.w3.org/2001/XMLSchema#long\nhttp://www.w3.org/2001/XMLSchema#int\nhttp://www.w3.org/2001/XMLSchema#short\nhttp://www.w3.org/2001/XMLSchema#byte\nhttp://www.w3.org/2001/XMLSchema#nonNegativeInteger\nhttp://www.w3.org/2001/XMLSchema#unsignedLong\nhttp://www.w3.org/2001/XMLSchema#unsignedInt\nhttp://www.w3.org/2001/XMLSchema#unsignedShort\nhttp://www.w3.org/2001/XMLSchema#unsignedByte\nhttp://www.w3.org/2001/XMLSchema#positiveInteger\n```\n\nThis is also the case for terms with the following date/time datatypes:\n\n```\nhttp://www.w3.org/2001/XMLSchema#dateTime\n```\n\n### Quadstore.prototype.put()\n\n```js\nawait store.put(dataFactory.quad(/* ... */));\n```\n\nStores a new quad. Does *not* throw or return an error if the quad already exists.\n\nThis method also accepts an optional `opts` parameter with the following\nproperties:\n\n- `opts.preWrite`: this can be set to a function which accepts a\n  [chainedBatch](https://github.com/Level/abstract-leveldown#chainedbatch) and\n  performs additional backend operations atomically with the `put` operation.\n  See [Access to the backend](#access-to-the-backend) for more information.\n- `opts.scope`: this can be set to a `Scope` instance as returned by\n  [`initScope()`](#quadstoreprototypeinitscope) and \n  [`loadScope()`](#quadstoreprototypeloadscope). If set, blank node labels will\n  be changed to prevent blank node collisions. See \n  [Blank nodes and quad scoping](#blank-nodes-and-quad-scoping).\n\n### Quadstore.prototype.multiPut()\n\n```js\nawait store.multiPut([\n  dataFactory.quad(/* ... */),\n  dataFactory.quad(/* ... */),\n]);\n```\n\nStores new quads. Does *not* throw or return an error if quads already exists.\n\nThis method also accepts an optional `opts` parameter with the following\nproperties:\n\n- `opts.preWrite`: this can be set to a function which accepts a\n  [chainedBatch](https://github.com/Level/abstract-leveldown#chainedbatch) and\n  performs additional backend operations atomically with the `put` operation.\n  See [Access to the backend](#access-to-the-backend) for more information.\n- `opts.scope`: this can be set to a `Scope` instance as returned by\n  [`initScope()`](#quadstoreprototypeinitscope) and\n  [`loadScope()`](#quadstoreprototypeloadscope). If set, blank node labels will\n  be changed to prevent blank node collisions. See\n  [Blank nodes and quad scoping](#blank-nodes-and-quad-scoping).\n\n### Quadstore.prototype.del()\n\nThis method deletes a single quad. It Does *not* throw or return an error if the \nspecified quad is not present in the store.\n\n```js\nawait store.del(dataFactory.quad(/* ... */));\n```\n\nThis method also accepts an optional `opts` parameter with the following\nproperties:\n\n- `opts.preWrite`: this can be set to a function which accepts a\n  [chainedBatch](https://github.com/Level/abstract-leveldown#chainedbatch) and\n  performs additional backend operations atomically with the `put` operation.\n  See [Access to the backend](#access-to-the-backend) for more information.\n\n### Quadstore.prototype.multiDel()\n\nThis method deletes multiple quads. It Does *not* throw or return an error if\nthe specified quads are not present in the store.\n\n```js\nawait store.multiDel([\n  dataFactory.quad(/* ... */),\n  dataFactory.quad(/* ... */),\n]);\n```\n\nThis method also accepts an optional `opts` parameter with the following\nproperties:\n\n- `opts.preWrite`: this can be set to a function which accepts a\n  [chainedBatch](https://github.com/Level/abstract-leveldown#chainedbatch) and\n  performs additional backend operations atomically with the `put` operation.\n  See [Access to the backend](#access-to-the-backend) for more information.\n\n### Quadstore.prototype.patch()\n\nThis method deletes one quad and inserts another quad in a single operation.\nIt Does *not* throw or return an error if the specified quads are not present\nin the store (delete) or already present in the store (update).\n\n```js\nawait store.patch(\n  dataFactory.quad(/* ... */),  // will be deleted\n  dataFactory.quad(/* ... */),  // will be inserted\n);\n```\n\nThis method also accepts an optional `opts` parameter with the following\nproperties:\n\n- `opts.preWrite`: this can be set to a function which accepts a\n  [chainedBatch](https://github.com/Level/abstract-leveldown#chainedbatch) and\n  performs additional backend operations atomically with the `put` operation.\n  See [Access to the backend](#access-to-the-backend) for more information.\n\n### Quadstore.prototype.multiPatch()\n\nThis method deletes and inserts quads in a single operation. It Does *not* \nthrow or return an error if the specified quads are not present in the store \n(delete) or already present in the store (update).\n\n```js\n// will be deleted\nconst oldQuads = [ \n    dataFactory.quad(/* ... */),\n    dataFactory.quad(/* ... */),\n];\n\n// will be inserted\nconst newQuads = [ // will be inserted\n    dataFactory.quad(/* ... */),\n    dataFactory.quad(/* ... */),\n    dataFactory.quad(/* ... */),        \n];\n\nawait store.multiPatch(oldQuads, newQuads);\n```\n\nThis method also accepts an optional `opts` parameter with the following\nproperties:\n\n- `opts.preWrite`: this can be set to a function which accepts a\n  [chainedBatch](https://github.com/Level/abstract-leveldown#chainedbatch) and\n  performs additional backend operations atomically with the `put` operation.\n  See [Access to the backend](#access-to-the-backend) for more information.\n\n### Quadstore.prototype.getStream()\n\n```js\nconst pattern = {graph: dataFactory.namedNode('ex://g')};\nconst { iterator } = await store.getStream(pattern);\n```\n\nJust as [QuadStore.prototype.get()](#quadstoreprototypeget), this method\nsupports [range matching](#range-matching) and the `order`, `reverse` and \n`limit` options. \n\n### Quadstore.prototype.putStream()\n\n```js\nawait store.putStream(readableStream);\n```\n\nImports all quads coming through the specified `stream.Readable` into the store.\n\nThis method also accepts an optional `opts` parameter with the following\nproperties:\n\n- `opts.scope`: this can be set to a `Scope` instance as returned by\n  [`initScope()`](#quadstoreprototypeinitscope) and\n  [`loadScope()`](#quadstoreprototypeloadscope). If set, blank node labels will\n  be changed to prevent blank node collisions. See\n  [Blank nodes and quad scoping](#blank-nodes-and-quad-scoping).\n\n### Quadstore.prototype.delStream()\n\n```js\nawait store.delStream(readableStream);\n```\n\nDeletes all quads coming through the specified `stream.Readable` from the store.\n\n### Quadstore.prototype.match()\n\n    const subject = dataFactory.namedNode('http://example.com/subject');\n    const graph = dataFactory.namedNode('http://example.com/graph');\n    store.match(subject, null, null, graph)\n      .on('error', (err) =\u003e {})\n      .on('data', (quad) =\u003e {\n        // Quad is produced using dataFactory.quad()\n      })\n      .on('end', () =\u003e {});\n\nImplementation of the [RDF/JS Source#match method][dm-2]. Supports \n[range-based matching](#range-matching).\n\n### Quadstore.prototype.import()\n\n    const readableStream; // A stream.Readable of Quad() instances\n    store.import(readableStream)\n      .on('error', (err) =\u003e {})\n      .on('end', () =\u003e {});\n\nImplementation of the [RDF/JS Sink#import method][dm-2].\n\n### Quadstore.prototype.remove()\n\n    const readableStream; // A stream.Readable of Quad() instances\n    store.remove(readableStream)\n      .on('error', (err) =\u003e {})\n      .on('end', () =\u003e {});\n\nImplementation of the [RDF/JS Store#remove method][dm-2].\n\n### Quadstore.prototype.removeMatches()\n\n    const subject = dataFactory.namedNode('http://example.com/subject');\n    const graph = dataFactory.namedNode('http://example.com/graph');\n    store.removeMatches(subject, null, null, graph)\n      .on('error', (err) =\u003e {})\n      .on('end', () =\u003e {});\n\nImplementation of the [RDF/JS Sink#removeMatches method][dm-2].\n\n## Blank nodes and quad scoping\n\nBlank nodes are defined as _existential_ variables in that they merely indicate\nthe existence of an entity rather than act as references to the entity itself.\n\nWhile the semantics of blank nodes [can][bnode-disc-1] [be][bnode-disc-2]\n[rather][bnode-disc-3] [confusing][bnode-disc-4], one of the most practical \nconsequences of their definition is that two blank nodes having the same label\nmay not refer to the same entity unless both nodes come from the same logical\nset of quads.\n\nAs an example, here's two JSON-LD documents converted to N-Quads using the  \n[JSON-LD playground][jsonld-plg]:\n\n```json\n{\n  \"@id\": \"http://example.com/bob\",\n  \"foaf:knows\": {\n    \"foaf:name\": \"Alice\"\n  }\n}\n```\n\n```\n\u003chttp://example.com/bob\u003e \u003cfoaf:knows\u003e _:b0 .\n_:b0 \u003cfoaf:name\u003e \"Alice\" .\n```\n\n```json\n{\n  \"@id\": \"http://example.com/alice\",\n  \"foaf:knows\": {\n    \"foaf:name\": \"Bob\"\n  }\n}\n```\n\n```\n\u003chttp://example.com/alice\u003e \u003cfoaf:knows\u003e _:b0 .\n_:b0 \u003cfoaf:name\u003e \"Bob\" .\n```\n\nThe N-Quads equivalent for both of these documents contains a blank node with\nthe `b0` label. However, although the label is the same, these blank nodes\nindicate the existence of two different entities. Intuitively, we can say that\na blank node is scoped to the logical grouping of quads that contains it, be it\na single quad, a document or a stream.\n\nAs quadstore treats all write operations as if they were happening within the \nsame scope, importing these two sets of quads would result in a collision of \ntwo unrelated blank nodes, leading to a corrupted dataset. \n\nA good way to address these issues is to skolemize [skolemize][skolem-def] all \nblank nodes into IRIs / named nodes. However, this is not always possible and\n/ or practical.\n\nThe [`initScope()`](#quadstoreprototypeinitscope) method returns a `Scope`\ninstance which can be passed to the `put`, `multiPut` and `putStream` methods. \nWhen doing so, quadstore will replace each occurrence of a given blank node \nwith a different blank node having a randomly-generated label, preventing blank\nnode collisions.\n\nEach `Scope` instance keeps an internal cache of mappings between previously\nencountered blank nodes and their replacements, so that it is able to always \nreturn the same replacement blank node for a given label. Each new mapping is\natomically persisted to the store together with its originating quad, leading\neach scope to be incrementally persisted to the store consistently with each \nsuccessful `put` and `multiPut` operation. This allows scopes to be re-used\neven across process restarts via the \n[`loadScope()`](#quadstoreprototypeloadscope) method.\n\n[jsonld-plg]: https://json-ld.org/playground/\n[bnode-disc-1]: https://lists.w3.org/Archives/Public/semantic-web/2020Jun/0077.html\n[bnode-disc-2]: https://github.com/w3c/EasierRDF/issues/19\n[bnode-disc-3]: https://www.w3.org/2011/rdf-wg/wiki/User:Azimmerm/Blank-node-scope\n[bnode-disc-4]: https://www.w3.org/2011/rdf-wg/wiki/User:Azimmerm/Blank-node-scope-again\n[skolem-def]: https://www.w3.org/2011/rdf-wg/wiki/Skolemisation\n\n### Quadstore.prototype.initScope()\n\nInitializes a new, empty scope.\n\n```js\nconst scope = await store.initScope();\nawait store.put(quad, { scope });\nawait store.multiPut(quads, { scope });\nawait store.putStream(stream, { scope });\n```\n\n### Quadstore.prototype.loadScope()\n\nEach `Scope` instance has an `.id` property that acts as its unique identifier.\nThe `loadScope()` method can be used to re-hydrate a scope through its `.id`: \n\n```js\nconst scope = await store.initScope();\n/* store scope.id somewhere */\n```\n\n```js\n/* read the previously-stored scope.id */\nconst scope = await store.loadScope(scopeId);\n```\n\n### Quadstore.prototype.deleteScope()\n\nDeletes all mappings of a given scope from the store.\n\n```js\nconst scope = await store.initScope();\n/* ... */\nawait store.deleteScope(scope.id);\n```\n\n### Quadstore.prototype.deleteAllScopes()\n\nDeletes all mappings of all scopes from the store.\n\n```js\nawait store.deleteAllScopes();\n```\n\n## SPARQL\n\nSPARQL queries can be executed against a `Quadstore` instance using any query\nengine capable of querying across RDF/JS data sources.\n\nAn example of one such engine is [quadstore-comunica][c2], an engine built as\na custom distribution and configuration of [Comunica][c1] that implements the\n[RDF/JS Query spec][c4].:\n\n\u003e Comunica is a knowledge graph querying framework. [...] Comunica is a meta\n\u003e query engine using which query engines can be created. It does this by\n\u003e providing a set of modules that can be wired together in a flexible manner.\n\u003e [...] Its primary goal is executing SPARQL queries over one or more\n\u003e interfaces.\n\nIn time, [quadstore-comunica][c2] will be extended with custom query modules\nthat will optimize query performance by pushing some matching and ordering\noperations down to quadstore itself. \n\n```typescript\nimport { MemoryLevel } from 'memory-level';\nimport { DataFactory } from 'rdf-data-factory';\nimport { Quadstore } from 'quadstore';\nimport { Engine } from 'quadstore-comunica';\n\nconst backend = new MemoryLevel();\nconst df = new DataFactory();\nconst store = new Quadstore({backend, dataFactory: df});\nconst engine = new Engine(store);\n\nawait store.open();\n\nconst bindingsStream = await engine.queryBindings('SELECT * {?s ?p ?o}');\n```\n\nMore information on [quadstore-comunica][c2]'s repository.\n\n[c1]: https://github.com/comunica/comunica\n[c2]: https://github.com/quadstorejs/quadstore-comunica\n[c3]: https://github.com/comunica/comunica/graphs/contributors\n[c4]: https://rdf.js.org/query-spec/\n\n## Browser usage\n\nThe [`browser-level`][b1] backend for levelDB offers support for browser-side\npersistent storage via [IndexedDB][b2]. \n\n`quadstore` can be bundled for browser-side usage via Webpack, preferably using\nversion 5.x. The reference [quadstore-browser][b0] is meant to help in getting \nto a working Webpack configuration and also hosts a pre-built bundle with everything\nthat is required to use `quadstore` in browsers.\n \n[b0]: https://github.com/quadstorejs/quadstore-browser\n[b1]: https://github.com/Level/browser-level\n[b2]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API\n\n## Deno usage\n\n`quadstore` can be used with the [Deno][d0] runtime via the [skypack.dev][d1] \nCDN:\n\n```ts\nimport { DataFactory } from 'https://cdn.skypack.dev/rdf-data-factory@1.1.1';\nimport { Quadstore } from 'https://cdn.skypack.dev/quadstore@11.0.6';\nimport { MemoryLevel } from 'https://cdn.skypack.dev/memory-level@1.0.0';\nimport { Engine } from 'https://cdn.skypack.dev/quadstore-comunica@3.0.7';\n\nconst backend = new MemoryLevel();\nconst dataFactory = new DataFactory();\nconst store = new Quadstore({ backend, dataFactory });\nconst engine = new Engine(store);\n\nawait store.open();\nawait store.put(dataFactory.quad(\n        dataFactory.namedNode('ex://s'),\n        dataFactory.namedNode('ex://p'),\n        dataFactory.namedNode('ex://o'),\n));\nconst stream = await engine.queryBindings('SELECT * WHERE { ?s ?p ?o }');\nstream.on('data', (bindings) =\u003e console.log(bindings));\n```\n\nExample usage:\n\n```shell\ndeno run quadstore-test.ts\n```\n\n[d0]: https://deno.land\n[d1]: https://www.skypack.dev\n\n## Performance\n\nPerformance is evaluated at tracked at [https://github.com/quadstorejs/quadstore-perf][perf]\n\n[perf]: https://github.com/quadstorejs/quadstore-perf\n\n## LICENSE\n\nMIT. See [LICENSE.md](./LICENSE.md).\n","funding_links":[],"categories":["Databases"],"sub_categories":["Data Cube extensions"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/beautifulinteractions.github.io%2Fnode-quadstore","html_url":"https://awesome.ecosyste.ms/projects/beautifulinteractions.github.io%2Fnode-quadstore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/beautifulinteractions.github.io%2Fnode-quadstore/lists"}