mindtrace-database 0.11.0__tar.gz → 0.13.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mindtrace_database-0.13.0/PKG-INFO +486 -0
- mindtrace_database-0.13.0/README.md +464 -0
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/__init__.py +2 -1
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/backends/mongo_odm.py +61 -9
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/backends/redis_odm.py +26 -20
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/core/exceptions.py +7 -0
- mindtrace_database-0.13.0/mindtrace/database/sample/user.py +12 -0
- mindtrace_database-0.13.0/mindtrace/database/testing/__init__.py +29 -0
- mindtrace_database-0.13.0/mindtrace/database/testing/suites/__init__.py +1 -0
- mindtrace_database-0.13.0/mindtrace/database/testing/suites/_models.py +21 -0
- mindtrace_database-0.13.0/mindtrace/database/testing/suites/_mongo.py +28 -0
- mindtrace_database-0.13.0/mindtrace/database/testing/suites/mongo_crud.py +106 -0
- mindtrace_database-0.13.0/mindtrace/database/testing/suites/mongo_insert.py +113 -0
- mindtrace_database-0.13.0/mindtrace/database/testing/suites/mongo_read.py +133 -0
- mindtrace_database-0.13.0/mindtrace/database/testing/suites/mongo_update.py +124 -0
- mindtrace_database-0.13.0/mindtrace_database.egg-info/PKG-INFO +486 -0
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace_database.egg-info/SOURCES.txt +9 -0
- mindtrace_database-0.13.0/mindtrace_database.egg-info/entry_points.txt +2 -0
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace_database.egg-info/requires.txt +2 -2
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/pyproject.toml +6 -3
- mindtrace_database-0.11.0/PKG-INFO +0 -1084
- mindtrace_database-0.11.0/README.md +0 -1062
- mindtrace_database-0.11.0/mindtrace/database/sample/user.py +0 -10
- mindtrace_database-0.11.0/mindtrace_database.egg-info/PKG-INFO +0 -1084
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/LICENSE +0 -0
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/backends/mindtrace_odm.py +0 -0
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/backends/registry_odm.py +0 -0
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/backends/unified_odm.py +0 -0
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace_database.egg-info/dependency_links.txt +0 -0
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace_database.egg-info/top_level.txt +0 -0
- {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/setup.cfg +0 -0
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mindtrace-database
|
|
3
|
+
Version: 0.13.0
|
|
4
|
+
Summary: Database functionality for Mindtrace
|
|
5
|
+
Author: Mindtrace Team
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://mindtrace.ai
|
|
8
|
+
Project-URL: Repository, https://github.com/mindtrace/mindtrace/blob/main/mindtrace/database
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: beanie<2,>=1.29.0
|
|
14
|
+
Requires-Dist: mindtrace-core>=0.13.0
|
|
15
|
+
Requires-Dist: pydantic>=2.11.1
|
|
16
|
+
Requires-Dist: redis>=4.0.0
|
|
17
|
+
Requires-Dist: redis-om>=0.3.5
|
|
18
|
+
Requires-Dist: motor>=3.3.0
|
|
19
|
+
Requires-Dist: pymongo>=4.14.0
|
|
20
|
+
Requires-Dist: mindtrace-registry>=0.13.0
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
[](https://pypi.org/project/mindtrace-database/)
|
|
24
|
+
[](https://github.com/mindtrace/mindtrace/blob/main/mindtrace/database/LICENSE)
|
|
25
|
+
[](https://pepy.tech/projects/mindtrace-database)
|
|
26
|
+
|
|
27
|
+
# Mindtrace Database
|
|
28
|
+
|
|
29
|
+
The `Database` module provides Mindtrace’s object-document mapping layer for MongoDB, Redis, Registry-backed storage, and unified multi-backend workflows.
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
- **Unified ODM interface** through `UnifiedMindtraceODM`
|
|
34
|
+
- **Backend-specific ODMs** for MongoDB, Redis, and Registry-backed storage
|
|
35
|
+
- **Single-model and multi-model operation** in the same API style
|
|
36
|
+
- **Sync and async access patterns** across all supported backends
|
|
37
|
+
- **Unified document models** that can target both MongoDB and Redis
|
|
38
|
+
- **Consistent exceptions** such as `DocumentNotFoundError` and `DuplicateInsertError`
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
import asyncio
|
|
44
|
+
|
|
45
|
+
from pydantic import Field
|
|
46
|
+
|
|
47
|
+
from mindtrace.database import BackendType, UnifiedMindtraceDocument, UnifiedMindtraceODM
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class User(UnifiedMindtraceDocument):
|
|
51
|
+
name: str = Field(description="User name")
|
|
52
|
+
email: str = Field(description="Email address")
|
|
53
|
+
age: int = Field(ge=0)
|
|
54
|
+
|
|
55
|
+
class Meta:
|
|
56
|
+
collection_name = "users"
|
|
57
|
+
global_key_prefix = "myapp"
|
|
58
|
+
indexed_fields = ["email", "name"]
|
|
59
|
+
unique_fields = ["email"]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
async def main():
|
|
63
|
+
db = UnifiedMindtraceODM(
|
|
64
|
+
unified_model_cls=User,
|
|
65
|
+
mongo_db_uri="mongodb://localhost:27017",
|
|
66
|
+
mongo_db_name="myapp",
|
|
67
|
+
redis_url="redis://localhost:6379",
|
|
68
|
+
preferred_backend=BackendType.MONGO,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
user = User(name="Alice", email="alice@example.com", age=30)
|
|
72
|
+
inserted = await db.insert_async(user)
|
|
73
|
+
fetched = await db.get_async(inserted.id)
|
|
74
|
+
print(fetched)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
asyncio.run(main())
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
In practice, the database module gives you a common way to define document models and CRUD workflows while choosing the backend that best fits your application.
|
|
81
|
+
|
|
82
|
+
## Core Concepts
|
|
83
|
+
|
|
84
|
+
The package revolves around four main ODM styles:
|
|
85
|
+
|
|
86
|
+
- **`UnifiedMindtraceODM`** — one API over MongoDB and/or Redis
|
|
87
|
+
- **`MongoMindtraceODM`** — MongoDB-specific ODM built on Beanie
|
|
88
|
+
- **`RedisMindtraceODM`** — Redis-specific ODM built on redis-om
|
|
89
|
+
- **`RegistryMindtraceODM`** — Registry-backed ODM for simpler local or storage-backed document persistence
|
|
90
|
+
|
|
91
|
+
The package also provides matching document model bases:
|
|
92
|
+
|
|
93
|
+
- `UnifiedMindtraceDocument`
|
|
94
|
+
- `MindtraceDocument`
|
|
95
|
+
- `MindtraceRedisDocument`
|
|
96
|
+
|
|
97
|
+
## UnifiedMindtraceODM
|
|
98
|
+
|
|
99
|
+
`UnifiedMindtraceODM` is the recommended starting point when you want one API that can work across MongoDB and Redis.
|
|
100
|
+
|
|
101
|
+
### Unified document model
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from pydantic import Field
|
|
105
|
+
|
|
106
|
+
from mindtrace.database import UnifiedMindtraceDocument
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class User(UnifiedMindtraceDocument):
|
|
110
|
+
name: str = Field(description="User name")
|
|
111
|
+
email: str = Field(description="Email")
|
|
112
|
+
age: int = Field(ge=0)
|
|
113
|
+
|
|
114
|
+
class Meta:
|
|
115
|
+
collection_name = "users"
|
|
116
|
+
global_key_prefix = "myapp"
|
|
117
|
+
indexed_fields = ["email", "name"]
|
|
118
|
+
unique_fields = ["email"]
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Unified ODM setup
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from mindtrace.database import BackendType, UnifiedMindtraceODM
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
db = UnifiedMindtraceODM(
|
|
128
|
+
unified_model_cls=User,
|
|
129
|
+
mongo_db_uri="mongodb://localhost:27017",
|
|
130
|
+
mongo_db_name="myapp",
|
|
131
|
+
redis_url="redis://localhost:6379",
|
|
132
|
+
preferred_backend=BackendType.MONGO,
|
|
133
|
+
)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Common operations
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
# Async operations
|
|
140
|
+
inserted_user = await db.insert_async(User(name="Alice", email="alice@example.com", age=30))
|
|
141
|
+
retrieved_user = await db.get_async(inserted_user.id)
|
|
142
|
+
retrieved_user.age = 31
|
|
143
|
+
updated_user = await db.update_async(retrieved_user)
|
|
144
|
+
all_users = await db.all_async()
|
|
145
|
+
python_users = await db.find_async({"name": "Alice"})
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
# Sync operations
|
|
150
|
+
inserted_user = db.insert(User(name="Bob", email="bob@example.com", age=25))
|
|
151
|
+
retrieved_user = db.get(inserted_user.id)
|
|
152
|
+
retrieved_user.age = 26
|
|
153
|
+
updated_user = db.update(retrieved_user)
|
|
154
|
+
all_users = db.all()
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Switching backends
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
db.switch_backend(BackendType.REDIS)
|
|
161
|
+
redis_user = db.insert(User(name="Carol", email="carol@example.com", age=28))
|
|
162
|
+
|
|
163
|
+
current_backend = db.get_current_backend_type()
|
|
164
|
+
print(current_backend)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Multi-model mode
|
|
168
|
+
|
|
169
|
+
All ODMs in this package support multi-model mode.
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
class Address(UnifiedMindtraceDocument):
|
|
173
|
+
street: str
|
|
174
|
+
city: str
|
|
175
|
+
|
|
176
|
+
class Meta:
|
|
177
|
+
collection_name = "addresses"
|
|
178
|
+
global_key_prefix = "myapp"
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
db = UnifiedMindtraceODM(
|
|
182
|
+
unified_models={"user": User, "address": Address},
|
|
183
|
+
mongo_db_uri="mongodb://localhost:27017",
|
|
184
|
+
mongo_db_name="myapp",
|
|
185
|
+
redis_url="redis://localhost:6379",
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
address = await db.address.insert_async(Address(street="123 Main St", city="NYC"))
|
|
189
|
+
user = await db.user.insert_async(User(name="Alice", email="alice@example.com", age=30))
|
|
190
|
+
users = await db.user.all_async()
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
In multi-model mode, use attribute-based access like `db.user.insert_async(...)` rather than `db.insert_async(...)`.
|
|
194
|
+
|
|
195
|
+
## MongoMindtraceODM
|
|
196
|
+
|
|
197
|
+
Use `MongoMindtraceODM` when you want MongoDB-specific document models and Beanie features.
|
|
198
|
+
|
|
199
|
+
### Mongo document model
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
from typing import Annotated
|
|
203
|
+
|
|
204
|
+
from beanie import Indexed
|
|
205
|
+
|
|
206
|
+
from mindtrace.database import MindtraceDocument
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class MongoUser(MindtraceDocument):
|
|
210
|
+
name: str
|
|
211
|
+
email: Annotated[str, Indexed(unique=True)]
|
|
212
|
+
age: int
|
|
213
|
+
|
|
214
|
+
class Settings:
|
|
215
|
+
name = "users"
|
|
216
|
+
use_cache = False
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Mongo ODM setup
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from mindtrace.database import MongoMindtraceODM
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
db = MongoMindtraceODM(
|
|
226
|
+
model_cls=MongoUser,
|
|
227
|
+
db_uri="mongodb://localhost:27017",
|
|
228
|
+
db_name="myapp",
|
|
229
|
+
)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Async-first behavior
|
|
233
|
+
|
|
234
|
+
MongoDB is natively async in this package.
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
inserted = await db.insert(MongoUser(name="Alice", email="alice@example.com", age=30))
|
|
238
|
+
fetched = await db.get(inserted.id)
|
|
239
|
+
results = await db.find(MongoUser.name == "Alice")
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Sync wrappers
|
|
243
|
+
|
|
244
|
+
```python
|
|
245
|
+
inserted = db.insert_sync(MongoUser(name="Bob", email="bob@example.com", age=25))
|
|
246
|
+
fetched = db.get_sync(inserted.id)
|
|
247
|
+
all_users = db.all_sync()
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Linked documents
|
|
251
|
+
|
|
252
|
+
MongoDB supports Beanie `Link` fields.
|
|
253
|
+
|
|
254
|
+
```python
|
|
255
|
+
from typing import Optional
|
|
256
|
+
|
|
257
|
+
from mindtrace.database import Link, MindtraceDocument, MongoMindtraceODM
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class Address(MindtraceDocument):
|
|
261
|
+
street: str
|
|
262
|
+
city: str
|
|
263
|
+
|
|
264
|
+
class Settings:
|
|
265
|
+
name = "addresses"
|
|
266
|
+
use_cache = False
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
class UserWithAddress(MindtraceDocument):
|
|
270
|
+
name: str
|
|
271
|
+
address: Optional[Link[Address]] = None
|
|
272
|
+
|
|
273
|
+
class Settings:
|
|
274
|
+
name = "users"
|
|
275
|
+
use_cache = False
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
db = MongoMindtraceODM(
|
|
279
|
+
models={"user": UserWithAddress, "address": Address},
|
|
280
|
+
db_uri="mongodb://localhost:27017",
|
|
281
|
+
db_name="myapp",
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
address = await db.address.insert(Address(street="123 Main St", city="NYC"))
|
|
285
|
+
user = await db.user.insert(UserWithAddress(name="Alice", address=address))
|
|
286
|
+
user_with_links = await db.user.get(user.id, fetch_links=True)
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Aggregation
|
|
290
|
+
|
|
291
|
+
```python
|
|
292
|
+
pipeline = [
|
|
293
|
+
{"$match": {"age": {"$gte": 18}}},
|
|
294
|
+
{"$group": {"_id": "$age", "count": {"$sum": 1}}},
|
|
295
|
+
]
|
|
296
|
+
results = await db.aggregate(pipeline)
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## RedisMindtraceODM
|
|
300
|
+
|
|
301
|
+
Use `RedisMindtraceODM` when you want Redis-backed JSON documents and indexed Redis OM queries.
|
|
302
|
+
|
|
303
|
+
### Redis document model
|
|
304
|
+
|
|
305
|
+
```python
|
|
306
|
+
from redis_om import Field
|
|
307
|
+
|
|
308
|
+
from mindtrace.database import MindtraceRedisDocument
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
class RedisUser(MindtraceRedisDocument):
|
|
312
|
+
name: str = Field(index=True)
|
|
313
|
+
email: str = Field(index=True)
|
|
314
|
+
age: int = Field(index=True)
|
|
315
|
+
|
|
316
|
+
class Meta:
|
|
317
|
+
global_key_prefix = "myapp"
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Redis ODM setup
|
|
321
|
+
|
|
322
|
+
```python
|
|
323
|
+
from mindtrace.database import RedisMindtraceODM
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
db = RedisMindtraceODM(
|
|
327
|
+
model_cls=RedisUser,
|
|
328
|
+
redis_url="redis://localhost:6379",
|
|
329
|
+
)
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Sync-first behavior
|
|
333
|
+
|
|
334
|
+
Redis is natively sync in this package.
|
|
335
|
+
|
|
336
|
+
```python
|
|
337
|
+
inserted = db.insert(RedisUser(name="Alice", email="alice@example.com", age=30))
|
|
338
|
+
fetched = db.get(inserted.id)
|
|
339
|
+
results = db.find(RedisUser.age >= 18)
|
|
340
|
+
all_users = db.all()
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Async wrappers
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
inserted = await db.insert_async(RedisUser(name="Bob", email="bob@example.com", age=25))
|
|
347
|
+
fetched = await db.get_async(inserted.id)
|
|
348
|
+
all_users = await db.all_async()
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Notes on Redis IDs
|
|
352
|
+
|
|
353
|
+
Redis OM uses `pk` internally, but `MindtraceRedisDocument` exposes a consistent `id` property so code can treat MongoDB and Redis documents more similarly.
|
|
354
|
+
|
|
355
|
+
## RegistryMindtraceODM
|
|
356
|
+
|
|
357
|
+
Use `RegistryMindtraceODM` when you want a simpler registry-backed ODM using Mindtrace’s Registry layer instead of a database server.
|
|
358
|
+
|
|
359
|
+
```python
|
|
360
|
+
from pydantic import BaseModel
|
|
361
|
+
|
|
362
|
+
from mindtrace.database import RegistryMindtraceODM
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
class User(BaseModel):
|
|
366
|
+
name: str
|
|
367
|
+
email: str
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
db = RegistryMindtraceODM(model_cls=User)
|
|
371
|
+
inserted = db.insert(User(name="John Doe", email="john@example.com"))
|
|
372
|
+
retrieved = db.get(inserted.id)
|
|
373
|
+
retrieved.name = "John Smith"
|
|
374
|
+
updated = db.update(retrieved)
|
|
375
|
+
all_users = db.all()
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
This backend is useful when you want the ODM interface but prefer Registry-backed storage semantics.
|
|
379
|
+
|
|
380
|
+
## Sync and Async Interfaces
|
|
381
|
+
|
|
382
|
+
All ODMs expose the same broad CRUD shape, but their native execution mode differs.
|
|
383
|
+
|
|
384
|
+
- **MongoMindtraceODM** — native async, with sync wrappers
|
|
385
|
+
- **RedisMindtraceODM** — native sync, with async wrappers
|
|
386
|
+
- **UnifiedMindtraceODM** — routes to the active backend and adapts accordingly
|
|
387
|
+
- **RegistryMindtraceODM** — sync-oriented
|
|
388
|
+
|
|
389
|
+
That means you can often keep the same mental model while fitting your application’s execution style.
|
|
390
|
+
|
|
391
|
+
## Initialization
|
|
392
|
+
|
|
393
|
+
ODMs support automatic or explicit initialization.
|
|
394
|
+
|
|
395
|
+
```python
|
|
396
|
+
from mindtrace.database import BackendType, InitMode, UnifiedMindtraceDocument, UnifiedMindtraceODM
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
db = UnifiedMindtraceODM(
|
|
400
|
+
unified_model_cls=User,
|
|
401
|
+
mongo_db_uri="mongodb://localhost:27017",
|
|
402
|
+
mongo_db_name="myapp",
|
|
403
|
+
redis_url="redis://localhost:6379",
|
|
404
|
+
preferred_backend=BackendType.MONGO,
|
|
405
|
+
auto_init=True,
|
|
406
|
+
init_mode=InitMode.SYNC,
|
|
407
|
+
)
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Init modes
|
|
411
|
+
|
|
412
|
+
- `InitMode.SYNC`
|
|
413
|
+
- `InitMode.ASYNC`
|
|
414
|
+
|
|
415
|
+
Defaults differ by backend:
|
|
416
|
+
|
|
417
|
+
- MongoDB defaults to `ASYNC`
|
|
418
|
+
- Redis defaults to `SYNC`
|
|
419
|
+
- Registry is sync-oriented
|
|
420
|
+
|
|
421
|
+
## Error Handling
|
|
422
|
+
|
|
423
|
+
The package provides a consistent exception surface across backends.
|
|
424
|
+
|
|
425
|
+
```python
|
|
426
|
+
from mindtrace.database import DocumentNotFoundError, DuplicateInsertError
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
try:
|
|
430
|
+
user = await db.get_async("missing-id")
|
|
431
|
+
except DocumentNotFoundError as e:
|
|
432
|
+
print(f"Not found: {e}")
|
|
433
|
+
|
|
434
|
+
try:
|
|
435
|
+
await db.insert_async(User(name="Alice", email="alice@example.com", age=30))
|
|
436
|
+
except DuplicateInsertError as e:
|
|
437
|
+
print(f"Duplicate insert: {e}")
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
In multi-model mode, calling direct methods like `db.insert(...)` instead of `db.user.insert(...)` raises a `ValueError` to prevent ambiguity.
|
|
441
|
+
|
|
442
|
+
## Installation
|
|
443
|
+
|
|
444
|
+
If you are working from the full Mindtrace repo:
|
|
445
|
+
|
|
446
|
+
```bash
|
|
447
|
+
$ git clone https://github.com/Mindtrace/mindtrace.git && cd mindtrace
|
|
448
|
+
$ uv sync --dev --all-extras
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
The database package depends on backend libraries such as Beanie, Motor, PyMongo, and Redis OM.
|
|
452
|
+
|
|
453
|
+
## Examples
|
|
454
|
+
|
|
455
|
+
Related examples in the repo:
|
|
456
|
+
|
|
457
|
+
- [Unified ODM example](../../samples/database/unified_example.py)
|
|
458
|
+
- [MongoDB example](../../samples/database/mongo_example.py)
|
|
459
|
+
- [Redis example](../../samples/database/redis_example.py)
|
|
460
|
+
- [Registry example](../../samples/database/registry_example.py)
|
|
461
|
+
- [Database samples README](../../samples/database/README.md)
|
|
462
|
+
|
|
463
|
+
## Testing
|
|
464
|
+
|
|
465
|
+
If you are working in the full Mindtrace repo, run tests for this module specifically:
|
|
466
|
+
|
|
467
|
+
```bash
|
|
468
|
+
$ git clone https://github.com/Mindtrace/mindtrace.git && cd mindtrace
|
|
469
|
+
$ uv sync --dev --all-extras
|
|
470
|
+
$ ds test: database
|
|
471
|
+
$ ds test: --unit database
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
If you want backend-specific integration coverage as well:
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
$ ds test: database --integration
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## Practical Notes and Caveats
|
|
481
|
+
|
|
482
|
+
- `UnifiedMindtraceODM` only exposes the overlap of capabilities that make sense across MongoDB and Redis; backend-specific features still live on the backend-specific ODMs.
|
|
483
|
+
- Multi-model mode changes the calling style: use attribute-based access like `db.user.get(...)`.
|
|
484
|
+
- MongoDB supports linked documents and aggregation; Redis does not provide the same feature set.
|
|
485
|
+
- Redis and MongoDB differ in native execution style, so some methods are wrappers around the backend’s natural sync/async mode.
|
|
486
|
+
- `RegistryMindtraceODM` is useful for simpler or storage-backed workflows, but its query capabilities are intentionally simpler than MongoDB or Redis.
|