{"id":19290395,"url":"https://github.com/deve-sh/doggodb","last_synced_at":"2026-05-17T19:02:39.834Z","repository":{"id":57214506,"uuid":"300869919","full_name":"deve-sh/DoggoDB","owner":"deve-sh","description":"A try at a lightweight database as a localStorage abstraction in the browser.","archived":false,"fork":false,"pushed_at":"2021-05-09T04:33:51.000Z","size":573,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-29T14:03:25.539Z","etag":null,"topics":["database"],"latest_commit_sha":null,"homepage":"https://deve-sh.github.io/DoggoDB","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/deve-sh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-10-03T11:59:24.000Z","updated_at":"2021-05-09T04:33:53.000Z","dependencies_parsed_at":"2022-08-26T13:41:27.366Z","dependency_job_id":null,"html_url":"https://github.com/deve-sh/DoggoDB","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deve-sh%2FDoggoDB","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deve-sh%2FDoggoDB/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deve-sh%2FDoggoDB/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deve-sh%2FDoggoDB/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deve-sh","download_url":"https://codeload.github.com/deve-sh/DoggoDB/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240395742,"owners_count":19794573,"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"],"created_at":"2024-11-09T22:19:07.174Z","updated_at":"2025-11-14T19:09:07.341Z","avatar_url":"https://github.com/deve-sh.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Doggo DB 🐶\n\nDoggoDB is a simple implementation of a local-storage based mini database in the browser that stores data in the form of JSON Data.\n\nThere are plans to expand to full-fledged file based database storage on the server-side with indices and a better querying syntax.\n\n**Note**: As of now, you can't use the implementation inside a server environment like Node.js since the Local Storage API isn't directly available inside a server.\n\n## Index\n\nThe links might not work in case you are viewing them in docs generated using JSDoc, it might be easier in that case to simply scroll to those sections.\n\n-   [Use Cases And Features](#use-cases-and-features)\n-   [Installation](#installation)\n-   [Usage](#usage)\n    -   [Initialize the Database](#initialize-the-database)\n    -   [Creating Tables](#creating-tables)\n    -   [Adding Data to Tables](#adding-data-to-tables)\n    -   [Retreiving Data](#retreiving-data)\n    -   [Finding And Querying Data](#finding-and-querying-data)\n    -   [Advanced Querying Capabilities](#advanced-querying-capabilities)\n    -   [Updating Data](#updating-data)\n    -   [Deleting Data](#deleting-data)\n    -   [Transactions](#transactions)\n-   [Contribution](#contribution)\n-   [Suggestions, Issues and Bugs](#suggestions-issues-and-bugs)\n\n## Use Cases And Features\n\nThis is not supposed to be a primary database, which is supposed to be obvious. Instead, DoggoDB is supposed to be used as primarily a localStorage based cache for libraries/frameworks such as Svelte or just plain HTML, CSS and JS that don't have a native persisted state management solution such as `Redux-Persist` (Although you can use Redux and Redux Persist with pretty much any framework or libraries, how many of us do?)\n\n#### Wait a second... Why wouldn't I simply write Local Storage querying code myself?\n\nYou absolutely can. This is just an interesting side project that I plan to expand to a fully functional server-side database as I learn more about databases. Inspired by projects such as [Firebase](https://firebase.google.com) and [lowdb](https://github.com/typicode/lowdb) but with 0 dependencies written purely with Vanilla JavaScript.\n\nAlso, this was built out of my own need for a good abstraction on top of `localStorage`, and also better looking querying syntax 😛.\n\nDoggoDB in its first iteration supports:\n\n-   Creation of databases.\n-   Creation of tables.\n-   Querying of tables.\n-   Adding data to tables.\n-   Updation of existing data.\n-   Deletion based on filters.\n\nI.E: The basic CRUD system of NoSQL Databases.\n\n## Installation\n\nRun the following command to install this database utility.\n\n```bash\nnpm install doggodb\n```\n\nAnd include as:\n\n```javascript\n// CommonJS / Node.js (I don't know why you would use this in a server environment at this stage.)\nconst { db } = require(\"doggodb\");\n\n// ES6 Imports\nimport { db } from \"doggodb\";\n\n// Named Import\nimport { db as doggodb } from \"doggodb\";\n```\n\nTo download from a CDN:\n\n```html\n\u003c!-- Head --\u003e\n\u003cscript\n    type=\"text/javascript\"\n    src=\"https://unpkg.com/doggodb/dist/doggodb.min.js\"\n\u003e\u003c/script\u003e\n\n\u003c!-- Body Bottom --\u003e\n\u003cscript type=\"text/javascript\" defer\u003e\n    // The 'db' function is inside the 'doggodb' object after importing from CDN.\n    const dbInstance = new doggodb.db(\"databaseName\");\n\u003c/script\u003e\n```\n\nFeel free to play around with the imports and names.\n\n## Usage\n\n#### Initialize the Database\n\n```js\nconst dbInstance = new db(\"databaseName\");\nconst secondDB = new db(\"separateDatabase\");\n```\n\n#### Creating tables\n\nCreate a table using the instance:\n\n```js\ndbInstance.table(\"newtable\");\n```\n\n#### Adding data to tables\n\nAdd data to a table (Right now data container can only be an object, but the fields it contains can be anything supported by `JSON.stringify`)\n\n```js\ndbInstance.table(\"newtable\").add({\n    firstName: \"ABC\",\n    lastName: \"XYZ\",\n});\n```\n\nWhen you add data to a table, DoggoDB automatically adds a unique identifider called `entryId`. The different name is chosen to not conflict with idetifiers such as **'id'** or **'\\_id'** that you might be storing locally after importing from your primary database.\n\n#### Retreiving Data\n\nGet all data stored in a table as an array:\n\n```js\ndbInstance.table(\"newtable\").get(); // [ {...} ]\n```\n\n#### Finding and Querying Data\n\nQuery data based on field values (Only linear fields supported, no array or object equality as of now):\n\n```js\ndbInstance.table(\"newtable\").find({ firstName: \"ABC\" }); // [ { ... }]\n```\n\nTo find without any filters, you can pass an empty object or no filter object at all.\n\n```js\ndbInstance.table(\"newtable\").find({}); // Technically the same as .get\ndbInstance.table(\"newtable\").find(); // Technically the same as .get\n\n// To find by id. Simply include it.\ndbInstance.table(\"newtable\").find({ entryId: 123 });\n```\n\nTo offset and limit data, pass in an object with the `offset` and `limit` properties.\n\n- `offset` - The index to start counting entries from.\n- `limit` - The number of entires to limit in the result set.\n\n```js\ndbInstance.table(\"newtable\").find({ field: \"value\" }, { limit: 5 });\ndbInstance.table(\"newtable\").find({ field: \"value\" }, { offset: 2, limit: 3 });\ndbInstance.table(\"newtable\").find({ field: \"value\" }, { offset: 4 });\n```\n\nQueries now also support nested querying, for example, if you want to search for a field match inside an object in your table row named `details` with field named `access`:\n\n```js\ndbInstance.table(\"newtable\").find({\n    \"details.access\": \"admin\"   // For data structured like: { details: { access: \"admin\", name: \"xyz\" } }\n})\n```\n\nQueries now also support Regular Expression Based querying (Even for nested object queries):\n\n```js\ndbInstance.table(\"newtable\").find({\n    \"details.access\": /adm/i\n})\n```\n\n\n#### Advanced Querying Capabilities\n\nOn top of the limits and offset methods, the library also supports advanced querying capabilities such as 'Array Membership' and other operations. They can be acheived by structuring your filter objects in specific ways.\n\nRight now, the following are available:\n\n- `$not`: Checks if a value in a field is not the provided value.\n\nThe following two are only applicable for fields that are of the type Arrays:\n- `$includes`: Checks if a field's value includes a certain value.\n- `$notIncludes`: Checks if a field's value includes a certain value or not.\n\nThe remaining are also array-membership operations.\n- `$in`: Checks if a field's value is included in a set of values.\n- `$any`: Simple copy of '$in'.\n- `$notIn`: Checks if a field's value is not present in an Array value. \n\n**Usage**:\n\n```js\ndbInstance.table(\"newtable\").find({ \n    $not: { field: 1 }  // Will check if the value for \"field\" is not equal to 1.\n});\n\ndbInstance.table(\"newtable\").find({ \n    $includes: { field: 1 } // Will check if the array at \"field\" includes 1 or not.\n});\n\ndbInstance.table(\"newtable\").find({ \n    $notIncludes: { field: 1 }\n});\n\ndbInstance.table(\"newtable\").find({ \n    $any: { field: [ 1, 2, 3] }\n});\n\ndbInstance.table(\"newtable\").find({ \n    $in: { field: [ 1, 2, 3] }\n});\n\ndbInstance.table(\"newtable\").find({ \n    $notIn: { field: [ 1, 2, 3] }\n});\n```\n\n##### Or Queries\n\nOr Queries are now supported by DoggoDB.\n\n```js\ndbInstance.table(\"newtable\").find({ \n    $or: { field1: \"value1\", field2: \"value2\"}\n});\n```\n\nThe above query, unlike the other filters, checks for the rows where either of the conditions is valid. This can be paired with other filters and they will behave as regular queries.\n\n**Notes**: As of now, the advanced queries can't be nested inside each other, but they can be paired together to create a super query.\n\nFor Example:\n\n```js\ndbInstance.table(\"newtable\").find({ \n    $or: { field1: \"value1\", field2: \"value2\"}, \n    $in: { field3: [1, 2, 3] }\n});\n```\n\nAnother point to note is that the queries work only on rows that have those fields in them. If suppose you try to find rows where the `marks` attribute is 0, the rows that don't have `marks` won't be counted.\n\nThe above advanced querying capabilities are supported for updating and deleting data as well.\n\n#### Updating Data\n\nTo update a set of values fetched from filters. Use the `findAndUpdate` method.\n\n```js\ndbInstance.table(\"newtable\").findAndUpdate(filters, { ...updates });\n```\n\nThis method by default only **updates the first entry it finds matching the filters**, in order to update all the entries, pass `false` as the last paramter.\n\n```js\ndbInstance.table(\"newtable\").findAndUpdate(filters, { ...updates }, false);\n```\n\nTo update at a specific index in the contents, use the `updateAt` function.\n\n```js\ndbInstance.table(\"newtable\").updateAt(entryIndex, { ...updates });\n```\n\n#### Deleting Data\n\nTo delete data that matches a filter. Use the `delete` method.\n\n```js\ndbInstance.table(\"newtable\").delete(filters);\n```\n\nThis method, just like the `findAndUpdate` method, **deletes only the the first entry it finds matching the filters**. To override this behaviour, pass `false` as the final argument to the function.\n\n```js\ndbInstance.table(\"newtable\").delete(filters, false);\n```\n\n### Transactions\n\nThe database now supports transactions. These are pretty simple in their work and follow the following algorithm to perform them:\n\n- Start a transaction by setting a flag to `true`.\n- Make any changes locally in the class state.\n- If the user commits the transaction, commit the changes made in the local class state to the storage.\n- If the user aborts the transaction, simply discard the changes made in the class state and load the new changes afresh.\n\n```js\n// Usage of transactions\ndbInstance.startTransaction();\n\n// ... Make any changes here to the instance as you would based on the above docs.\n\n// Commit the transaction\ndbInstance.commitTransaction();\n\n// Abort the transaction\ndbInstance.abortTransaction();\n\n// Continue...\n```\n\n## Contribution\n\nThis project is extremely naive at this stage, and any contibutions or suggestions would be highly appreciated.\n\nFor contributing to the code, simply fork this repository, make the changes you may want to in a new branch and create a pull request for it.\n\nFor making any suggestions, read the [Issues and Bugs](#suggestions-issues-and-bugs) section.\n\n## Suggestions, Issues and Bugs\n\nFor any issues related to this project, simply raise an issue in the repository and I will respond quickly.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeve-sh%2Fdoggodb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeve-sh%2Fdoggodb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeve-sh%2Fdoggodb/lists"}