pymotyc

Statically typed asynchronous MongoDB collections with Pydantic models and Motor engine.


License
MIT
Install
pip install pymotyc==0.9.0

Documentation

PyMotyc

Statically typed asynchronous MongoDB collections with Pydantic models and Motor engine.

Motyc stands for MOngodb TYped Collections, and also is diminutive for the word 'motocycle' in Russian, which is with motor of course!

Key features

One can use only necessary features with existing Pydantic models or all features at once using MotycModel (which is no more than well configured BaseModel).

  • Statically typed MongoDB collection with find and save capabiilities.
  • Trivial query builder to have only relation between model's fields and queries, in which they are used, as well as advaced query builder with logical expresisons over models fields.
  • Flexible identity management during save operation, wherer...

Installation

pip install pymotyc

Quickstart

Please explore this minimal, but fully functional application.

Do import stuff.

import asyncio
from pydantic import BaseModel
from motor.motor_asyncio import AsyncIOMotorClient
import pymotyc

Create Pydantic model.

class Employee(BaseModel):
    name: str
    age: int

Create database class with collections, annotated by Collection[] Generic.

class Warehouse:
    empolyees: pymotyc.Collection[Employee]

Create Motor Client. Provide mongo_host, port etc there. We assume mongo is running on local host with default port. You can use ./run.sh mongo to start MongoDB instance in docker container.

async def main():
    motor = AsyncIOMotorClient("mongodb://127.0.0.1:27017")

Create PyMotyc Engine. Provide Motor client and list of databases to manage by this engine. Engine will create (if no) Collection instanses inside database classes, looking for Collection[] annotaions.

    await pymotyc.Engine.create(motor=motor, databases=[Warehouse])

Now you can access raw Motor collection and db through correspondent attributes of Collection instances. There we will just drop collection to reproduce results of the app runs.

    await Warehouse.empolyees.collection.drop()

Now you can use statically typed collections!

    await Warehouse.empolyees.save(Employee(name='Vasya Pupkin', age=42))

    vasya = await Warehouse.empolyees.find_one(age=42)

    # vasya type is Employee now, enjoy ide type hints!
    assert vasya.name == 'Vasya Pupkin'

    employees = await Warehouse.empolyees.find(age=42)
    assert employees == [Employee(name='Vasya Pupkin', age=42)]

The problem now is, that model instances have no relation with documents inside database, so we can't modify saved or fetched documents in database. To solve this we should provide id management capabilities, see next step!

Go deeper

Models hierarchy and migrations

Id fields and indexes

Raw queries and iterators

Refactorable queries