
Security News
PyPI Expands Trusted Publishing to GitLab Self-Managed as Adoption Passes 25 Percent
PyPI adds Trusted Publishing support for GitLab Self-Managed as adoption reaches 25% of uploads
A complete, zero-configuration NoSQL database solution for Python applications
dbini is a feature-complete NoSQL database solution designed for Python applications that need advanced document storage without the complexity of external database setup. It provides a comprehensive, file-based storage system with support for complex queries, array operations, full-text search, and REST API access - making it ideal for production applications, prototyping, and local-first development.
$size, $elemMatch, and array indexinguser.profile.preferences)$eq, $ne, $gt, $gte, $lt, $lte$and, $or, $not$in, $nin, $size, $elemMatch$like, $regex$existspip install dbini
git clone https://github.com/Binidu01/dbini.git
cd dbini
pip install .
from dbini import DBini
# Initialize database for your project
db = DBini("myproject")
# Add a new document
user_data = {
"name": "Alice Johnson",
"email": "alice@example.com",
"age": 28,
"skills": ["python", "javascript", "react"],
"profile": {
"bio": "Full-stack developer",
"location": "San Francisco",
"preferences": {"theme": "dark"}
}
}
doc_id = db.add_document("users", user_data)
# Simple queries
users = db.find("users", filters={"age": 28})
user = db.get_document("users", doc_id)
# Complex queries with array operations
react_users = db.find("users", filters={
"skills": {"$in": ["react"]}
})
# Nested object queries
dark_theme_users = db.find("users", filters={
"profile.preferences.theme": "dark"
})
# Array size queries
skilled_users = db.find("users", filters={
"skills": {"$size": {"$gte": 3}}
})
db.close()
from dbini import DBini
from dbini.core import Collection
db = DBini("advanced_project")
users = Collection(db, "users")
# Sample data with complex structures
sample_users = [
{
"name": "Alice",
"age": 28,
"skills": ["python", "react", "node.js"],
"projects": [
{"name": "E-commerce API", "status": "completed", "tech": ["python"]},
{"name": "Dashboard", "status": "in_progress", "tech": ["react"]}
],
"location": "San Francisco"
},
{
"name": "Bob",
"age": 32,
"skills": ["python", "django"],
"projects": [
{"name": "Blog Platform", "status": "completed", "tech": ["django"]}
],
"location": "New York"
}
]
# Bulk insert
user_ids = users.bulk_insert(sample_users)
# Complex array queries - find users with completed projects
completed_project_users = users.find({
"projects": {
"$elemMatch": {"status": "completed"}
}
})
# Complex logical queries
experienced_python_devs = users.find({
"$and": [
{"age": {"$gte": 25}},
{"skills": {"$in": ["python"]}},
{"projects": {"$size": {"$gte": 1}}}
]
})
# Regular expression queries
sf_users = users.find({
"location": {"$regex": "San.*"}
})
# Full-text search
react_related = users.find(search="react dashboard")
# Upsert operation
user_id, was_inserted = users.upsert(
{"email": "charlie@example.com"}, # filter
{"name": "Charlie", "age": 25, "skills": ["javascript"]} # data
)
# Aggregations with grouping
avg_age_by_location = users.aggregate("avg", "age", group_by="location")
skill_counts = users.aggregate("count", group_by="skills")
db.close()
from dbini import DBini
db = DBini("validated_project")
# Define schema
user_schema = {
"fields": {
"name": {"type": "string", "required": True, "minLength": 2},
"email": {"type": "string", "required": True},
"age": {"type": "integer", "min": 0, "max": 120},
"skills": {"type": "array"},
"profile.bio": {"type": "string", "maxLength": 500}
}
}
# Set schema for collection
db.set_schema("users", user_schema)
# Documents are automatically validated
try:
doc_id = db.add_document("users", {
"name": "John",
"email": "john@example.com",
"age": 25,
"skills": ["python", "django"]
})
print("Document added successfully")
except ValueError as e:
print(f"Validation failed: {e}")
# Manual validation
valid_doc = {"name": "Jane", "email": "jane@example.com", "age": 30}
is_valid, errors = db.validate_document("users", valid_doc)
print(f"Valid: {is_valid}, Errors: {errors}")
db.close()
from dbini.server import serve
# Start enhanced API server with all features
serve(project_root="myproject", host="localhost", port=8080)
The server provides comprehensive REST API endpoints:
| Method | Endpoint | Description |
|---|---|---|
POST | /v1/collections/{collection}/documents | Create document with validation |
GET | /v1/collections/{collection}/documents/{id} | Get document by ID |
PATCH | /v1/collections/{collection}/documents/{id} | Update document (partial) |
DELETE | /v1/collections/{collection}/documents/{id} | Delete document |
PUT | /v1/collections/{collection}/documents/upsert | Upsert document |
| Method | Endpoint | Description |
|---|---|---|
POST | /v1/collections/{collection}:query | Advanced query with filters, search, sorting |
GET | /v1/collections/{collection}/documents | Get all documents with pagination |
POST | /v1/collections/{collection}:aggregate | Aggregation operations |
| Method | Endpoint | Description |
|---|---|---|
POST | /v1/collections/{collection}/bulk:insert | Bulk insert documents |
POST | /v1/collections/{collection}/bulk:update | Bulk update documents |
POST | /v1/collections/{collection}/bulk:delete | Bulk delete documents |
| Method | Endpoint | Description |
|---|---|---|
POST | /v1/collections/{collection}/schema | Set collection schema |
GET | /v1/collections/{collection}/schema | Get collection schema |
DELETE | /v1/collections/{collection}/schema | Remove collection schema |
POST | /v1/collections/{collection}:validate | Validate document against schema |
| Method | Endpoint | Description |
|---|---|---|
GET | /v1/collections | List collections with stats |
GET | /v1/collections/{collection}/stats | Get collection statistics |
POST | /v1/collections/{collection}/index | Create field index |
| Method | Endpoint | Description |
|---|---|---|
POST | /v1/files | Upload file |
GET | /v1/files/{id} | Download file |
GET | /v1/files/{id}/info | Get file metadata |
GET | /v1/files | List all files |
DELETE | /v1/files/{id} | Delete file |
| Method | Endpoint | Description |
|---|---|---|
GET | /v1/health | System health check |
GET | /v1/info | Database information and stats |
POST | /v1/export | Export database snapshot |
POST | /v1/restore | Restore from snapshot |
| Endpoint | Description |
|---|---|
ws://host:port/v1/ws/{collection} | Collection-specific updates |
ws://host:port/v1/ws | All database updates |
# Advanced query with multiple conditions
curl -X POST "http://localhost:8080/v1/collections/users:query" \
-H "Content-Type: application/json" \
-d '{
"filters": {
"$and": [
{"age": {"$gte": 25}},
{"skills": {"$in": ["python"]}},
{"projects": {"$elemMatch": {"status": "completed"}}}
]
},
"sort": [["age", -1], ["name", 1]],
"limit": 10,
"search": "developer"
}'
# Bulk insert multiple users
curl -X POST "http://localhost:8080/v1/collections/users/bulk:insert" \
-H "Content-Type: application/json" \
-d '{
"docs": [
{"name": "Alice", "age": 28, "skills": ["python", "react"]},
{"name": "Bob", "age": 32, "skills": ["java", "spring"]}
]
}'
# Bulk update with filters
curl -X POST "http://localhost:8080/v1/collections/users/bulk:update" \
-H "Content-Type: application/json" \
-d '{
"filters": {"age": {"$gte": 30}},
"updates": {"is_senior": true}
}'
# Set schema for collection
curl -X POST "http://localhost:8080/v1/collections/users/schema" \
-H "Content-Type: application/json" \
-d '{
"schema": {
"fields": {
"name": {"type": "string", "required": true},
"email": {"type": "string", "required": true},
"age": {"type": "integer", "min": 0, "max": 120}
}
}
}'
from dbini import DBini
db = DBini("project_path")
# Document operations
doc_id = db.add_document(collection, document, doc_id=None)
doc = db.get_document(collection, doc_id)
success = db.update_document(collection, doc_id, updates)
doc_id, was_inserted = db.upsert_document(collection, filters, updates, doc_id=None)
success = db.delete_document(collection, doc_id)
# Advanced querying
docs = db.find(collection, filters=None, limit=None, sort=None, search=None)
# Bulk operations
doc_ids = db.bulk_insert(collection, documents)
count = db.bulk_update(collection, filters, updates)
count = db.bulk_delete(collection, filters)
# Aggregations
result = db.aggregate(collection, operation, field=None, group_by=None)
# Schema operations
db.set_schema(collection, schema)
schema = db.get_schema(collection)
is_valid, errors = db.validate_document(collection, document)
# Indexing and optimization
db.ensure_index_on(collection, field_path)
stats = db.collection_stats(collection)
# File operations
file_id = db.save_file(file_path, dest_filename=None)
file_path = db.get_file_path(file_id)
files = db.list_files()
# Utilities
collections = db.list_collections()
snapshot_path = db.export_snapshot(snapshot_dir)
db.restore_snapshot(snapshot_path)
is_valid, bad_line, message = db.verify_wal()
db.close()
from dbini.core import Collection
collection = Collection(db, "collection_name")
# Simplified operations
doc_id = collection.add(document, doc_id=None)
doc = collection.get(doc_id)
success = collection.update(doc_id, updates)
doc_id, was_inserted = collection.upsert(filters, updates, doc_id=None)
success = collection.delete(doc_id)
# Querying
docs = collection.find(filters=None, limit=None, sort=None, search=None)
doc = collection.find_one(filters)
# Bulk operations
doc_ids = collection.bulk_insert(documents)
count = collection.bulk_update(filters, updates)
count = collection.bulk_delete(filters)
# Aggregations and utilities
result = collection.aggregate(operation, field=None, group_by=None)
collection.create_index(field)
collection.set_schema(schema)
schema = collection.get_schema()
stats = collection.stats()
When you initialize a dbini project, the following directory structure is created:
myproject/
├── data/
│ ├── collections/
│ │ └── users/
│ │ ├── 550e8400-e29b-41d4-a716-446655440000.json
│ │ └── 6ba7b810-9dad-11d1-80b4-00c04fd430c8.json
│ └── files/
│ ├── 123e4567-e89b-12d3-a456-426614174000_image.jpg
│ └── 987fcdeb-51a2-43d1-9f12-345678901234_document.pdf
├── index/
│ ├── users.sqlite
│ └── files.index.sqlite
├── wal/
│ └── append.log
└── meta/
├── project.json
├── keys.json
└── users_schema.json
dbini is built with modern Python technologies and best practices:
The enhanced version is fully backward compatible. Existing code will work unchanged, but you can now use additional features:
# Old code (still works)
db = DBini("myproject")
docs = db.find("users", filters={"age": 25})
# New enhanced features
# Array operations
users_with_skills = db.find("users", filters={"skills": {"$size": {"$gte": 3}}})
# Full-text search
search_results = db.find("users", search="python developer")
# Upsert operations
user_id, inserted = db.upsert_document("users", {"email": "user@example.com"}, {"name": "Updated Name"})
# Bulk operations
inserted_ids = db.bulk_insert("users", [{"name": "User1"}, {"name": "User2"}])
We welcome contributions to dbini! Here's how you can help:
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)git clone https://github.com/Binidu01/dbini.git
cd dbini
pip install -e ".[dev]"
pytest # Run tests
Please ensure your code follows Python best practices and includes appropriate tests.
This project is licensed under the MIT License. See the LICENSE file for details.
/docs when running the server$size, $elemMatch)dbini is inspired by modern NoSQL databases like MongoDB and local-first software principles. Special thanks to the Python community and all contributors who help improve this project.
Made with ❤️ by Binidu01
If you find dbini useful, please consider giving it a ⭐ on GitHub!
FAQs
Zero-config NoSQL backend database as a Python package
We found that dbini demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
PyPI adds Trusted Publishing support for GitLab Self-Managed as adoption reaches 25% of uploads

Research
/Security News
A malicious Chrome extension posing as an Ethereum wallet steals seed phrases by encoding them into Sui transactions, enabling full wallet takeover.

Security News
Socket is heading to London! Stop by our booth or schedule a meeting to see what we've been working on.