AsyncIO MongoDB Object Document Mapper for Python using type hints
npx @tessl/cli install tessl/pypi-odmantic@1.0.00
# ODMantic
1
2
ODMantic is a modern async Object Document Mapper (ODM) for MongoDB in Python that leverages type hints and is built on top of Pydantic for model definition and validation. It provides a developer-friendly API for defining MongoDB document models using standard Python types, supports both synchronous and asynchronous operations with AsyncIO frameworks like FastAPI, and offers features including automatic data validation, JSON serialization and schema generation, functional query building using Python operators, and comprehensive type safety.
3
4
## Package Information
5
6
- **Package Name**: odmantic
7
- **Language**: Python
8
- **Installation**: `pip install odmantic`
9
10
## Core Imports
11
12
```python
13
import odmantic
14
```
15
16
Common imports for database operations:
17
18
```python
19
from odmantic import AIOEngine, SyncEngine, Model, Field, ObjectId
20
from odmantic.config import ODMConfigDict
21
```
22
23
## Basic Usage
24
25
```python
26
from odmantic import AIOEngine, Model, Field
27
from motor.motor_asyncio import AsyncIOMotorClient
28
import asyncio
29
30
# Define a model
31
class User(Model):
32
name: str
33
email: str = Field(unique=True)
34
age: int = Field(ge=0)
35
36
# Setup async engine
37
client = AsyncIOMotorClient("mongodb://localhost:27017")
38
engine = AIOEngine(client, database="my_db")
39
40
async def main():
41
# Create and save a user
42
user = User(name="John Doe", email="john@example.com", age=30)
43
await engine.save(user)
44
45
# Find users
46
users = await engine.find(User, User.age >= 18)
47
async for user in users:
48
print(f"{user.name}: {user.email}")
49
50
# Find one user
51
user = await engine.find_one(User, User.email == "john@example.com")
52
if user:
53
print(f"Found: {user.name}")
54
55
asyncio.run(main())
56
```
57
58
## Architecture
59
60
ODMantic's architecture provides both async and sync database operations:
61
62
- **Engines**: Database operation handlers (AIOEngine for async, SyncEngine for sync)
63
- **Models**: Document schemas with type validation using Pydantic
64
- **Fields**: MongoDB-specific field definitions with indexing and constraints
65
- **Sessions**: Transaction and session management for atomic operations
66
- **Query Builder**: Functional query construction using Python operators
67
- **BSON Types**: Native MongoDB types like ObjectId, Int64, Decimal128
68
69
This design allows for type-safe MongoDB operations while maintaining high performance through motor (async) and pymongo (sync) drivers.
70
71
## Capabilities
72
73
### Database Engines
74
75
Async and sync MongoDB operation engines providing complete CRUD functionality, query building, session management, and database configuration.
76
77
```python { .api }
78
class AIOEngine:
79
def __init__(self, client=None, database="test"): ...
80
async def save(self, instance, session=None): ...
81
async def find(self, model, *queries, sort=None, skip=0, limit=None, session=None): ...
82
async def find_one(self, model, *queries, sort=None, session=None): ...
83
async def delete(self, instance, session=None): ...
84
async def count(self, model, *queries, session=None): ...
85
86
class SyncEngine:
87
def __init__(self, client=None, database="test"): ...
88
def save(self, instance, session=None): ...
89
def find(self, model, *queries, sort=None, skip=0, limit=None, session=None): ...
90
def find_one(self, model, *queries, sort=None, session=None): ...
91
def delete(self, instance, session=None): ...
92
def count(self, model, *queries, session=None): ...
93
```
94
95
[Database Engines](./engines.md)
96
97
### Model Definition
98
99
Document model classes with Pydantic integration for validation, serialization, and MongoDB-specific features like embedded documents and references.
100
101
```python { .api }
102
class Model:
103
def model_copy(self, **changes): ...
104
def model_update(self, **changes): ...
105
def model_dump_doc(self, include=None, exclude=None, by_alias=False, exclude_unset=False, exclude_defaults=False): ...
106
@classmethod
107
def model_validate_doc(cls, raw_doc): ...
108
109
class EmbeddedModel:
110
def model_update(self, **changes): ...
111
```
112
113
[Models](./models.md)
114
115
### Field Definitions
116
117
MongoDB-specific field definitions with indexing, validation, and constraint options.
118
119
```python { .api }
120
def Field(
121
default=...,
122
*,
123
key_name=None,
124
primary_field=False,
125
index=False,
126
unique=False,
127
default_factory=None,
128
title=None,
129
description=None,
130
**kwargs
131
): ...
132
```
133
134
[Fields](./fields.md)
135
136
### Query Building
137
138
Functional query construction using Python operators for MongoDB queries and sorting.
139
140
```python { .api }
141
def eq(field, value): ...
142
def ne(field, value): ...
143
def gt(field, value): ...
144
def gte(field, value): ...
145
def lt(field, value): ...
146
def lte(field, value): ...
147
def in_(field, sequence): ...
148
def not_in(field, sequence): ...
149
def match(field, pattern): ...
150
def and_(*elements): ...
151
def or_(*elements): ...
152
def nor_(*elements): ...
153
def asc(field): ...
154
def desc(field): ...
155
```
156
157
[Queries](./queries.md)
158
159
### Session Management
160
161
Session and transaction support for atomic operations and consistency guarantees.
162
163
```python { .api }
164
class AIOSession:
165
async def __aenter__(self): ...
166
async def __aexit__(self, exc_type, exc_val, exc_tb): ...
167
168
class AIOTransaction:
169
async def __aenter__(self): ...
170
async def __aexit__(self, exc_type, exc_val, exc_tb): ...
171
172
class SyncSession:
173
def __enter__(self): ...
174
def __exit__(self, exc_type, exc_val, exc_tb): ...
175
176
class SyncTransaction:
177
def __enter__(self): ...
178
def __exit__(self, exc_type, exc_val, exc_tb): ...
179
```
180
181
[Sessions](./sessions.md)
182
183
### BSON Types
184
185
MongoDB BSON types including ObjectId, Int64, Decimal128, Binary, and Regex.
186
187
```python { .api }
188
class ObjectId:
189
def __init__(self, oid=None): ...
190
def __str__(self): ...
191
192
class WithBsonSerializer:
193
def __bson__(self): ...
194
```
195
196
[BSON Types](./bson-types.md)
197
198
### Index Management
199
200
Index definition and management for MongoDB collections.
201
202
```python { .api }
203
class Index:
204
def __init__(self, *fields, **kwargs): ...
205
206
def Reference(*, key_name=None): ...
207
```
208
209
[Indexes](./indexes.md)
210
211
## Types
212
213
```python { .api }
214
from typing import Optional, Union, List, Dict, Any, Literal, Callable, Iterable
215
from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorClientSession
216
from pymongo import MongoClient, IndexModel
217
from pymongo.client_session import ClientSession
218
from pydantic import ConfigDict
219
from pydantic_core import PydanticCustomError
220
221
# Engine types
222
AIOSessionType = Union[AsyncIOMotorClientSession, AIOSession, AIOTransaction, None]
223
SyncSessionType = Union[ClientSession, SyncSession, SyncTransaction, None]
224
225
# Configuration type
226
class ODMConfigDict(ConfigDict):
227
collection: str | None
228
parse_doc_with_default_factories: bool
229
indexes: Callable[[], Iterable[Index | IndexModel]] | None
230
231
# Field proxy for query building
232
class FieldProxy:
233
def __eq__(self, other): ...
234
def __ne__(self, other): ...
235
def __gt__(self, other): ...
236
def __ge__(self, other): ...
237
def __lt__(self, other): ...
238
def __le__(self, other): ...
239
240
# Query and sort expressions
241
class QueryExpression(Dict[str, Any]): ...
242
class SortExpression(Dict[str, Literal[-1, 1]]): ...
243
244
# Cursors for result iteration
245
class AIOCursor:
246
def __aiter__(self): ...
247
def __await__(self): ...
248
249
class SyncCursor:
250
def __iter__(self): ...
251
```
252
253
## Exceptions
254
255
```python { .api }
256
class BaseEngineException(Exception): ...
257
class DocumentNotFoundError(BaseEngineException): ...
258
class DuplicateKeyError(BaseEngineException): ...
259
class DocumentParsingError(ValueError): ...
260
261
def ODManticCustomError(error_type: str, message_template: str, context: Union[Dict[str, Any], None] = None) -> PydanticCustomError: ...
262
def KeyNotFoundInDocumentError(key_name: str) -> PydanticCustomError: ...
263
def ReferencedDocumentNotFoundError(foreign_key_name: str) -> PydanticCustomError: ...
264
def IncorrectGenericEmbeddedModelValue(value: Any) -> PydanticCustomError: ...
265
```