Giter VIP home page Giter VIP logo

montydb's Introduction

drawing

Python package Version PyPi downloads

Monty, Mongo tinified. MongoDB implemented in Python!

Inspired by TinyDB and it's extension TinyMongo

What is it?

A pure Python-implemented database that looks and works like MongoDB.

>>> from montydb import MontyClient

>>> col = MontyClient(":memory:").db.test
>>> col.insert_many( [{"stock": "A", "qty": 6}, {"stock": "A", "qty": 2}] )
>>> cur = col.find( {"stock": "A", "qty": {"$gt": 4}} )
>>> next(cur)
{'_id': ObjectId('5ad34e537e8dd45d9c61a456'), 'stock': 'A', 'qty': 6}

Most of the CRUD operators have been implemented. You can visit issue #14 to see the full list.

This project is tested against:

  • MongoDB: 3.6, 4.0, 4.2 (4.4 on the way๐Ÿ’ฆ)
  • Python: 2.7, 3.6, 3.7, 3.8, 3.9

Install

pip install montydb
  • optional, to use real bson in operation (pymongo will be installed) For minimum requirements, montydb ships with it's own fork of ObjectId in montydb.types, so you may ignore this option if ObjectId is all you need from bson

    pip install montydb[bson]
  • optional, to use lightning memory-mapped db as storage engine

    pip install montydb[lmdb]

Storage

๐Ÿฆ„ Available storage engines:

  • in-memory
  • flat-file
  • sqlite
  • lmdb (lightning memory-mapped db)

Depending on which one you use, you may have to configure the storage engine before you start.

โš ๏ธ

The configuration process only required on repository creation or modification. And, one repository (the parent level of databases) can only assign one storage engine.

To configure a storage, see flat-file storage for example:

from montydb import set_storage, MontyClient


set_storage(
    # general settings
    
    repository="/db/repo",  # dir path for database to live on disk, default is {cwd}
    storage="flatfile",     # storage name, default "flatfile"
    mongo_version="4.0",    # try matching behavior with this mongodb version
    use_bson=False,         # default None, and will import pymongo's bson if None or True

    # any other kwargs are storage engine settings.
    
    cache_modified=10,       # the only setting that flat-file have
)

# ready to go

Once that done, there should be a file named monty.storage.cfg saved in your db repository path. It would be /db/repo for the above examples.

Configuration

Now let's moving on to each storage engine's config settings.

๐ŸŒŸ In-Memory

memory storage does not need nor have any configuration, nothing saved to disk.

from montydb import MontyClient


client = MontyClient(":memory:")

# ready to go

๐Ÿ”ฐ Flat-File

flatfile is the default on-disk storage engine.

from montydb import set_storage, MontyClient


set_storage("/db/repo", cache_modified=5)  # optional step
client = MontyClient("/db/repo")  # use current working dir if no path given

# ready to go

FlatFile config:

[flatfile]
cache_modified: 0  # how many document CRUD cached before flush to disk.

๐Ÿ’Ž SQLite

sqlite is NOT the default on-disk storage, need configuration first before getting client.

Pre-existing sqlite storage file which saved by montydb<=1.3.0 is not read/writeable after montydb==2.0.0.

from montydb import set_storage, MontyClient


set_storage("/db/repo", storage="sqlite")  # required, to set sqlite as engine
client = MontyClient("/db/repo")

# ready to go

SQLite config:

[sqlite]
journal_mode: WAL

SQLite write concern:

client = MontyClient("/db/repo",
                     synchronous=1,
                     automatic_index=False,
                     busy_timeout=5000)

๐Ÿš€ LMDB (Lightning Memory-Mapped Database)

lightning is NOT the default on-disk storage, need configuration first before get client.

Newly implemented.

from montydb import set_storage, MontyClient


set_storage("/db/repo", storage="lightning")  # required, to set lightning as engine
client = MontyClient("/db/repo")

# ready to go

LMDB config:

[lightning]
map_size: 10485760  # Maximum size database may grow to.

URI

Optionally, You could prefix the repository path with montydb URI scheme.

client = MontyClient("montydb:///db/repo")

Utilities

Pymongo bson may required.

  • montyimport

    Imports content from an Extended JSON file into a MontyCollection instance. The JSON file could be generated from montyexport or mongoexport.

    from montydb import open_repo, utils
    
    
    with open_repo("foo/bar"):
        utils.montyimport("db", "col", "/path/dump.json")
  • montyexport

    Produces a JSON export of data stored in a MontyCollection instance. The JSON file could be loaded by montyimport or mongoimport.

    from montydb import open_repo, utils
    
    
    with open_repo("foo/bar"):
        utils.montyexport("db", "col", "/data/dump.json")
  • montyrestore

    Loads a binary database dump into a MontyCollection instance. The BSON file could be generated from montydump or mongodump.

    from montydb import open_repo, utils
    
    
    with open_repo("foo/bar"):
        utils.montyrestore("db", "col", "/path/dump.bson")
  • montydump

    Creates a binary export from a MontyCollection instance. The BSON file could be loaded by montyrestore or mongorestore.

    from montydb import open_repo, utils
    
    
    with open_repo("foo/bar"):
        utils.montydump("db", "col", "/data/dump.bson")
  • MongoQueryRecorder

    Record MongoDB query results in a period of time. Requires to access database profiler.

    This works via filtering the database profile data and reproduce the queries of find and distinct commands.

    from pymongo import MongoClient
    from montydb.utils import MongoQueryRecorder
    
    client = MongoClient()
    recorder = MongoQueryRecorder(client["mydb"])
    recorder.start()
    
    # Make some queries or run the App...
    recorder.stop()
    recorder.extract()
    {<collection_1>: [<doc_1>, <doc_2>, ...], ...}
  • MontyList

    Experimental, a subclass of list, combined the common CRUD methods from Mongo's Collection and Cursor.

    from montydb.utils import MontyList
    
    mtl = MontyList([1, 2, {"a": 1}, {"a": 5}, {"a": 8}])
    mtl.find({"a": {"$gt": 3}})
    MontyList([{'a': 5}, {'a': 8}])

Why did I make this?

Mainly for personal skill practicing and fun.

I work in the VFX industry and some of my production needs (mostly edge-case) requires to run in a limited environment (e.g. outsourced render farms), which may have problem to run or connect a MongoDB instance. And I found this project really helps.


This project is supported by JetBrains

drawing ย ย  drawing

montydb's People

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.