mdb-engine 0.1.6__py3-none-any.whl
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.
- mdb_engine/README.md +144 -0
- mdb_engine/__init__.py +37 -0
- mdb_engine/auth/README.md +631 -0
- mdb_engine/auth/__init__.py +128 -0
- mdb_engine/auth/casbin_factory.py +199 -0
- mdb_engine/auth/casbin_models.py +46 -0
- mdb_engine/auth/config_defaults.py +71 -0
- mdb_engine/auth/config_helpers.py +213 -0
- mdb_engine/auth/cookie_utils.py +158 -0
- mdb_engine/auth/decorators.py +350 -0
- mdb_engine/auth/dependencies.py +747 -0
- mdb_engine/auth/helpers.py +64 -0
- mdb_engine/auth/integration.py +578 -0
- mdb_engine/auth/jwt.py +225 -0
- mdb_engine/auth/middleware.py +241 -0
- mdb_engine/auth/oso_factory.py +323 -0
- mdb_engine/auth/provider.py +570 -0
- mdb_engine/auth/restrictions.py +271 -0
- mdb_engine/auth/session_manager.py +477 -0
- mdb_engine/auth/token_lifecycle.py +213 -0
- mdb_engine/auth/token_store.py +289 -0
- mdb_engine/auth/users.py +1516 -0
- mdb_engine/auth/utils.py +614 -0
- mdb_engine/cli/__init__.py +13 -0
- mdb_engine/cli/commands/__init__.py +7 -0
- mdb_engine/cli/commands/generate.py +105 -0
- mdb_engine/cli/commands/migrate.py +83 -0
- mdb_engine/cli/commands/show.py +70 -0
- mdb_engine/cli/commands/validate.py +63 -0
- mdb_engine/cli/main.py +41 -0
- mdb_engine/cli/utils.py +92 -0
- mdb_engine/config.py +217 -0
- mdb_engine/constants.py +160 -0
- mdb_engine/core/README.md +542 -0
- mdb_engine/core/__init__.py +42 -0
- mdb_engine/core/app_registration.py +392 -0
- mdb_engine/core/connection.py +243 -0
- mdb_engine/core/engine.py +749 -0
- mdb_engine/core/index_management.py +162 -0
- mdb_engine/core/manifest.py +2793 -0
- mdb_engine/core/seeding.py +179 -0
- mdb_engine/core/service_initialization.py +355 -0
- mdb_engine/core/types.py +413 -0
- mdb_engine/database/README.md +522 -0
- mdb_engine/database/__init__.py +31 -0
- mdb_engine/database/abstraction.py +635 -0
- mdb_engine/database/connection.py +387 -0
- mdb_engine/database/scoped_wrapper.py +1721 -0
- mdb_engine/embeddings/README.md +184 -0
- mdb_engine/embeddings/__init__.py +62 -0
- mdb_engine/embeddings/dependencies.py +193 -0
- mdb_engine/embeddings/service.py +759 -0
- mdb_engine/exceptions.py +167 -0
- mdb_engine/indexes/README.md +651 -0
- mdb_engine/indexes/__init__.py +21 -0
- mdb_engine/indexes/helpers.py +145 -0
- mdb_engine/indexes/manager.py +895 -0
- mdb_engine/memory/README.md +451 -0
- mdb_engine/memory/__init__.py +30 -0
- mdb_engine/memory/service.py +1285 -0
- mdb_engine/observability/README.md +515 -0
- mdb_engine/observability/__init__.py +42 -0
- mdb_engine/observability/health.py +296 -0
- mdb_engine/observability/logging.py +161 -0
- mdb_engine/observability/metrics.py +297 -0
- mdb_engine/routing/README.md +462 -0
- mdb_engine/routing/__init__.py +73 -0
- mdb_engine/routing/websockets.py +813 -0
- mdb_engine/utils/__init__.py +7 -0
- mdb_engine-0.1.6.dist-info/METADATA +213 -0
- mdb_engine-0.1.6.dist-info/RECORD +75 -0
- mdb_engine-0.1.6.dist-info/WHEEL +5 -0
- mdb_engine-0.1.6.dist-info/entry_points.txt +2 -0
- mdb_engine-0.1.6.dist-info/licenses/LICENSE +661 -0
- mdb_engine-0.1.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,651 @@
|
|
|
1
|
+
# Index Management Module
|
|
2
|
+
|
|
3
|
+
High-level index creation and management orchestration for MDB_ENGINE applications. Supports all MongoDB index types including regular, TTL, partial, text, geospatial, vector search, and Atlas Search indexes.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Index Orchestration**: High-level functions for creating indexes from manifest definitions
|
|
8
|
+
- **All Index Types**: Support for regular, TTL, partial, text, geospatial, vector, search, and hybrid indexes
|
|
9
|
+
- **Index Validation**: Built-in validation for index definitions
|
|
10
|
+
- **Helper Functions**: Utilities for key normalization and index comparison
|
|
11
|
+
- **Manifest Integration**: Seamless integration with manifest.json index definitions
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
The indexes module is part of MDB_ENGINE. No additional installation required.
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### Basic Usage
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from mdb_engine.indexes import run_index_creation_for_collection
|
|
23
|
+
from motor.motor_asyncio import AsyncIOMotorDatabase
|
|
24
|
+
|
|
25
|
+
# Define indexes in manifest or programmatically
|
|
26
|
+
index_definitions = [
|
|
27
|
+
{
|
|
28
|
+
"name": "email_idx",
|
|
29
|
+
"type": "regular",
|
|
30
|
+
"keys": {"email": 1},
|
|
31
|
+
"unique": True
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "status_created_idx",
|
|
35
|
+
"type": "regular",
|
|
36
|
+
"keys": {"status": 1, "created_at": -1}
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
# Create indexes for a collection
|
|
41
|
+
await run_index_creation_for_collection(
|
|
42
|
+
db=db,
|
|
43
|
+
slug="my_app",
|
|
44
|
+
collection_name="users",
|
|
45
|
+
index_definitions=index_definitions
|
|
46
|
+
)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Index Types
|
|
50
|
+
|
|
51
|
+
### Regular Indexes
|
|
52
|
+
|
|
53
|
+
Standard MongoDB indexes for efficient queries:
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
index_definitions = [
|
|
57
|
+
{
|
|
58
|
+
"name": "email_idx",
|
|
59
|
+
"type": "regular",
|
|
60
|
+
"keys": {"email": 1},
|
|
61
|
+
"options": {
|
|
62
|
+
"unique": True,
|
|
63
|
+
"sparse": False
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "compound_idx",
|
|
68
|
+
"type": "regular",
|
|
69
|
+
"keys": {"status": 1, "created_at": -1, "priority": 1}
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### TTL Indexes
|
|
75
|
+
|
|
76
|
+
Time-to-live indexes that automatically expire documents:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
index_definitions = [
|
|
80
|
+
{
|
|
81
|
+
"name": "expire_sessions",
|
|
82
|
+
"type": "ttl",
|
|
83
|
+
"keys": {"last_activity": 1},
|
|
84
|
+
"options": {
|
|
85
|
+
"expireAfterSeconds": 3600 # Expire after 1 hour
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Note**: `expireAfterSeconds` must be at least 1 second and is required for TTL indexes.
|
|
92
|
+
|
|
93
|
+
### Partial Indexes
|
|
94
|
+
|
|
95
|
+
Indexes that only index documents matching a filter expression:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
index_definitions = [
|
|
99
|
+
{
|
|
100
|
+
"name": "active_users_idx",
|
|
101
|
+
"type": "partial",
|
|
102
|
+
"keys": {"email": 1},
|
|
103
|
+
"options": {
|
|
104
|
+
"partialFilterExpression": {
|
|
105
|
+
"status": "active"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Text Indexes
|
|
113
|
+
|
|
114
|
+
Full-text search indexes:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
index_definitions = [
|
|
118
|
+
{
|
|
119
|
+
"name": "text_search",
|
|
120
|
+
"type": "text",
|
|
121
|
+
"keys": [
|
|
122
|
+
("title", "text"),
|
|
123
|
+
("content", "text"),
|
|
124
|
+
("tags", "text")
|
|
125
|
+
],
|
|
126
|
+
"options": {
|
|
127
|
+
"default_language": "english",
|
|
128
|
+
"weights": {
|
|
129
|
+
"title": 10,
|
|
130
|
+
"content": 5,
|
|
131
|
+
"tags": 2
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Geospatial Indexes
|
|
139
|
+
|
|
140
|
+
Indexes for geospatial queries (2dsphere, 2d, geoHaystack):
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
index_definitions = [
|
|
144
|
+
{
|
|
145
|
+
"name": "location_idx",
|
|
146
|
+
"type": "geospatial",
|
|
147
|
+
"keys": {"location": "2dsphere"}
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"name": "coordinates_idx",
|
|
151
|
+
"type": "geospatial",
|
|
152
|
+
"keys": {"coordinates": "2d"}
|
|
153
|
+
}
|
|
154
|
+
]
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Vector Search Indexes
|
|
158
|
+
|
|
159
|
+
Atlas Vector Search indexes for semantic search:
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
index_definitions = [
|
|
163
|
+
{
|
|
164
|
+
"name": "vector_search",
|
|
165
|
+
"type": "vector_search",
|
|
166
|
+
"definition": {
|
|
167
|
+
"fields": [{
|
|
168
|
+
"type": "vector",
|
|
169
|
+
"path": "embedding",
|
|
170
|
+
"numDimensions": 1536,
|
|
171
|
+
"similarity": "cosine"
|
|
172
|
+
}]
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
]
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Atlas Search Indexes
|
|
179
|
+
|
|
180
|
+
Lucene-based full-text search indexes:
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
index_definitions = [
|
|
184
|
+
{
|
|
185
|
+
"name": "atlas_search",
|
|
186
|
+
"type": "search",
|
|
187
|
+
"definition": {
|
|
188
|
+
"mappings": {
|
|
189
|
+
"dynamic": False,
|
|
190
|
+
"fields": {
|
|
191
|
+
"title": {
|
|
192
|
+
"type": "string",
|
|
193
|
+
"analyzer": "lucene.standard"
|
|
194
|
+
},
|
|
195
|
+
"content": {
|
|
196
|
+
"type": "string",
|
|
197
|
+
"analyzer": "lucene.english"
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Hybrid Indexes
|
|
207
|
+
|
|
208
|
+
Combines vector and keyword search:
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
index_definitions = [
|
|
212
|
+
{
|
|
213
|
+
"name": "hybrid_search",
|
|
214
|
+
"type": "hybrid",
|
|
215
|
+
"definition": {
|
|
216
|
+
"fields": [{
|
|
217
|
+
"type": "vector",
|
|
218
|
+
"path": "embedding",
|
|
219
|
+
"numDimensions": 1536
|
|
220
|
+
}],
|
|
221
|
+
"mappings": {
|
|
222
|
+
"dynamic": False,
|
|
223
|
+
"fields": {
|
|
224
|
+
"title": {"type": "string"}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
]
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Manifest Integration
|
|
233
|
+
|
|
234
|
+
Define indexes in your `manifest.json`:
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"slug": "my_app",
|
|
239
|
+
"collections": {
|
|
240
|
+
"users": {
|
|
241
|
+
"indexes": [
|
|
242
|
+
{
|
|
243
|
+
"name": "email_idx",
|
|
244
|
+
"type": "regular",
|
|
245
|
+
"keys": {"email": 1},
|
|
246
|
+
"unique": true
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"name": "expire_sessions",
|
|
250
|
+
"type": "ttl",
|
|
251
|
+
"keys": {"last_activity": 1},
|
|
252
|
+
"options": {
|
|
253
|
+
"expireAfterSeconds": 3600
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"name": "vector_search",
|
|
258
|
+
"type": "vector_search",
|
|
259
|
+
"definition": {
|
|
260
|
+
"fields": [{
|
|
261
|
+
"type": "vector",
|
|
262
|
+
"path": "embedding",
|
|
263
|
+
"numDimensions": 1536,
|
|
264
|
+
"similarity": "cosine"
|
|
265
|
+
}]
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Indexes are automatically created when you register the app:
|
|
275
|
+
|
|
276
|
+
```python
|
|
277
|
+
from mdb_engine import MongoDBEngine
|
|
278
|
+
|
|
279
|
+
engine = MongoDBEngine(mongo_uri="...", db_name="...")
|
|
280
|
+
await engine.initialize()
|
|
281
|
+
|
|
282
|
+
manifest = await engine.load_manifest("manifest.json")
|
|
283
|
+
await engine.register_app(manifest) # Indexes created automatically
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Helper Functions
|
|
287
|
+
|
|
288
|
+
### Key Normalization
|
|
289
|
+
|
|
290
|
+
Normalize index keys to consistent format:
|
|
291
|
+
|
|
292
|
+
```python
|
|
293
|
+
from mdb_engine.indexes.helpers import normalize_keys, keys_to_dict
|
|
294
|
+
|
|
295
|
+
# Normalize dict to list of tuples
|
|
296
|
+
keys_dict = {"email": 1, "name": -1}
|
|
297
|
+
keys_list = normalize_keys(keys_dict)
|
|
298
|
+
# Returns: [("email", 1), ("name", -1)]
|
|
299
|
+
|
|
300
|
+
# Convert list to dict
|
|
301
|
+
keys_dict = keys_to_dict(keys_list)
|
|
302
|
+
# Returns: {"email": 1, "name": -1}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Index Validation
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
from mdb_engine.indexes.helpers import (
|
|
309
|
+
is_id_index,
|
|
310
|
+
validate_index_definition_basic,
|
|
311
|
+
check_and_update_index
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
# Check if index is _id index (MongoDB creates these automatically)
|
|
315
|
+
is_id = is_id_index({"_id": 1}) # Returns True
|
|
316
|
+
|
|
317
|
+
# Validate index definition
|
|
318
|
+
is_valid, error_msg = validate_index_definition_basic(
|
|
319
|
+
index_def={"name": "test", "keys": {"email": 1}},
|
|
320
|
+
index_name="test",
|
|
321
|
+
required_fields=["keys"],
|
|
322
|
+
log_prefix="[my_app]"
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
# Check if index exists and matches
|
|
326
|
+
exists, existing = await check_and_update_index(
|
|
327
|
+
index_manager=index_manager,
|
|
328
|
+
index_name="email_idx",
|
|
329
|
+
expected_keys={"email": 1},
|
|
330
|
+
expected_options={"unique": True}
|
|
331
|
+
)
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## API Reference
|
|
335
|
+
|
|
336
|
+
### `run_index_creation_for_collection`
|
|
337
|
+
|
|
338
|
+
Main function for creating indexes from definitions:
|
|
339
|
+
|
|
340
|
+
```python
|
|
341
|
+
await run_index_creation_for_collection(
|
|
342
|
+
db: AsyncIOMotorDatabase,
|
|
343
|
+
slug: str,
|
|
344
|
+
collection_name: str,
|
|
345
|
+
index_definitions: List[Dict[str, Any]]
|
|
346
|
+
)
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
**Parameters:**
|
|
350
|
+
- `db`: MongoDB database instance
|
|
351
|
+
- `slug`: App slug (for logging)
|
|
352
|
+
- `collection_name`: Name of the collection
|
|
353
|
+
- `index_definitions`: List of index definition dictionaries
|
|
354
|
+
|
|
355
|
+
**Index Definition Format:**
|
|
356
|
+
|
|
357
|
+
```python
|
|
358
|
+
{
|
|
359
|
+
"name": str, # Index name (required)
|
|
360
|
+
"type": str, # Index type (required)
|
|
361
|
+
"keys": dict | list, # Index keys (required for most types)
|
|
362
|
+
"options": dict, # Index options (optional)
|
|
363
|
+
"definition": dict # Full definition (for vector/search indexes)
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Helper Functions
|
|
368
|
+
|
|
369
|
+
#### `normalize_keys(keys)`
|
|
370
|
+
|
|
371
|
+
Normalize index keys to list of tuples format.
|
|
372
|
+
|
|
373
|
+
**Parameters:**
|
|
374
|
+
- `keys`: Dict or list of tuples
|
|
375
|
+
|
|
376
|
+
**Returns:** List of (field_name, direction) tuples
|
|
377
|
+
|
|
378
|
+
#### `keys_to_dict(keys)`
|
|
379
|
+
|
|
380
|
+
Convert index keys to dictionary format.
|
|
381
|
+
|
|
382
|
+
**Parameters:**
|
|
383
|
+
- `keys`: Dict or list of tuples
|
|
384
|
+
|
|
385
|
+
**Returns:** Dictionary representation
|
|
386
|
+
|
|
387
|
+
#### `is_id_index(keys)`
|
|
388
|
+
|
|
389
|
+
Check if index keys target the `_id` field.
|
|
390
|
+
|
|
391
|
+
**Parameters:**
|
|
392
|
+
- `keys`: Index keys to check
|
|
393
|
+
|
|
394
|
+
**Returns:** True if this is an `_id` index
|
|
395
|
+
|
|
396
|
+
#### `check_and_update_index(index_manager, index_name, expected_keys, expected_options=None)`
|
|
397
|
+
|
|
398
|
+
Check if index exists and matches expected definition.
|
|
399
|
+
|
|
400
|
+
**Parameters:**
|
|
401
|
+
- `index_manager`: AsyncAtlasIndexManager instance
|
|
402
|
+
- `index_name`: Name of the index
|
|
403
|
+
- `expected_keys`: Expected index keys
|
|
404
|
+
- `expected_options`: Expected index options
|
|
405
|
+
|
|
406
|
+
**Returns:** Tuple of (index_exists, existing_index_dict or None)
|
|
407
|
+
|
|
408
|
+
#### `validate_index_definition_basic(index_def, index_name, required_fields, log_prefix="")`
|
|
409
|
+
|
|
410
|
+
Validate basic index definition structure.
|
|
411
|
+
|
|
412
|
+
**Parameters:**
|
|
413
|
+
- `index_def`: Index definition dictionary
|
|
414
|
+
- `index_name`: Name of the index
|
|
415
|
+
- `required_fields`: List of required field names
|
|
416
|
+
- `log_prefix`: Logging prefix
|
|
417
|
+
|
|
418
|
+
**Returns:** Tuple of (is_valid, error_message)
|
|
419
|
+
|
|
420
|
+
## Index Definition Examples
|
|
421
|
+
|
|
422
|
+
### Compound Index
|
|
423
|
+
|
|
424
|
+
```python
|
|
425
|
+
{
|
|
426
|
+
"name": "user_status_created",
|
|
427
|
+
"type": "regular",
|
|
428
|
+
"keys": {
|
|
429
|
+
"user_id": 1,
|
|
430
|
+
"status": 1,
|
|
431
|
+
"created_at": -1
|
|
432
|
+
},
|
|
433
|
+
"options": {
|
|
434
|
+
"background": True
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### Unique Index with Sparse
|
|
440
|
+
|
|
441
|
+
```python
|
|
442
|
+
{
|
|
443
|
+
"name": "username_unique",
|
|
444
|
+
"type": "regular",
|
|
445
|
+
"keys": {"username": 1},
|
|
446
|
+
"options": {
|
|
447
|
+
"unique": True,
|
|
448
|
+
"sparse": True # Only index documents with username field
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### TTL Index with Minimum Expiry
|
|
454
|
+
|
|
455
|
+
```python
|
|
456
|
+
{
|
|
457
|
+
"name": "session_expiry",
|
|
458
|
+
"type": "ttl",
|
|
459
|
+
"keys": {"last_seen": 1},
|
|
460
|
+
"options": {
|
|
461
|
+
"expireAfterSeconds": 86400 # 24 hours (minimum: 1 second)
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### Partial Index for Active Documents
|
|
467
|
+
|
|
468
|
+
```python
|
|
469
|
+
{
|
|
470
|
+
"name": "active_docs_idx",
|
|
471
|
+
"type": "partial",
|
|
472
|
+
"keys": {"title": 1, "updated_at": -1},
|
|
473
|
+
"options": {
|
|
474
|
+
"partialFilterExpression": {
|
|
475
|
+
"status": {"$in": ["active", "published"]},
|
|
476
|
+
"deleted": False
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### Multi-Field Text Index
|
|
483
|
+
|
|
484
|
+
```python
|
|
485
|
+
{
|
|
486
|
+
"name": "full_text_search",
|
|
487
|
+
"type": "text",
|
|
488
|
+
"keys": [
|
|
489
|
+
("title", "text"),
|
|
490
|
+
("description", "text"),
|
|
491
|
+
("tags", "text")
|
|
492
|
+
],
|
|
493
|
+
"options": {
|
|
494
|
+
"default_language": "english",
|
|
495
|
+
"weights": {
|
|
496
|
+
"title": 10,
|
|
497
|
+
"description": 5,
|
|
498
|
+
"tags": 2
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### Vector Search Index
|
|
505
|
+
|
|
506
|
+
```python
|
|
507
|
+
{
|
|
508
|
+
"name": "embeddings_vector",
|
|
509
|
+
"type": "vector_search",
|
|
510
|
+
"definition": {
|
|
511
|
+
"fields": [{
|
|
512
|
+
"type": "vector",
|
|
513
|
+
"path": "embedding",
|
|
514
|
+
"numDimensions": 1536,
|
|
515
|
+
"similarity": "cosine"
|
|
516
|
+
}]
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### Atlas Search Index
|
|
522
|
+
|
|
523
|
+
```python
|
|
524
|
+
{
|
|
525
|
+
"name": "atlas_fulltext",
|
|
526
|
+
"type": "search",
|
|
527
|
+
"definition": {
|
|
528
|
+
"mappings": {
|
|
529
|
+
"dynamic": False,
|
|
530
|
+
"fields": {
|
|
531
|
+
"title": {
|
|
532
|
+
"type": "string",
|
|
533
|
+
"analyzer": "lucene.standard"
|
|
534
|
+
},
|
|
535
|
+
"content": {
|
|
536
|
+
"type": "string",
|
|
537
|
+
"analyzer": "lucene.english"
|
|
538
|
+
},
|
|
539
|
+
"tags": {
|
|
540
|
+
"type": "stringFacet"
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
## Best Practices
|
|
549
|
+
|
|
550
|
+
1. **Name indexes descriptively** - Use clear, descriptive names (e.g., `user_email_unique_idx`)
|
|
551
|
+
2. **Define indexes in manifest** - Centralize index definitions in manifest.json
|
|
552
|
+
3. **Use compound indexes wisely** - Order fields by selectivity (most selective first)
|
|
553
|
+
4. **Consider partial indexes** - Use partial indexes to reduce index size
|
|
554
|
+
5. **Set TTL appropriately** - Use TTL indexes for time-based data expiration
|
|
555
|
+
6. **Validate definitions** - Use validation functions before creating indexes
|
|
556
|
+
7. **Monitor index creation** - Check logs for index creation status
|
|
557
|
+
8. **Use background creation** - Set `background: True` for large collections
|
|
558
|
+
9. **Test index performance** - Verify indexes improve query performance
|
|
559
|
+
10. **Document index purpose** - Add comments explaining why each index exists
|
|
560
|
+
|
|
561
|
+
## Error Handling
|
|
562
|
+
|
|
563
|
+
```python
|
|
564
|
+
from mdb_engine.indexes import run_index_creation_for_collection
|
|
565
|
+
import logging
|
|
566
|
+
|
|
567
|
+
logger = logging.getLogger(__name__)
|
|
568
|
+
|
|
569
|
+
try:
|
|
570
|
+
await run_index_creation_for_collection(
|
|
571
|
+
db=db,
|
|
572
|
+
slug="my_app",
|
|
573
|
+
collection_name="users",
|
|
574
|
+
index_definitions=index_definitions
|
|
575
|
+
)
|
|
576
|
+
except Exception as e:
|
|
577
|
+
logger.error(f"Failed to create indexes: {e}", exc_info=True)
|
|
578
|
+
raise
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
## Integration Examples
|
|
582
|
+
|
|
583
|
+
### MongoDBEngine Integration
|
|
584
|
+
|
|
585
|
+
Indexes are automatically created when registering apps:
|
|
586
|
+
|
|
587
|
+
```python
|
|
588
|
+
from mdb_engine import MongoDBEngine
|
|
589
|
+
|
|
590
|
+
engine = MongoDBEngine(mongo_uri="...", db_name="...")
|
|
591
|
+
await engine.initialize()
|
|
592
|
+
|
|
593
|
+
# Load manifest with index definitions
|
|
594
|
+
manifest = await engine.load_manifest("manifest.json")
|
|
595
|
+
|
|
596
|
+
# Register app (indexes created automatically)
|
|
597
|
+
await engine.register_app(manifest)
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### Manual Index Creation
|
|
601
|
+
|
|
602
|
+
Create indexes programmatically:
|
|
603
|
+
|
|
604
|
+
```python
|
|
605
|
+
from mdb_engine.indexes import run_index_creation_for_collection
|
|
606
|
+
|
|
607
|
+
index_definitions = [
|
|
608
|
+
{
|
|
609
|
+
"name": "email_idx",
|
|
610
|
+
"type": "regular",
|
|
611
|
+
"keys": {"email": 1},
|
|
612
|
+
"unique": True
|
|
613
|
+
}
|
|
614
|
+
]
|
|
615
|
+
|
|
616
|
+
await run_index_creation_for_collection(
|
|
617
|
+
db=engine.mongo_db,
|
|
618
|
+
slug="my_app",
|
|
619
|
+
collection_name="users",
|
|
620
|
+
index_definitions=index_definitions
|
|
621
|
+
)
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
### Multiple Collections
|
|
625
|
+
|
|
626
|
+
Create indexes for multiple collections:
|
|
627
|
+
|
|
628
|
+
```python
|
|
629
|
+
collections_with_indexes = {
|
|
630
|
+
"users": [
|
|
631
|
+
{"name": "email_idx", "type": "regular", "keys": {"email": 1}, "unique": True}
|
|
632
|
+
],
|
|
633
|
+
"documents": [
|
|
634
|
+
{"name": "vector_idx", "type": "vector_search", "definition": {...}}
|
|
635
|
+
]
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
for collection_name, index_definitions in collections_with_indexes.items():
|
|
639
|
+
await run_index_creation_for_collection(
|
|
640
|
+
db=engine.mongo_db,
|
|
641
|
+
slug="my_app",
|
|
642
|
+
collection_name=collection_name,
|
|
643
|
+
index_definitions=index_definitions
|
|
644
|
+
)
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
## Related Modules
|
|
648
|
+
|
|
649
|
+
- **`database/`** - AsyncAtlasIndexManager for Atlas indexes
|
|
650
|
+
- **`core/`** - Manifest system and MongoDBEngine
|
|
651
|
+
- **`observability/`** - Logging for index operations
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Index Management Module
|
|
3
|
+
|
|
4
|
+
Provides index management utilities for MongoDB Atlas Search and regular indexes.
|
|
5
|
+
|
|
6
|
+
This module is part of MDB_ENGINE - MongoDB Engine.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# Re-export index managers from database module for convenience
|
|
10
|
+
from ..database.scoped_wrapper import AsyncAtlasIndexManager, AutoIndexManager
|
|
11
|
+
# Export high-level management functions
|
|
12
|
+
from .manager import normalize_json_def, run_index_creation_for_collection
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
# Index managers
|
|
16
|
+
"AsyncAtlasIndexManager",
|
|
17
|
+
"AutoIndexManager",
|
|
18
|
+
# Management functions
|
|
19
|
+
"normalize_json_def",
|
|
20
|
+
"run_index_creation_for_collection",
|
|
21
|
+
]
|