NeoSQLite - NoSQL for SQLite with PyMongo-like API
NeoSQLite (new + nosqlite) is a pure Python library that provides a schemaless, PyMongo-like wrapper for interacting with SQLite databases. The API is designed to be familiar to those who have worked with PyMongo, providing a simple and intuitive way to work with document-based data in a relational database.
Keywords: NoSQL, NoSQLite, SQLite NoSQL, PyMongo alternative, SQLite document database, Python NoSQL, schemaless SQLite, MongoDB-like SQLite
Features
PyMongo-like API: A familiar interface for developers experienced with MongoDB.- NX-27017: MongoDB Wire Protocol Server — Use PyMongo with SQLite backend
- Schemaless Documents: Store flexible JSON-like documents.
- Lazy Cursor:
find()returns a memory-efficient cursor for iterating over results. - Raw Batch Support:
find_raw_batches()returns raw JSON data in batches for efficient processing. - Advanced Indexing: Single-key, compound-key, nested-key indexes, and FTS5 text search.
- TTL Indexes:
expireAfterSecondsexpiry with lazy auto-purge and an opt-in background sweeper. - ACID Transactions: Full
ClientSessionAPI with PyMongo 4.x parity using SQLite SAVEPOINTs. - Change Streams: Native SQLite triggers for
watch()— no replica set required. - Advanced Aggregation:
$setWindowFields,$graphLookup,$fill, streaming$facet, and more. - Tier-1 SQL Optimization: Dozens of operators translated to native SQL for 10-100x speedup.
- Native
$jsonSchema: Query filtering and write-time validation via SQLite CHECK constraints. - Window Functions: Complete MongoDB 5.0+ suite (
$rank,$top,$bottom, math operators). - MongoDB-compatible ObjectId: Full 12-byte specification with automatic generation.
- Full GridFS Support: Modern
GridFSBucketAPI plus legacyGridFScompatibility. - Binary Data: PyMongo-compatible
Binaryclass with UUID support. - AutoVacuum & compact: Reclaim disk space with incremental or full VACUUM.
- dbStats Command: MongoDB-compatible statistics with accurate index sizes.
- SQL Translation Caching: 10-30% faster for repeated aggregation pipelines and
$exprqueries. - Configurable Journal Mode: WAL (default), DELETE, MEMORY, and more.
- Security Hardening: Built-in SQL injection protection via centralized identifier quoting.
See Release Notes for the full history.
Latest Release: v1.17.0
NeoSQLite v1.17.0 is a minor feature and parity release delivering comprehensive transactional hardening, PyMongo API parity expansions, and 100% compatibility across the differential test suite. Fully backward compatible.
Key Highlights:
- Transaction Context Managers & Session Propagation —
ClientSession.start_transaction()supports the Python context manager protocol (with session.start_transaction(): ...), with strict session validation and pass-through across operations likefind_one(..., session=session). - Full Bulk Write Architecture & Parity — Added
BulkWriteError,upserted_ids, duck-typed request matching, and fullordered=Truevsordered=Falseexecution semantics with failure accumulation. - Aggregation System Variables & Expressions — Added support for
$$ROOTand$$CURRENTsystem variables and dictionary template expressions in$groupaccumulators,%Lmillisecond formatting in$dateToString, and composable$dateDiffwith nested date arithmetic expressions. - Data Safety, Storage Integrity & Security Hardening — Ensured WAL checkpointing and compliant backup file naming during auto-vacuum migration, prevented SQL injection in
$lookupaliases and collection names, sanitized FTS5 queries against syntax injection, prevented silent GridFS data loss on non-autocommit connections, and eliminated thread race conditions inObjectIdcounter generation. - Type & Query Parity — Converted
ObjectId.generation_timeto a timezone-aware UTC datetime property;$currentDatenow sets proper BSON Date objects deserialized as Pythondatetime.datetime; exact_idtypes are preserved without string-to-ObjectId coercion; andlist_collection_names()cleanly excludes internal SQLite, metadata, and FTS5 shadow tables.
For full details, see documents/releases/v1.17.0.md. Previous release highlights are in documents/releases/v1.16.3.md.
Installation
pip install neosqlite
Optional Extras
# Enhanced JSON/JSONB support (only needed if your SQLite lacks JSON functions)
pip install neosqlite[jsonb]
# Memory-constrained processing for large result sets
pip install neosqlite[memory-constrained]
# NX-27017 MongoDB Wire Protocol Server
pip install "neosqlite[nx27017]" # Core
pip install "neosqlite[nx27017-speed]" # With uvloop (Linux/macOS)
Quickstart
import neosqlite
with neosqlite.Connection(':memory:') as conn:
users = conn.users
# Insert
users.insert_one({'name': 'Alice', 'age': 30})
users.insert_many([
{'name': 'Bob', 'age': 25},
{'name': 'Charlie', 'age': 35}
])
# Find
alice = users.find_one({'name': 'Alice'})
for user in users.find():
print(user)
# Update
users.update_one({'name': 'Alice'}, {'$set': {'age': 31}})
# Delete & Count
result = users.delete_many({'age': {'$gt': 30}})
print(f"Remaining: {users.count_documents({})}")
Drop-in Replacement for PyMongo
1. Direct API (No MongoDB)
import neosqlite
client = neosqlite.Connection('mydatabase.db')
collection = client.mycollection
collection.insert_one({"name": "test"})
2. Wire Protocol (NX-27017) — Zero Code Changes
# Start server
nx-27017 --db ./myapp.db
# Then use PyMongo normally — no code changes!
from pymongo import MongoClient
client = MongoClient('mongodb://localhost:27017/')
collection = client.mydatabase.mycollection
collection.insert_one({"name": "test"}) # Works!
PyMongo Compatibility
| Metric | Result |
|---|---|
| Total Tests | 381 |
| Passed | 363 |
| Skipped | 18 (architectural differences) |
| Failed | 0 |
| Compatibility | 100% |
Skipped tests are due to MongoDB requiring a replica set (change streams, transactions) or NeoSQLite extensions ($log2, $contains). All comparable APIs pass. Tested against MongoDB 8.x (mongo:8.2.12 pinned container image).
Run the comparison yourself: ./scripts/run-api-comparison.sh
_id Field Behavior
NeoSQLite uses a strict MongoDB-compatible _id column:
- Integer
_idvalues are stored and queried in the dedicated_idcolumn — not redirected to the auto-incrementidrowid. - String
_idvalues are kept verbatim (e.g.,"5"is a string, not converted to integer5). - Auto-generated
_idproduces MongoDB-compatible 12-byte ObjectIds stored in the_idcolumn. - Legacy collections (created before the
_idcolumn existed) fall back to theidcolumn via an automatic resolver. - Range queries (
$gt,$lt, etc.) on_iduse Python evaluation to preserve correct cross-type comparison semantics (MongoDB BSON ordering).
Key APIs
Indexes
# Single-key, compound, nested
users.create_index('age')
users.create_index([('name', neosqlite.ASCENDING), ('age', neosqlite.DESCENDING)])
users.create_index('profile.followers')
# FTS5 text search
users.create_search_index('bio')
Query Operators
$eq, $gt, $gte, $lt, $lte, $ne, $in, $nin, $and, $or, $not, $nor,
$exists, $type, $regex, $elemMatch, $size, $mod,
$bitsAllSet, $bitsAllClear, $bitsAnySet, $bitsAnyClear,
$text (FTS5), $jsonSchema, and more.
Aggregation Stages
$match, $project, $group, $sort, $skip, $limit, $unwind,
$lookup, $facet, $bucket, $bucketAuto, $sample, $merge,
$setWindowFields, $graphLookup, $fill, $densify, $unionWith,
$replaceRoot, $replaceWith, $unset, $count, $redact, $addFields, $switch.
Transactions
with client.start_session() as session:
with session.start_transaction():
users.insert_one({"name": "Alice"}, session=session)
orders.insert_one({"user": "Alice"}, session=session)
# Commits on success, rolls back on exception
Change Streams
# Native SQLite triggers — no replica set needed
stream = collection.watch()
for change in stream:
print(change)
Journal Mode
from neosqlite import Connection, JournalMode
db = Connection("app.db", journal_mode=JournalMode.WAL) # Default
| Mode | Use Case |
|---|---|
| WAL | Best concurrency (default) |
| DELETE | Single-file distribution |
| MEMORY | Maximum speed, no crash recovery |
Documentation
| Topic | Link |
|---|---|
| Knowledge Base / Docs | documents/ |
| Release Notes | documents/releases/ |
| GridFS | documents/gridfs.md |
| Text Search | documents/text-search.md |
| Aggregation Optimization | documents/aggregation-pipeline-optimization.md |
| NX-27017 Server | packages/nx_27017/README.md |
| API Comparison | examples/api_comparison/README.md |
Contributing
Clone the repository:
git clone https://github.com/cwt/neosqlite.git
cd neosqlite
Create and activate a virtual environment:
python3 -m venv .venv
source .venv/bin/activate
Then run the test script, which installs all required dependencies automatically:
./scripts/runtest.sh
Shell Script Compatibility
All shell scripts in this project target bash 3.2+ for compatibility with macOS, which still ships with bash 3.2.x. Please ensure any contributions to shell scripts remain compatible.
Contribution and License
This project was originally developed as shaunduncan/nosqlite and was later forked as plutec/nosqlite before becoming NeoSQLite. It is now maintained by Chaiwat Suttipongsakul and is licensed under the MIT license.
Contributions are highly encouraged. If you find a bug, have an enhancement in mind, or want to suggest a new feature, please feel free to open an issue or submit a pull request.
Metadata
Release files for neosqlite 1.17.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| neosqlite-1.17.0.tar.gz | 305.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| neosqlite-1.17.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 670.9 kB
Release files / neosqlite-1.17.0.tar.gz
| Download URL | neosqlite-1.17.0.tar.gz |
|---|---|
| Size | 305.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e82081648e4d89842936f2c77bbba45a999ed5fa27dd20d34a0444efeb5aacf7
|
|
BLAKE2b-256 checksum How to use checksums |
893ba3bd6aa52bb0748479babc7cee9491322a050f74810728786d04b8d980a3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.1 CPython/3.14.7 Linux/7.2.7-200.fc44.x86_64
|
Release files / neosqlite-1.17.0-py3-none-any.whl
| Download URL | neosqlite-1.17.0-py3-none-any.whl |
|---|---|
| Size | 365.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b48fca4c715e6286023b98e2b4de56e8dcd9efe9a93fd838865df4cba2ab2342
|
|
BLAKE2b-256 checksum How to use checksums |
55ae826e0a86234f817b3432139ddc5488349d02b62f2dab372052c9f67b83d8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.1 CPython/3.14.7 Linux/7.2.7-200.fc44.x86_64
|