Skip to main content

NeoSQLite - NoSQL for SQLite with PyMongo-like API

PyPI Version

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

NeoSQLite: SQLite with a MongoDB Disguise

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: expireAfterSeconds expiry with lazy auto-purge and an opt-in background sweeper.
  • ACID Transactions: Full ClientSession API 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 GridFSBucket API plus legacy GridFS compatibility.
  • Binary Data: PyMongo-compatible Binary class 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 $expr queries.
  • 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.16.0

NeoSQLite v1.16.0 is a feature release delivering PyMongo modern API parity, TTL index expiry, and change-stream hardening for SQLite-backed job queues. All additions are backward compatible.

Key Highlights:

  • PyMongo Modern Parity — find() accepts limit/skip/sort kwargs; create_index() accepts expireAfterSeconds and other options; new get_database()/drop_database() helpers.
  • TTL Index Expiry — expireAfterSeconds declaration with purge_expired(), lazy auto-purge on reads, and an opt-in background sweeper.
  • Change-Stream Hardening — resume_after/start_after tokens, library-side $match filtering, and a documented drain-then-tail job-queue recipe.
  • 48 New Tests — Full suite green (2,919 passed) with the force-fallback kill switch both on and off.

For full details, see documents/releases/v1.16.0.md. Previous release highlights are in documents/releases/v1.15.2.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 _id values are stored and queried in the dedicated _id column — not redirected to the auto-increment id rowid.
  • String _id values are kept verbatim (e.g., "5" is a string, not converted to integer 5).
  • Auto-generated _id produces MongoDB-compatible 12-byte ObjectIds stored in the _id column.
  • Legacy collections (created before the _id column existed) fall back to the id column via an automatic resolver.
  • Range queries ($gt, $lt, etc.) on _id use 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.16.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for neosqlite 1.16.0
File Size Uploaded
neosqlite-1.16.0.tar.gz 295.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for neosqlite 1.16.0
File Interpreter ABI Platform
neosqlite-1.16.0-py3-none-any.whl Python 3 none any Details

Total release size: 652.6 kB

Release files / neosqlite-1.16.0.tar.gz

Download URL neosqlite-1.16.0.tar.gz
Size 295.1 kB
Tags Source
SHA-256 checksum
How to use checksums
4309260ca1231ed4aef37063825c41523607b19ad3b1e2058ee0a081b3f30818
BLAKE2b-256 checksum
How to use checksums
87e615e237ac87876a2e22b00c8312b2e203a12c97ad2bc7b877fbd64b993192
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.14.7 Darwin/25.6.0

Release files / neosqlite-1.16.0-py3-none-any.whl

Download URL neosqlite-1.16.0-py3-none-any.whl
Size 357.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8f217c08b0125d87d101bdc52ff69bf97e04019b56151beb289711e41e06e6de
BLAKE2b-256 checksum
How to use checksums
b9999831d48c9e09ebf5dc7115dd045c19a409ac4ac6bdb020c326952dffa861
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.14.7 Darwin/25.6.0

Release history Release notifications | RSS feed

1.17.0

2 release files

1.16.3

2 release files

1.16.2

2 release files

1.16.1

2 release files

This release

1.16.0 This release

2 release files

1.15.1

2 release files

1.15.0

2 release files

1.14.9

2 release files

1.14.8

2 release files

1.14.7

2 release files

1.14.6

2 release files

1.14.5

2 release files

1.14.4

2 release files

1.14.3

2 release files

1.13.9

2 release files

1.13.8

2 release files

1.13.7

2 release files

1.13.6

2 release files

1.13.5

2 release files

1.13.4

2 release files

1.13.3

2 release files

1.13.2

2 release files

1.13.1

2 release files

1.13.0

2 release files

1.12.1

2 release files

1.12.0

2 release files

1.11.0

2 release files

1.10.1

2 release files

1.10.0

2 release files

1.9.2

2 release files

1.9.1

2 release files

1.9.0

2 release files

1.8.0

2 release files

1.7.0

2 release files

1.6.1

2 release files

1.6.0

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.3.2

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.3

2 release files

1.2.2

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page