A lightweight, embedded MongoDB-like database in a single file
Project description
MainyDB
MainyDB is an ultra-fast, embedded MongoDB-like database in a single .mdb file. It provides a PyMongo-compatible API, allowing you to use MongoDB-style queries, updates, and aggregations in a lightweight, file-based database.
Features
- Single File Storage: All data is stored in a single
.mdbfile - PyMongo-Compatible API: Use the same API as PyMongo for seamless integration
- JSON-like Document Storage: Store and query JSON-like documents (Python dictionaries)
- Full MongoDB Query Support: Includes comparison, logical, array, and update operators
- Aggregation Pipeline: Perform complex data transformations with MongoDB-style aggregation pipelines
- In-Memory Indexes: Fast queries with automatic indexing
- Asynchronous File Writing: Non-blocking operations for better performance
- Thread-Safe: Concurrent access with proper locking mechanisms
- Media Support: Store and retrieve images and videos with automatic base64 encoding/decoding
- Media Caching: Automatic caching of decoded media for 2 hours
Installation
pip install MainyDB
The Library is also available on PyPI: https://pypi.org/project/MainyDB/
# Clone the repository
git clone https://github.com/dddevid/MainyDB.git
# Install dependencies
cd MainyDB
pip install -r requirements.txt
Quick Start
from MainyDB import MainyDB
# Create or open a database
db = MainyDB("my_database.mdb")
# Get a collection (creates it if it doesn't exist)
users = db.myapp.users
# Insert a document
user_id = users.insert_one({
"name": "John Doe",
"email": "john@example.com",
"age": 30
}).inserted_id
# Find documents
for user in users.find({"age": {"$gt": 25}}):
print(f"{user['name']}: {user['email']}")
# Update a document
users.update_one(
{"_id": user_id},
{"$set": {"age": 31}}
)
# Delete a document
users.delete_one({"email": "john@example.com"})
# Close the database when done
db.close()
PyMongo Compatibility Mode
MainyDB can be used as a drop-in replacement for PyMongo:
from MainyDB import MongoClient
# Connect to a "server" (actually uses the file-based database)
client = MongoClient()
# Get a database
db = client.myapp
# Get a collection
users = db.users
# Use the same PyMongo API
users.insert_one({"name": "Jane Smith"})
API Reference
MainyDB Class
MainyDB(file_path, **kwargs)
Creates or opens a MainyDB database.
file_path: Path to the .mdb filekwargs: Additional options
Methods:
list_collection_names(): Returns a list of collection names in the databasedrop_collection(name): Drops a collectionstats(): Returns database statisticsclose(): Closes the database connection
Collection Class
Methods for working with collections:
Collection Operations
create_collection(name, options=None): Creates a new collectiondrop(): Drops the collectionrenameCollection(newName): Renames the collectionstats(): Returns collection statisticscount_documents(query): Counts documents matching the querycreate_index(keys, **kwargs): Creates an index on the specified fields
Document Operations
insert_one(document): Inserts a single documentinsert_many(documents): Inserts multiple documentsfind(query=None, projection=None): Finds documents matching the queryfind_one(query=None, projection=None): Finds a single documentupdate_one(filter, update, options=None): Updates a single documentupdate_many(filter, update, options=None): Updates multiple documentsreplace_one(filter, replacement, options=None): Replaces a documentdelete_one(filter): Deletes a single documentdelete_many(filter): Deletes multiple documentsbulk_write(operations): Performs bulk write operationsdistinct(field, query=None): Returns distinct values for a field
Query Operators
MainyDB supports all standard MongoDB query operators:
Comparison Operators
$eq: Equals$ne: Not equals$gt: Greater than$gte: Greater than or equal$lt: Less than$lte: Less than or equal$in: In array$nin: Not in array
Logical Operators
$and: Logical AND$or: Logical OR$not: Logical NOT$nor: Logical NOR
Array Operators
$all: All elements match$elemMatch: Element matches$size: Array size
Update Operators
$set: Sets field values$unset: Removes fields$inc: Increments field values$mul: Multiplies field values$rename: Renames fields$min: Updates if value is less than current$max: Updates if value is greater than current$currentDate: Sets field to current date$push: Adds elements to arrays$pop: Removes first or last element from arrays$pull: Removes elements from arrays$pullAll: Removes all matching elements from arrays$addToSet: Adds elements to arrays if they don't exist
Aggregation Pipeline
MainyDB supports MongoDB-style aggregation pipelines with stages like:
$match: Filters documents$project: Reshapes documents$group: Groups documents$sort: Sorts documents$limit: Limits number of documents$skip: Skips documents$unwind: Deconstructs arrays$addFields: Adds fields$lookup: Performs a left outer join$count: Counts documents
Media Handling
MainyDB can store and retrieve binary data like images and videos:
# Store an image
with open("image.jpg", "rb") as f:
image_data = f.read()
media = db.myapp.media
media.insert_one({
"name": "profile_pic.jpg",
"data": image_data # Automatically encoded as base64
})
# Retrieve the image
stored_media = media.find_one({"name": "profile_pic.jpg"})
image_data = stored_media["data"] # Automatically decoded from base64
# Save the image
with open("retrieved_image.jpg", "wb") as f:
f.write(image_data)
Direct Image Upload (file path)
- You can upload images by passing a file path string directly; MainyDB reads the file, stores it as base64, and returns
byteson read. - Supported extensions:
.png,.jpg,.jpeg,.webp,.tiff,.heic,.gif.
# Insert from file path (the image is stored as base64 internally)
images = db.myapp.images
res = images.insert_one({
"name": "logo",
"image": "./assets/logo.png" # path to an existing image file
})
# Read: returns raw bytes (not a base64 string)
logo_doc = images.find_one({"name": "logo"})
logo_bytes = logo_doc["image"]
with open("retrieved_logo.png", "wb") as f:
f.write(logo_bytes)
Thread Safety
MainyDB is thread-safe and can be accessed from multiple threads:
import threading
def update_counter(thread_id):
for i in range(1000):
# Atomic update operation
counters.update_one(
{"_id": "counter1"},
{"$inc": {"value": 1}}
)
# Create threads
threads = []
for i in range(10):
thread = threading.Thread(target=update_counter, args=(i,))
threads.append(thread)
thread.start()
# Wait for all threads to complete
for thread in threads:
thread.join()
Examples
See the examples directory for more detailed examples:
basic_usage.py: Basic CRUD operationsadvanced_usage.py: Advanced queries, aggregations, and concurrency
Stress Test
Sono disponibili script di stresstest nella cartella tests/stress. Ogni script è eseguibile direttamente:
# Inserimenti massivi e throughput
python tests/stress/stress_large_insert.py
# Concorrenza lettura/scrittura con più thread
python tests/stress/stress_concurrent_rw.py
# Mix di operazioni CRUD, proiezioni, skip/limit e aggregazioni
python tests/stress/stress_mixed_operations.py
# Stress su indici (singoli e compositi) e query mirate
python tests/stress/stress_indexing.py
Note:
- Gli script usano un database temporaneo e non modificano file esistenti.
- Gli output stampano riassunti (tempo, operazioni/secondo, conteggi) e includono assert per la correttezza di base.
- Esegui gli script dalla radice del progetto (
e:\Progetti\MainyDB).
Author
Made with ❤️ by devid
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mainydb-1.0.3.tar.gz.
File metadata
- Download URL: mainydb-1.0.3.tar.gz
- Upload date:
- Size: 21.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8320cec7efa3da9bddc024837d199a6cc98dfc5216fdfb7b5572550b882d7d89
|
|
| MD5 |
6624a69fc126841fe0425e2af8687a6a
|
|
| BLAKE2b-256 |
1fdd960a2dd4dc4b2f4e1eb98b1bc48e829cba152ec22a47f255b0a4f3967277
|
File details
Details for the file mainydb-1.0.3-py3-none-any.whl.
File metadata
- Download URL: mainydb-1.0.3-py3-none-any.whl
- Upload date:
- Size: 16.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
73de0e22167ca09d85a88c78e1a207c6fe7eda17e81026cafa3c1652cab0a8e5
|
|
| MD5 |
1ba09f095ab41ef289b8f0e73ca27b56
|
|
| BLAKE2b-256 |
e8d50640e750ae86ba7779eb24219679c48a5fc3e3840b95412514e2ce550ce4
|