{"id":13500058,"url":"https://github.com/coleifer/unqlite-python","last_synced_at":"2025-05-15T01:06:53.360Z","repository":{"id":50556877,"uuid":"21070036","full_name":"coleifer/unqlite-python","owner":"coleifer","description":"Python bindings for the UnQLite embedded NoSQL database","archived":false,"fork":false,"pushed_at":"2025-05-12T19:18:10.000Z","size":2152,"stargazers_count":398,"open_issues_count":0,"forks_count":34,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-05-12T20:36:00.837Z","etag":null,"topics":["embedded-database","nosql","python","unqlite"],"latest_commit_sha":null,"homepage":"http://unqlite-python.readthedocs.org/","language":"C","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/coleifer.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":"2014-06-21T14:12:26.000Z","updated_at":"2025-05-12T19:18:13.000Z","dependencies_parsed_at":"2024-10-31T18:31:47.234Z","dependency_job_id":"b71aadca-ee2c-42a0-b378-c813d2e9dc28","html_url":"https://github.com/coleifer/unqlite-python","commit_stats":{"total_commits":164,"total_committers":12,"mean_commits":"13.666666666666666","dds":0.1585365853658537,"last_synced_commit":"4b2b235073e34d26b39adec7ffea4e7fb0dc6d51"},"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coleifer%2Funqlite-python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coleifer%2Funqlite-python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coleifer%2Funqlite-python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coleifer%2Funqlite-python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coleifer","download_url":"https://codeload.github.com/coleifer/unqlite-python/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254254041,"owners_count":22039792,"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":["embedded-database","nosql","python","unqlite"],"created_at":"2024-07-31T22:00:50.581Z","updated_at":"2025-05-15T01:06:50.121Z","avatar_url":"https://github.com/coleifer.png","language":"C","readme":"![](http://media.charlesleifer.com/blog/photos/unqlite-python-logo.png)\n\nFast Python bindings for [UnQLite](http://unqlite.org/), a lightweight, embedded NoSQL database and JSON document store.\n\n### Please note\n\n**Read the issue tracker for [this database](https://github.com/symisc/unqlite/issues/)**\nbefore considering using it. UnQLite has not seen any meaningful development\nsince 2014. It is **strongly** recommended that you use [Sqlite](https://www.sqlite.org/).\nSqlite has robust support for [json](https://www.sqlite.org/json1.html) and is\nactively developed and maintained.\n\n### Features\n\nUnQLite features:\n\n* Embedded, zero-conf database\n* Transactional (ACID)\n* Single file or in-memory database\n* Key/value store\n* Cursor support and linear record traversal\n* JSON document store\n* Thread-safe\n* Terabyte-sized databases\n\nUnQLite-Python features:\n\n* Compiled library, extremely fast with minimal overhead.\n* Supports key/value operations, cursors, and transactions using Pythonic APIs.\n* Support for Jx9 scripting.\n* APIs for working with Jx9 JSON document collections.\n\nLinks:\n\n* [unqlite-python documentation](https://unqlite-python.readthedocs.io/)\n* [UnQLite's C API](http://unqlite.symisc.net/c_api.html)\n\n## Installation\n\nYou can install unqlite using `pip`.\n\n    pip install unqlite\n\n## Basic usage\n\nBelow is a sample interactive console session designed to show some of the basic features and functionality of the unqlite-python library. Also check out the [full API documentation](https://unqlite-python.readthedocs.io/en/latest/api.html).\n\nTo begin, instantiate an ``UnQLite`` object. You can specify either the path to a database file, or use UnQLite as an in-memory database.\n\n```pycon\n\u003e\u003e\u003e from unqlite import UnQLite\n\u003e\u003e\u003e db = UnQLite()  # Create an in-memory database.\n```\n\n### Key/value features\n\nUnQLite can be used as a key/value store.\n\n```pycon\n\u003e\u003e\u003e db['foo'] = 'bar'  # Use as a key/value store.\n\u003e\u003e\u003e db['foo']  # The key/value store deals in byte-strings.\nb'bar'\n\n\u003e\u003e\u003e for i in range(4):\n...     db['k%s' % i] = str(i)\n...\n\n\u003e\u003e\u003e 'k3' in db\nTrue\n\u003e\u003e\u003e 'k4' in db\nFalse\n\u003e\u003e\u003e del db['k3']\n\n\u003e\u003e\u003e db.append('k2', 'XXXX')\n\u003e\u003e\u003e db['k2']\nb'2XXXX'\n```\n\nThe database can also be iterated through directly. Note that keys are decoded\nwhile values are left as bytestrings.\n\n```pycon\n\u003e\u003e\u003e [item for item in db]\n[('foo', b'bar'), ('k0', b'0'), ('k1', b'1'), ('k2', b'2XXXX')]\n```\n\n### Cursors\n\nFor finer-grained record traversal, you can use cursors.\n\n```pycon\n\u003e\u003e\u003e with db.cursor() as cursor:\n...     cursor.seek('k0')\n...     for key, value in cursor:\n...         print(key, '=\u003e', value.decode('utf8'))\n...\nk0 =\u003e 0\nk1 =\u003e 1\nk2 =\u003e 2XXXX\n\n\u003e\u003e\u003e with db.cursor() as cursor:\n...     cursor.seek('k2')\n...     print(cursor.value())\n...\nb'2XXXX'\n\n\u003e\u003e\u003e with db.cursor() as cursor:\n...     cursor.seek('k0')\n...     print(list(cursor.fetch_until('k2', include_stop_key=False)))\n...\n[('k0', b'0'), ('k1', b'1')]\n```\n\nThere are many different ways of interacting with cursors, which are described in the [Cursor API documentation](https://unqlite-python.readthedocs.io/en/latest/api.html#Cursor).\n\n### Document store features\n\nIn my opinion the most interesting feature of UnQLite is its JSON document store. The [Jx9 scripting language](http://unqlite.org/jx9.html) is used to interact with the document store, and it is a wacky mix of PHP and maybe JavaScript (?).\n\n**Note**: as of v0.8.0 the document store and collections APIs treat all\nstrings as unicode.\n\nInteracting with the document store basically consists of creating a Jx9 script (you might think of it as an imperative SQL query), compiling it, and then executing it.\n\n```pycon\n\u003e\u003e\u003e script = \"\"\"\n...     db_create('users');\n...     db_store('users', $list_of_users);\n...     $users_from_db = db_fetch_all('users');\n... \"\"\"\n\n\u003e\u003e\u003e list_of_users = [\n...     {'username': 'Huey', 'age': 3},\n...     {'username': 'Mickey', 'age': 5}\n... ]\n\n\u003e\u003e\u003e with db.vm(script) as vm:\n...     vm['list_of_users'] = list_of_users\n...     vm.execute()\n...     users_from_db = vm['users_from_db']\n...\nTrue\n\n\u003e\u003e\u003e users_from_db  # UnQLite assigns items in a collection an ID.\n[{'username': 'Huey', 'age': 3, '__id': 0},\n {'username': 'Mickey', 'age': 5, '__id': 1}]\n```\n\nThis is just a taste of what is possible with Jx9. In the near future I may add some wrappers around common Jx9 collection operations, but for now hopefully it is not too difficult to work with.\n\nMore information can be found in the [VM API documentation](https://unqlite-python.readthedocs.io/en/latest/api.html#VM).\n\n### Collections\n\nTo simplify working with JSON document collections, `unqlite-python` provides a light API for\nexecuting Jx9 queries on collections. A collection is an ordered list of JSON objects\n(records). Records can be appended or deleted, and in the next major release of UnQLite there will\nbe support for updates as well.\n\nTo begin working with collections, you can use the factory method on ``UnQLite``:\n\n```pycon\n\u003e\u003e\u003e users = db.collection('users')\n\u003e\u003e\u003e users.create()  # Create the collection if it does not exist.\n\u003e\u003e\u003e users.exists()\nTrue\n```\n\nYou can use the ``store()`` method to add one or many records. To add a single record just pass in a python ``dict``. To add multiple records, pass in a list of dicts. Records can be fetched and deleted by ID.\n\nBy default, the ID of the last-stored record is returned. At the time of\nwriting, IDs start at 0, so when inserting 3 records the last-id is 2:\n\n```pycon\n\u003e\u003e\u003e users.store([\n...     {'name': 'Charlie', 'color': 'green'},\n...     {'name': 'Huey', 'color': 'white'},\n...     {'name': 'Mickey', 'color': 'black'}])\n2\n\u003e\u003e\u003e users.store({'name': 'Leslie', 'color': 'also green'}, return_id=False)\nTrue\n\n\u003e\u003e\u003e users.fetch(0)  # Fetch the first record.\n{'__id': 0, 'color': 'green', 'name': 'Charlie'}\n\n\u003e\u003e\u003e users.delete(0)  # Delete the first record.\nTrue\n\u003e\u003e\u003e users.delete(users.last_record_id())  # Delete the last record.\nTrue\n```\n\nYou can retrieve all records in the collection, or specify a filtering function. The filtering function will be registered as a foreign function with the Jx9 VM and called *from* the VM.\n\n```pycon\n\u003e\u003e\u003e users.all()\n[{'__id': 1, 'color': 'white', 'name': 'Huey'},\n {'__id': 2, 'color': 'black', 'name': 'Mickey'}]\n\n\u003e\u003e\u003e users.filter(lambda obj: obj['name'].startswith('H'))\n[{'__id': 1, 'color': 'white', 'name': 'Huey'}]\n```\n\n### Transactions\n\nUnQLite supports transactions for file-backed databases (since transactions occur at the filesystem level, they have no effect on in-memory databases).\n\nThe easiest way to create a transaction is with the context manager:\n\n```pycon\n\u003e\u003e\u003e db = UnQLite('/tmp/test.db')\n\u003e\u003e\u003e with db.transaction():\n...     db['k1'] = 'v1'\n...     db['k2'] = 'v2'\n...\n\u003e\u003e\u003e db['k1']\nb'v1'\n```\n\nYou can also use the transaction decorator which will wrap a function call in a transaction and commit upon successful execution (rolling back if an exception occurs).\n\n```pycon\n\u003e\u003e\u003e @db.commit_on_success\n... def save_value(key, value, exc=False):\n...     db[key] = value\n...     if exc:\n...         raise Exception('uh-oh')\n...\n\u003e\u003e\u003e save_value('k3', 'v3')\n\u003e\u003e\u003e save_value('k3', 'vx', True)\nTraceback (most recent call last):\n  File \"\u003cstdin\u003e\", line 1, in \u003cmodule\u003e\n  File \"unqlite/core.py\", line 312, in wrapper\n    return fn(*args, **kwargs)\n  File \"\u003cstdin\u003e\", line 5, in save_value\nException: uh-oh\n\u003e\u003e\u003e db['k3']\nb'v3'\n```\n\nFor finer-grained control you can call `db.begin()`, `db.rollback()` and `db.commit()` manually:\n\n```pycon\n\u003e\u003e\u003e db.begin()\n\u003e\u003e\u003e db['k3'] = 'v3-xx'\n\u003e\u003e\u003e db.commit()\nTrue\n\u003e\u003e\u003e db['k3']\nb'v3-xx'\n```\n\n-------------------------------------------\n\nThis code is based in part on [buaabyl's pyUnQLite](https://github.com/buaabyl/pyUnQLite/).\n","funding_links":[],"categories":["C"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoleifer%2Funqlite-python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoleifer%2Funqlite-python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoleifer%2Funqlite-python/lists"}