Skip to main content

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 .mdb file
  • 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 file
  • kwargs: Additional options

Methods:

  • list_collection_names(): Returns a list of collection names in the database
  • drop_collection(name): Drops a collection
  • stats(): Returns database statistics
  • close(): Closes the database connection

Collection Class

Methods for working with collections:

Collection Operations

  • create_collection(name, options=None): Creates a new collection
  • drop(): Drops the collection
  • renameCollection(newName): Renames the collection
  • stats(): Returns collection statistics
  • count_documents(query): Counts documents matching the query
  • create_index(keys, **kwargs): Creates an index on the specified fields

Document Operations

  • insert_one(document): Inserts a single document
  • insert_many(documents): Inserts multiple documents
  • find(query=None, projection=None): Finds documents matching the query
  • find_one(query=None, projection=None): Finds a single document
  • update_one(filter, update, options=None): Updates a single document
  • update_many(filter, update, options=None): Updates multiple documents
  • replace_one(filter, replacement, options=None): Replaces a document
  • delete_one(filter): Deletes a single document
  • delete_many(filter): Deletes multiple documents
  • bulk_write(operations): Performs bulk write operations
  • distinct(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 bytes on 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 operations
  • advanced_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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mainydb-1.0.3.tar.gz (21.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mainydb-1.0.3-py3-none-any.whl (16.0 kB view details)

Uploaded Python 3

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

Hashes for mainydb-1.0.3.tar.gz
Algorithm Hash digest
SHA256 8320cec7efa3da9bddc024837d199a6cc98dfc5216fdfb7b5572550b882d7d89
MD5 6624a69fc126841fe0425e2af8687a6a
BLAKE2b-256 1fdd960a2dd4dc4b2f4e1eb98b1bc48e829cba152ec22a47f255b0a4f3967277

See more details on using hashes here.

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

Hashes for mainydb-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 73de0e22167ca09d85a88c78e1a207c6fe7eda17e81026cafa3c1652cab0a8e5
MD5 1ba09f095ab41ef289b8f0e73ca27b56
BLAKE2b-256 e8d50640e750ae86ba7779eb24219679c48a5fc3e3840b95412514e2ce550ce4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page