{"id":18887470,"url":"https://github.com/pdrb/dbj","last_synced_at":"2025-08-21T01:32:16.504Z","repository":{"id":62567038,"uuid":"163641244","full_name":"pdrb/dbj","owner":"pdrb","description":"Simple embedded in memory json database.","archived":false,"fork":false,"pushed_at":"2024-10-02T20:14:55.000Z","size":54,"stargazers_count":27,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-04T21:50:04.131Z","etag":null,"topics":["database","dbj","json","nosql","python"],"latest_commit_sha":null,"homepage":"","language":"Python","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/pdrb.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-31T05:15:44.000Z","updated_at":"2024-12-30T08:56:46.000Z","dependencies_parsed_at":"2024-11-15T12:03:59.891Z","dependency_job_id":"73cdd096-7009-4137-8b66-0ad64181dd2f","html_url":"https://github.com/pdrb/dbj","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/pdrb/dbj","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pdrb%2Fdbj","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pdrb%2Fdbj/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pdrb%2Fdbj/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pdrb%2Fdbj/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pdrb","download_url":"https://codeload.github.com/pdrb/dbj/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pdrb%2Fdbj/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270640699,"owners_count":24620993,"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","status":"online","status_checked_at":"2025-08-15T02:00:12.559Z","response_time":110,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","dbj","json","nosql","python"],"created_at":"2024-11-08T07:37:53.341Z","updated_at":"2025-08-21T01:32:16.234Z","avatar_url":"https://github.com/pdrb.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dbj\n\n[![CI](https://github.com/pdrb/dbj/actions/workflows/ci.yml/badge.svg)](https://github.com/pdrb/dbj/actions/workflows/ci.yml)\n[![Coverage](https://coveralls.io/repos/github/pdrb/dbj/badge.svg?branch=master)](https://coveralls.io/github/pdrb/dbj?branch=master)\n[![Version](https://img.shields.io/pypi/v/dbj.svg)](https://pypi.python.org/pypi/dbj)\n[![Downloads](https://static.pepy.tech/badge/dbj)](https://pepy.tech/project/dbj)\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n[![LICENSE](https://img.shields.io/github/license/pdrb/dbj)](https://github.com/pdrb/dbj/blob/master/LICENSE)\n\ndbj is a simple embedded in memory json database.\n\nIt is easy to use, fast and has a simple query language.\n\nThe code is fully documented, tested and beginner friendly.\n\nOnly the standard library is used and it works on Python 3.8+. For older Python (2.7, 3.4...) use version `0.1.10`.\n\n## Usage\n\n```python\n\u003e\u003e\u003e from dbj import dbj\n\u003e\u003e\u003e db = dbj('mydb.json')\n\n\u003e\u003e\u003e # Insert using an auto generated uuid1 key\n\u003e\u003e\u003e db.insert({'name': 'John', 'age': 18})\n'a71d90ce0c7611e995faf23c91392d78'\n\n\u003e\u003e\u003e # Insert using a supplied key, in this case 'anab@example.org'\n\u003e\u003e\u003e user = {'name': 'Ana Beatriz', 'age': 10}\n\u003e\u003e\u003e db.insert(user, 'anab@example.org')\n'anab@example.org'\n\n\u003e\u003e\u003e db.insert({'name': 'Bob', 'age': 30})\n'cc6ddfe60c7611e995faf23c91392d78'\n\n\u003e\u003e\u003e db.get('a71d90ce0c7611e995faf23c91392d78')\n{'name': 'John', 'age': 18}\n\n\u003e\u003e\u003e db.get('anab@example.org')\n{'name': 'Ana Beatriz', 'age': 10}\n\n\u003e\u003e\u003e db.find('age \u003e= 18')\n['a71d90ce0c7611e995faf23c91392d78', 'cc6ddfe60c7611e995faf23c91392d78']\n\n\u003e\u003e\u003e db.find('name == \"ana beatriz\"')\n['anab@example.org']\n\n\u003e\u003e\u003e r = db.find('name == \"John\" or name == \"Bob\" and age \u003e 10')\n\u003e\u003e\u003e db.getmany(r)\n[{'name': 'Bob', 'age': 30}, {'name': 'John', 'age': 18}]\n\n\u003e\u003e\u003e # Sort the result by age\n\u003e\u003e\u003e r = db.sort(r, 'age')\n\u003e\u003e\u003e db.getmany(r)\n[{'name': 'John', 'age': 18}, {'name': 'Bob', 'age': 30}]\n\n\u003e\u003e\u003e # Sort can also be used from find directly\n\u003e\u003e\u003e r = db.find('age \u003e= 10', sortby='age')\n\u003e\u003e\u003e db.getmany(r)\n[{'name': 'Ana Beatriz', 'age': 10}, {'name': 'John', 'age': 18}, {'name': 'Bob', 'age': 30}]\n\n\u003e\u003e\u003e # One-liner:\n\u003e\u003e\u003e db.getmany(db.find('age \u003e= 10', sortby='age'))\n[{'name': 'Ana Beatriz', 'age': 10}, {'name': 'John', 'age': 18}, {'name': 'Bob', 'age': 30}]\n\n\u003e\u003e\u003e db.save()\nTrue\n```\n\n## Install\n\nInstall using pip:\n\n```shell\npip install dbj\n```\n\n## Examples\nCheck the [available commands](#available-commands) for a full list of supported methods.\n\nImport the module and create a new database:\n\n```python\n\u003e\u003e\u003e from dbj import dbj\n\u003e\u003e\u003e db = dbj('mydb.json')\n```\n\nInsert a few documents with auto generated key:\n\n```python\n\u003e\u003e\u003e doc = {'name': 'John Doe', 'age': 18}\n\u003e\u003e\u003e db.insert(doc)\n'7a5ebd420cb211e98a0ff23c91392d78'\n\n\u003e\u003e\u003e docs = [{'name': 'Beatriz', 'age': 30}, {'name': 'Ana', 'age': 10}]\n\u003e\u003e\u003e db.insertmany(docs)\n2\n```\n\nInsert with a supplied key:\n\n```python\n\u003e\u003e\u003e doc = {'name': 'john', 'age': 20, 'country': 'Brasil'}\n\u003e\u003e\u003e db.insert(doc, '1')\n1\n\n\u003e\u003e\u003e db.insert({'name': 'Bob', 'age': 40}, '2')\n2\n\n\u003e\u003e\u003e db.getallkeys()\n['7a5ebd420cb211e98a0ff23c91392d78', 'db21baf80cb211e98a0ff23c91392d78', 'db21edde0cb211e98a0ff23c91392d78', '1', '2']\n```\n\nPop and delete:\n\n```python\n\u003e\u003e\u003e db.delete('1')\nTrue\n\n\u003e\u003e\u003e db.poplast()\n{'name': 'Bob', 'age': 40}\n\n\u003e\u003e\u003e db.size()\n3\n\n\u003e\u003e\u003e db.getallkeys()\n['7a5ebd420cb211e98a0ff23c91392d78', 'db21baf80cb211e98a0ff23c91392d78', 'db21edde0cb211e98a0ff23c91392d78']\n```\n\nUpdating an existing document:\n\n```python\n\u003e\u003e\u003e db.insert({'name': 'Ethan', 'age': 40}, '1000')\n'1000'\n\n\u003e\u003e\u003e db.get('1000')\n{'name': 'Ethan', 'age': 40}\n\n\u003e\u003e\u003e db.update('1000', {'age': 50})\nTrue\n\n\u003e\u003e\u003e db.get('1000')\n{'name': 'Ethan', 'age': 50}\n\n\u003e\u003e\u003e db.update('1000', {'name': 'Ethan Doe', 'gender': 'male'})\nTrue\n\n\u003e\u003e\u003e db.pop('1000')\n{'name': 'Ethan Doe', 'age': 50, 'gender': 'male'}\n```\n\nRetrieving some documents:\n\n```python\n\u003e\u003e\u003e db.getall()\n[{'name': 'John Doe', 'age': 18}, {'name': 'Beatriz', 'age': 30}, {'name': 'Ana', 'age': 10}]\n\n\u003e\u003e\u003e db.getfirst()\n{'name': 'John Doe', 'age': 18}\n\n\u003e\u003e\u003e db.getlast()\n{'name': 'Ana', 'age': 10}\n\n\u003e\u003e\u003e db.getrandom() # returns a random document\n{'name': 'Ana', 'age': 10}\n```\n\nCheck for existance:\n\n```python\n\u003e\u003e\u003e db.exists('7a5ebd420cb211e98a0ff23c91392d78')\nTrue\n```\n\nSearchin and sorting:\n\n```python\n\u003e\u003e\u003e r = db.sort(db.getallkeys(), 'name')\n\u003e\u003e\u003e db.getmany(r)\n[{'name': 'Ana', 'age': 10}, {'name': 'Beatriz', 'age': 30}, {'name': 'John Doe', 'age': 18}]\n\n\u003e\u003e\u003e r = db.find('name ?= \"john\"')\n\u003e\u003e\u003e db.getmany(r)\n[{'name': 'John Doe', 'age': 18}]\n\n\u003e\u003e\u003e query = 'name == \"john doe\" or name == \"ana\" and age \u003e= 10'\n\u003e\u003e\u003e r = db.find(query)\n\u003e\u003e\u003e db.getmany(r)\n[{'name': 'John Doe', 'age': 18}, {'name': 'Ana', 'age': 10}]\n\n\u003e\u003e\u003e r = db.find('age \u003c 40', sortby='age')\n\u003e\u003e\u003e db.getmany(r)\n[{'name': 'Ana', 'age': 10}, {'name': 'John Doe', 'age': 18}, {'name': 'Beatriz', 'age': 30}]\n```\n\nSave the database to disk:\n\n```python\n\u003e\u003e\u003e db.save()\nTrue\n```\n\nTo save a prettified json, use indent:\n\n```python\n\u003e\u003e\u003e db.save(indent=4)\nTrue\n```\n\nEnable auto saving to disk after a insert, update or delete:\n\n```python\n\u003e\u003e\u003e db = dbj('mydb.json', autosave=True)\n```\n\n## About the simple query language\n\nThe query for the find command uses the following pattern:\n\n*field operator value and/or field operator value...*\n\n**Spaces are mandatory** and used as a separator by the parser. For example,\nthe following query **will not work**:\n\n```text\nname==\"John\" and age \u003e=18\n```\n\n**A valid example**:\n\n```text\nname == \"John Doe\" and age \u003e= 18\n```\n\nStrings must be enclosed by quotes. Quoted text can be searched using double\nquotes as the string delimiter, like:\n\n```text\nname == \"\"Bob \"B\" Lee\"\"\n```\n\nPlease note that if value is a string, a search for text will be executed\n(using the string operators below) and if value is a number, a number comparison\nsearch will be used.\n\nThe supported string operators are:\n\n```text\n'==' -\u003e Exact match. 'John' will not match 'John Doe' but will match 'john'\nby default. If case sensitive is desired, just use find with sens=True. See\navailable commands below for the full find method signature.\n\n'?=' -\u003e Partial match. In this case, 'John' will match 'John Doe'.\n\n'!=' -\u003e Not equal operator.\n```\n\nThe numbers comparison operators are:\n\n```text\n'==', '!=', '\u003c', '\u003c=', '\u003e', '\u003e='\n```\n\nThe supported logical operatos are:\n\n```text\nand, or\n```\n\n## Important changes\n\n0.1.4:\n------\n\n* The insert() method will raise a TypeError exception if the document dict is not json serializable.\n\n## Performance\n\nSince the entire database is a dict in memory, performance is pretty\ngood, it can handle dozens of thousands operations per second.\n\nA simple benchmark is included to get a roughly estimative of operations per\nsecond. Here is the result running on my personal machine (Ryzen 5 1600)\nusing Ubuntu 22 (via Windows WSL2) on Python 3.11:\n\n```text\n$ python3.11 bench_dbj.py\n\n--------------------------------\n\nInserting 100000 documents using auto generated uuid1 key...\nDone! Time spent: 0.50s\nInserted: 100000\nRate: 199738 ops/s\n\n--------------------------------\n\nClearing the database...\nDone!\n\n--------------------------------\n\nInserting 100000 documents using a supplied key...\nDone! Time spent: 0.24s\nInserted: 100000\nRate: 419375 ops/s\n\n--------------------------------\n\nRetrieving 100000 documents one at a time...\nDone! Time spent: 0.02s\nRetrieved: 100000\nRate: 6307774 ops/s\n\n--------------------------------\n\nSaving database to disk...\nDone! Time spent: 0.20s\n\n--------------------------------\n\nDeleting 100000 documents one at a time...\nDone! Time spent: 0.03s\nDeleted: 100000\nRate: 3827445 ops/s\n\n--------------------------------\n\nRemoving file...\nDone!\n\nPeak memory usage: 45.36 MB\n```\n\n## Available commands\n\n```text\ninsert(document, key=None) -\u003e Create a new document on database.\n    Args:\n        | document (dict): The document to be created.\n        | key (str, optional): The document unique key. Defaults to uuid1.\n    Returns:\n        The document key.\n\ninsertmany(documents) -\u003e Insert multiple documents on database.\n    Args:\n        documents (list): List containing the documents to insert.\n    Returns:\n        Number of inserted documents.\n\nsave(indent=None) -\u003e Save database to disk.\n    Args:\n        indent (int or str, optional): If provided, save a prettified json with that indent level. 0, negative or \"\" will only insert newlines.\n    Returns:\n        True if successful.\n\nclear() -\u003e Remove all documents from database.\n    Returns:\n        True if successful.\n\nsize() -\u003e Return the database size.\n    Returns:\n        Number of documents on database.\n\nexists(key) -\u003e Check if a document exists on database.\n    Args:\n        key (str): The document key.\n    Returns:\n        True or False if it does not exist.\n\ndelete(key) -\u003e Delete a document on database.\n    Args:\n        key (str): The document key.\n    Returns:\n        True or False if it does not exist.\n\ndeletemany(keys) -\u003e Delete multiple documents on database.\n    Args:\n        keys (list): List containing the keys of the documents to delete.\n    Returns:\n        Number of deleted documents.\n\nupdate(key, values) -\u003e Add/update values on a document.\n    Args:\n        | key (str): The document key.\n        | values (dict): The values to be added/updated.\n    Returns:\n        True or False if document does not exist.\n\nupdatemany(keys, values) -\u003e Add/update values on multiple documents.\n    Args:\n        | keys (list): List containing the keys of the documents to update.\n        | values (dict): The values to be added/updated.\n    Returns:\n        Number of updated documents.\n\nget(key) -\u003e Get a document on database.\n    Args:\n        key (str): The document key.\n    Returns:\n        The document or False if it does not exist.\n\ngetmany(keys) -\u003e Get multiple documents from database.\n    Args:\n        keys (list): List containing the keys of the documents to retrieve.\n    Returns:\n        List of documents.\n\ngetall() -\u003e Return a list containing all documents on database.\n    Returns:\n        List with all database documents.\n\ngetallkeys() -\u003e Return a list containing all keys on database.\n    Returns:\n        List with all database keys.\n\ngetrandom() -\u003e Get a random document on database.\n    Returns:\n        A document or False if database is empty.\n\ngetfirst() -\u003e Get the first inserted document on database.\n    Returns:\n        The first inserted document or False if database is empty.\n\ngetlast() -\u003e Get the last inserted document on database.\n    Returns:\n        The last inserted document or False if database is empty.\n\ngetfirstkey() -\u003e Get the first key on database.\n    Returns:\n        The first key or False if database is empty.\n\ngetlastkey() -\u003e Get the last key on database.\n    Returns:\n        The last key or False if database is empty.\n\npop(key) -\u003e Get the document from database and remove it.\n    Args:\n        key (str): The document key.\n    Returns:\n        The document or False if it does not exist.\n\npopfirst() -\u003e Get the first inserted document on database and remove it.\n    Returns:\n        The first inserted document or False if database is empty.\n\npoplast() -\u003e Get the last inserted document on database and remove it.\n    Returns:\n        The last inserted document or False if database is empty.\n\nsort(keys, field, reverse=False) -\u003e Sort the documents using the field provided.\n    Args:\n        | keys (list): List containing the keys of the documents to sort.\n        | field (str): Field to sort.\n        | reverse (bool, optional): Reverse search. Defaults to False.\n    Returns:\n        Sorted list with the documents keys.\n\nfindtext(field, text, exact=False, sens=False, inverse=False, asc=True) -\u003e Simple text search on the provided field.\n    Args:\n        | field (str): The field to search.\n        | text (str): The value to be searched.\n        | exact (bool, optional): Exact text match. Defaults to False.\n        | sens (bool, optional): Case sensitive. Defaults to False.\n        | inverse (bool, optional): Inverse search, return the documents that do not match the search. Defaults to False.\n        | asc (bool, optional): Ascii conversion before matching, this matches text like 'cafe' and 'café'. Defaults to True.\n    Returns:\n        List with the keys of the documents that matched the search.\n\nfindnum(expression) -\u003e Simple number comparison search on provided field.\n    Args:\n        | expression (str): The comparison expression to use, e.g., \"age \u003e= 18\". The pattern is 'field operator number'.\n    Returns:\n        List with the keys of the documents that matched the search.\n\nfind(query, sens=False, asc=True, sortby=None, reverse=False) -\u003e Simple query like search.\n    Args:\n        | query (str): The query to use.\n        | sens (bool, optional): Case sensitive. Defaults to False.\n        | asc (bool, optional): Ascii conversion before matching, this matches text like 'cafe' and 'café'. Defaults to True.\n        | sortby (string, optional): Sort using the provided field.\n        | reverse (bool, optional): Reverse sort. Defaults to False.\n    Returns:\n        List with the keys of the documents that matched the search.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpdrb%2Fdbj","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpdrb%2Fdbj","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpdrb%2Fdbj/lists"}