mongo-entity-orm 0.1.1__tar.gz → 0.1.3__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.
@@ -0,0 +1,261 @@
1
+ Metadata-Version: 2.3
2
+ Name: mongo-entity-orm
3
+ Version: 0.1.3
4
+ Summary: A MongoDB ORM for Python
5
+ License: MIT
6
+ Keywords: mongodb,orm,mongo,async
7
+ Author: Juraj Bezdek
8
+ Author-email: juraj.bezdek@gmail.com
9
+ Requires-Python: >=3.9,<4.0
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Requires-Dist: motor (>=3.7.1,<4.0.0)
20
+ Requires-Dist: pymongo (>=4.13.2,<5.0.0)
21
+ Project-URL: Documentation, https://github.com/ju-bezdek/mongo-orm#readme
22
+ Project-URL: Homepage, https://github.com/ju-bezdek/mongo-orm
23
+ Project-URL: Repository, https://github.com/ju-bezdek/mongo-orm
24
+ Description-Content-Type: text/markdown
25
+
26
+ # mongo-orm
27
+
28
+ A MongoDB ORM for Python
29
+
30
+ ## Installation
31
+
32
+ ```
33
+ pip install mongo-entity-orm
34
+ ```
35
+
36
+ or
37
+
38
+ ```
39
+ uv add mongo-entity-orm
40
+ ```
41
+
42
+ ## Configuration
43
+
44
+ Set the following environment variables before using the ORM:
45
+
46
+ | Variable | Description |
47
+ |---|---|
48
+ | `MONGODB_URI` | MongoDB connection string |
49
+ | `MONGO_DATABASE_NAME` | Name of the database |
50
+
51
+ ## Usage
52
+
53
+ ### Defining an Entity
54
+
55
+ Use the `@entity` decorator to map a class to a MongoDB collection. Your class should inherit from `BaseEntity`.
56
+
57
+ ```python
58
+ from mongo_orm import BaseEntity, entity
59
+
60
+ @entity(collection_name="users")
61
+ class User(BaseEntity):
62
+ name: str
63
+ email: str
64
+ ```
65
+
66
+ Every entity automatically has an `id` field (UUID string) and a `tenant_id` field (defaults to `"-"`).
67
+
68
+ ### CRUD Operations
69
+
70
+ All operations are available in both async (`a`-prefixed) and sync variants.
71
+
72
+ #### Get by ID
73
+
74
+ ```python
75
+ # async
76
+ user = await User.aget(id=user_id, tenant_id=tenant_id)
77
+
78
+ # sync
79
+ user = User.get(id=user_id, tenant_id=tenant_id)
80
+ ```
81
+
82
+ Pass `raise_not_found=True` to raise an exception instead of returning `None` when the entity is not found.
83
+
84
+ #### Save
85
+
86
+ ```python
87
+ user = User(name="Alice", email="alice@example.com", tenant_id="acme")
88
+
89
+ # async
90
+ await user.asave()
91
+
92
+ # sync
93
+ user.save()
94
+ ```
95
+
96
+ `save()` / `asave()` performs an upsert based on `id`, so it works for both creating and updating.
97
+
98
+ #### Update fields
99
+
100
+ ```python
101
+ # Update in-memory only
102
+ user.update(name="Bob")
103
+
104
+ # Update and immediately save (async)
105
+ await user.aupdate(name="Bob", auto_save=True)
106
+
107
+ # Update and immediately save (sync)
108
+ user.update(name="Bob", auto_save=True)
109
+ ```
110
+
111
+ #### Delete
112
+
113
+ ```python
114
+ # Delete an entity instance
115
+ user.delete()
116
+
117
+ # Delete by ID
118
+ User.delete_by_id(id=user_id, tenant_id=tenant_id)
119
+ ```
120
+
121
+ Pass `ignore_not_found=True` to suppress an exception when the entity does not exist.
122
+
123
+ ### Querying
124
+
125
+ #### Find (filter)
126
+
127
+ `filter` accepts a standard MongoDB query dict.
128
+
129
+ ```python
130
+ # async
131
+ users = await User.afind(tenant_id=tenant_id, filter={"name": "Alice"})
132
+
133
+ # sync
134
+ users = User.find(tenant_id=tenant_id, filter={"name": "Alice"})
135
+ ```
136
+
137
+ MongoDB operators work as expected:
138
+
139
+ ```python
140
+ users = await User.afind(
141
+ tenant_id=tenant_id,
142
+ filter={"name": {"$in": ["Alice", "Bob"]}, "email": {"$regex": "@example.com$"}},
143
+ )
144
+ ```
145
+
146
+ Use `tenant_id="*"` to query across all tenants.
147
+
148
+ #### Pagination
149
+
150
+ ```python
151
+ users = await User.afind(tenant_id=tenant_id, filter={}, skip=0, limit=20)
152
+ ```
153
+
154
+ #### Sorting
155
+
156
+ ```python
157
+ # Ascending
158
+ users = await User.afind(tenant_id=tenant_id, order_by="name")
159
+
160
+ # Descending (prefix with "-")
161
+ users = await User.afind(tenant_id=tenant_id, order_by="-name")
162
+
163
+ # Multiple sort fields
164
+ users = await User.afind(tenant_id=tenant_id, order_by=["-created_at", "name"])
165
+ ```
166
+
167
+ #### Find first
168
+
169
+ ```python
170
+ user = await User.afind_first(tenant_id=tenant_id, filter={"email": "alice@example.com"})
171
+ ```
172
+
173
+ Returns `None` if no match is found.
174
+
175
+ #### Count
176
+
177
+ ```python
178
+ # async
179
+ total = await User.acount(tenant_id=tenant_id, filter={"name": "Alice"})
180
+
181
+ # sync
182
+ total = User.count(tenant_id=tenant_id, filter={"name": "Alice"})
183
+ ```
184
+
185
+ #### Scroll pages (batch iteration)
186
+
187
+ ```python
188
+ # async
189
+ async for page in User.ascroll_pages(tenant_id=tenant_id, page_size=50):
190
+ for user in page:
191
+ ...
192
+
193
+ # sync
194
+ for page in User.scroll_pages(tenant_id=tenant_id, page_size=50):
195
+ for user in page:
196
+ ...
197
+ ```
198
+
199
+ #### Bulk save
200
+
201
+ ```python
202
+ await User.bulk_save([user1, user2, user3])
203
+ ```
204
+
205
+ ### Index Management
206
+
207
+ Define indexes on the entity class using `__indexes__`:
208
+
209
+ ```python
210
+ @entity(collection_name="users")
211
+ class User(BaseEntity):
212
+ name: str
213
+ email: str
214
+
215
+ __indexes__ = [
216
+ {"keys": [("email", 1)], "unique": True},
217
+ {"keys": [("name", 1)]},
218
+ {"keys": [("tenant_id", 1), ("name", 1)]},
219
+ ]
220
+ ```
221
+
222
+ Index management is controlled by the `MONGODB_INDEX_AUTOAPPLY` environment variable:
223
+
224
+ | Value | Behaviour |
225
+ |---|---|
226
+ | `never` (default) | No automatic index management |
227
+ | `always` | Checks and applies indexes on every startup |
228
+ | `auto-lock` | Applies indexes once; writes a hash to `mongo-orm.lock` and skips on subsequent startups |
229
+
230
+ #### Manual application
231
+
232
+ ```python
233
+ from mongo_orm.utils import apply_all_indexes
234
+
235
+ # Respects MONGODB_INDEX_AUTOAPPLY
236
+ apply_all_indexes()
237
+
238
+ # Force a specific mode
239
+ apply_all_indexes(mode="always")
240
+ ```
241
+
242
+ ## Development
243
+
244
+ ```bash
245
+ # Install dependencies
246
+ poetry install
247
+
248
+ # Run tests
249
+ poetry run pytest
250
+
251
+ # Format code
252
+ poetry run black .
253
+ poetry run isort .
254
+
255
+ # Type checking
256
+ poetry run mypy src/
257
+ ```
258
+
259
+ ## License
260
+
261
+ MIT
@@ -0,0 +1,236 @@
1
+ # mongo-orm
2
+
3
+ A MongoDB ORM for Python
4
+
5
+ ## Installation
6
+
7
+ ```
8
+ pip install mongo-entity-orm
9
+ ```
10
+
11
+ or
12
+
13
+ ```
14
+ uv add mongo-entity-orm
15
+ ```
16
+
17
+ ## Configuration
18
+
19
+ Set the following environment variables before using the ORM:
20
+
21
+ | Variable | Description |
22
+ |---|---|
23
+ | `MONGODB_URI` | MongoDB connection string |
24
+ | `MONGO_DATABASE_NAME` | Name of the database |
25
+
26
+ ## Usage
27
+
28
+ ### Defining an Entity
29
+
30
+ Use the `@entity` decorator to map a class to a MongoDB collection. Your class should inherit from `BaseEntity`.
31
+
32
+ ```python
33
+ from mongo_orm import BaseEntity, entity
34
+
35
+ @entity(collection_name="users")
36
+ class User(BaseEntity):
37
+ name: str
38
+ email: str
39
+ ```
40
+
41
+ Every entity automatically has an `id` field (UUID string) and a `tenant_id` field (defaults to `"-"`).
42
+
43
+ ### CRUD Operations
44
+
45
+ All operations are available in both async (`a`-prefixed) and sync variants.
46
+
47
+ #### Get by ID
48
+
49
+ ```python
50
+ # async
51
+ user = await User.aget(id=user_id, tenant_id=tenant_id)
52
+
53
+ # sync
54
+ user = User.get(id=user_id, tenant_id=tenant_id)
55
+ ```
56
+
57
+ Pass `raise_not_found=True` to raise an exception instead of returning `None` when the entity is not found.
58
+
59
+ #### Save
60
+
61
+ ```python
62
+ user = User(name="Alice", email="alice@example.com", tenant_id="acme")
63
+
64
+ # async
65
+ await user.asave()
66
+
67
+ # sync
68
+ user.save()
69
+ ```
70
+
71
+ `save()` / `asave()` performs an upsert based on `id`, so it works for both creating and updating.
72
+
73
+ #### Update fields
74
+
75
+ ```python
76
+ # Update in-memory only
77
+ user.update(name="Bob")
78
+
79
+ # Update and immediately save (async)
80
+ await user.aupdate(name="Bob", auto_save=True)
81
+
82
+ # Update and immediately save (sync)
83
+ user.update(name="Bob", auto_save=True)
84
+ ```
85
+
86
+ #### Delete
87
+
88
+ ```python
89
+ # Delete an entity instance
90
+ user.delete()
91
+
92
+ # Delete by ID
93
+ User.delete_by_id(id=user_id, tenant_id=tenant_id)
94
+ ```
95
+
96
+ Pass `ignore_not_found=True` to suppress an exception when the entity does not exist.
97
+
98
+ ### Querying
99
+
100
+ #### Find (filter)
101
+
102
+ `filter` accepts a standard MongoDB query dict.
103
+
104
+ ```python
105
+ # async
106
+ users = await User.afind(tenant_id=tenant_id, filter={"name": "Alice"})
107
+
108
+ # sync
109
+ users = User.find(tenant_id=tenant_id, filter={"name": "Alice"})
110
+ ```
111
+
112
+ MongoDB operators work as expected:
113
+
114
+ ```python
115
+ users = await User.afind(
116
+ tenant_id=tenant_id,
117
+ filter={"name": {"$in": ["Alice", "Bob"]}, "email": {"$regex": "@example.com$"}},
118
+ )
119
+ ```
120
+
121
+ Use `tenant_id="*"` to query across all tenants.
122
+
123
+ #### Pagination
124
+
125
+ ```python
126
+ users = await User.afind(tenant_id=tenant_id, filter={}, skip=0, limit=20)
127
+ ```
128
+
129
+ #### Sorting
130
+
131
+ ```python
132
+ # Ascending
133
+ users = await User.afind(tenant_id=tenant_id, order_by="name")
134
+
135
+ # Descending (prefix with "-")
136
+ users = await User.afind(tenant_id=tenant_id, order_by="-name")
137
+
138
+ # Multiple sort fields
139
+ users = await User.afind(tenant_id=tenant_id, order_by=["-created_at", "name"])
140
+ ```
141
+
142
+ #### Find first
143
+
144
+ ```python
145
+ user = await User.afind_first(tenant_id=tenant_id, filter={"email": "alice@example.com"})
146
+ ```
147
+
148
+ Returns `None` if no match is found.
149
+
150
+ #### Count
151
+
152
+ ```python
153
+ # async
154
+ total = await User.acount(tenant_id=tenant_id, filter={"name": "Alice"})
155
+
156
+ # sync
157
+ total = User.count(tenant_id=tenant_id, filter={"name": "Alice"})
158
+ ```
159
+
160
+ #### Scroll pages (batch iteration)
161
+
162
+ ```python
163
+ # async
164
+ async for page in User.ascroll_pages(tenant_id=tenant_id, page_size=50):
165
+ for user in page:
166
+ ...
167
+
168
+ # sync
169
+ for page in User.scroll_pages(tenant_id=tenant_id, page_size=50):
170
+ for user in page:
171
+ ...
172
+ ```
173
+
174
+ #### Bulk save
175
+
176
+ ```python
177
+ await User.bulk_save([user1, user2, user3])
178
+ ```
179
+
180
+ ### Index Management
181
+
182
+ Define indexes on the entity class using `__indexes__`:
183
+
184
+ ```python
185
+ @entity(collection_name="users")
186
+ class User(BaseEntity):
187
+ name: str
188
+ email: str
189
+
190
+ __indexes__ = [
191
+ {"keys": [("email", 1)], "unique": True},
192
+ {"keys": [("name", 1)]},
193
+ {"keys": [("tenant_id", 1), ("name", 1)]},
194
+ ]
195
+ ```
196
+
197
+ Index management is controlled by the `MONGODB_INDEX_AUTOAPPLY` environment variable:
198
+
199
+ | Value | Behaviour |
200
+ |---|---|
201
+ | `never` (default) | No automatic index management |
202
+ | `always` | Checks and applies indexes on every startup |
203
+ | `auto-lock` | Applies indexes once; writes a hash to `mongo-orm.lock` and skips on subsequent startups |
204
+
205
+ #### Manual application
206
+
207
+ ```python
208
+ from mongo_orm.utils import apply_all_indexes
209
+
210
+ # Respects MONGODB_INDEX_AUTOAPPLY
211
+ apply_all_indexes()
212
+
213
+ # Force a specific mode
214
+ apply_all_indexes(mode="always")
215
+ ```
216
+
217
+ ## Development
218
+
219
+ ```bash
220
+ # Install dependencies
221
+ poetry install
222
+
223
+ # Run tests
224
+ poetry run pytest
225
+
226
+ # Format code
227
+ poetry run black .
228
+ poetry run isort .
229
+
230
+ # Type checking
231
+ poetry run mypy src/
232
+ ```
233
+
234
+ ## License
235
+
236
+ MIT
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "mongo-entity-orm"
7
- version = "0.1.1"
7
+ version = "0.1.3"
8
8
  description = "A MongoDB ORM for Python"
9
9
  readme = "README.md"
10
10
  authors = ["Juraj Bezdek <juraj.bezdek@gmail.com>"]
@@ -12,7 +12,7 @@ license = "MIT"
12
12
  packages = [{include = "mongo_orm", from = "src"}]
13
13
  keywords = ["mongodb", "orm", "mongo", "async"]
14
14
  homepage = "https://github.com/ju-bezdek/mongo-orm"
15
- repository = "https://github.com/ju-bezdek/mongo"
15
+ repository = "https://github.com/ju-bezdek/mongo-orm"
16
16
 
17
17
  classifiers = [
18
18
  "Programming Language :: Python :: 3",
@@ -25,8 +25,8 @@ classifiers = [
25
25
  ]
26
26
 
27
27
  [tool.poetry.urls]
28
- Repository = "https://github.com/ju-bezdek/mongo"
29
- Documentation = "https://github.com/ju-bezdek/mongo#readme"
28
+ Repository = "https://github.com/ju-bezdek/mongo-orm"
29
+ Documentation = "https://github.com/ju-bezdek/mongo-orm#readme"
30
30
 
31
31
  [tool.poetry.dependencies]
32
32
  python = ">=3.9,<4.0"
@@ -60,18 +60,26 @@ class Repository:
60
60
  if mongo_db:
61
61
  self.mongo_db = mongo_db
62
62
  else:
63
+ mongodb_uri = Config.MONGODB_URI()
64
+ mongo_db_name = Config.MONGO_DATABASE_NAME()
65
+ if not mongodb_uri and not mongo_db_name:
66
+ raise ValueError(
67
+ "MONGODB_URI and MONGO_DATABASE_NAME environment variables are not set"
68
+ )
69
+ if not mongodb_uri:
70
+ raise ValueError("MONGODB_URI environment variable is not set")
71
+ if not mongo_db_name:
72
+ raise ValueError("MONGO_DATABASE_NAME environment variable is not set")
63
73
 
64
74
  self.mongo_client = MongoClient(
65
- Config.MONGODB_URI(), tlsAllowInvalidCertificates=True
75
+ mongodb_uri, tlsAllowInvalidCertificates=True
66
76
  )
67
77
  self.async_mongo_client = AsyncIOMotorClient(
68
- Config.MONGODB_URI(), tls=True, tlsAllowInvalidCertificates=True
78
+ mongodb_uri, tls=True, tlsAllowInvalidCertificates=True
69
79
  )
70
80
  self.mongo_client.admin.command("ping")
71
- self.mongo_db = self.mongo_client[str(Config.MONGO_DATABASE_NAME())]
72
- self.async_mongo_db = self.async_mongo_client[
73
- str(Config.MONGO_DATABASE_NAME())
74
- ]
81
+ self.mongo_db = self.mongo_client[str(mongo_db_name)]
82
+ self.async_mongo_db = self.async_mongo_client[str(mongo_db_name)]
75
83
 
76
84
 
77
85
  REPOSITORY = Repository()
@@ -301,7 +309,7 @@ class BaseEntity(BaseModel):
301
309
  )
302
310
 
303
311
  @classmethod
304
- def delete_by_id(cls, id, tenant_id: str):
312
+ def delete_by_id(cls, id, tenant_id: str = "*") -> bool:
305
313
 
306
314
  filter = {"_id": id}
307
315
  if tenant_id != "*":
@@ -313,7 +321,7 @@ class BaseEntity(BaseModel):
313
321
  def get(
314
322
  cls: Type[T],
315
323
  id: str,
316
- tenant_id: str,
324
+ tenant_id: str = "*",
317
325
  namespace: str = None,
318
326
  raise_not_found: bool = False,
319
327
  ) -> T | None:
@@ -334,7 +342,7 @@ class BaseEntity(BaseModel):
334
342
  async def aget(
335
343
  cls: Type[T],
336
344
  id: str,
337
- tenant_id: str,
345
+ tenant_id: str = "*",
338
346
  namespace: str = None,
339
347
  raise_not_found: bool = False,
340
348
  ) -> T | None:
@@ -370,7 +378,7 @@ class BaseEntity(BaseModel):
370
378
  return entity
371
379
 
372
380
  @classmethod
373
- def count(cls, tenant_id: str, filter: dict = None, limit=None) -> int:
381
+ def count(cls, tenant_id: str = "*", filter: dict = None, limit=None) -> int:
374
382
 
375
383
  if not filter:
376
384
  _filter = {}
@@ -386,7 +394,7 @@ class BaseEntity(BaseModel):
386
394
  return cls.collection.count_documents(_filter, **extra)
387
395
 
388
396
  @classmethod
389
- async def acount(cls, tenant_id: str, filter: dict = None, limit=None) -> int:
397
+ async def acount(cls, tenant_id: str = "*", filter: dict = None, limit=None) -> int:
390
398
 
391
399
  if not filter:
392
400
  _filter = {}
@@ -404,7 +412,7 @@ class BaseEntity(BaseModel):
404
412
  @classmethod
405
413
  async def afind(
406
414
  cls: Type[T],
407
- tenant_id: str,
415
+ tenant_id: str = "*",
408
416
  namespace: str = None,
409
417
  skip: int = 0,
410
418
  limit: int = 100,
@@ -414,8 +422,10 @@ class BaseEntity(BaseModel):
414
422
  ) -> List[T]:
415
423
  if not filter:
416
424
  filter = {}
425
+ else:
426
+ filter = {**filter}
417
427
  if tenant_id != "*":
418
- filter.update({"tenant_id": tenant_id, **additional_filters})
428
+ filter.update({"tenant_id": tenant_id})
419
429
 
420
430
  filter.update(additional_filters)
421
431
  if "id" in filter:
@@ -446,7 +456,7 @@ class BaseEntity(BaseModel):
446
456
  @classmethod
447
457
  def scroll_pages(
448
458
  cls: Type[T],
449
- tenant_id: str,
459
+ tenant_id: str = "*",
450
460
  filter: dict = None,
451
461
  order_by: str = None,
452
462
  page_size: int = 100,
@@ -468,7 +478,7 @@ class BaseEntity(BaseModel):
468
478
  @classmethod
469
479
  async def ascroll_pages(
470
480
  cls: Type[T],
471
- tenant_id: str,
481
+ tenant_id: str = "*",
472
482
  filter: dict = None,
473
483
  order_by: str = None,
474
484
  page_size: int = 100,
@@ -490,7 +500,7 @@ class BaseEntity(BaseModel):
490
500
  @classmethod
491
501
  def find(
492
502
  cls: Type[T],
493
- tenant_id: str,
503
+ tenant_id: str = "*",
494
504
  namespace: str = None,
495
505
  skip: int = 0,
496
506
  limit: int | None = 100,
@@ -503,7 +513,7 @@ class BaseEntity(BaseModel):
503
513
  else:
504
514
  filter = {**filter}
505
515
  if tenant_id != "*":
506
- filter.update({"tenant_id": tenant_id, **additional_filters})
516
+ filter.update({"tenant_id": tenant_id})
507
517
 
508
518
  filter.update(additional_filters)
509
519
  if "id" in filter:
@@ -536,13 +546,15 @@ class BaseEntity(BaseModel):
536
546
  return res
537
547
 
538
548
  @classmethod
539
- def find_first(cls, tenant_id, filter=None, order_by=None, **kwargs):
549
+ def find_first(cls, tenant_id: str = "*", filter=None, order_by=None, **kwargs):
540
550
  kwargs.pop("limit", None)
541
551
  items = cls.find(tenant_id, filter=filter, order_by=order_by, limit=1, **kwargs)
542
552
  return items[0] if items else None
543
553
 
544
554
  @classmethod
545
- async def afind_first(cls, tenant_id, filter=None, order_by=None, **kwargs):
555
+ async def afind_first(
556
+ cls, tenant_id: str = "*", filter=None, order_by=None, **kwargs
557
+ ):
546
558
  items = await cls.afind(
547
559
  tenant_id, filter=filter, order_by=order_by, limit=1, **kwargs
548
560
  )
@@ -1,94 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: mongo-entity-orm
3
- Version: 0.1.1
4
- Summary: A MongoDB ORM for Python
5
- License: MIT
6
- Keywords: mongodb,orm,mongo,async
7
- Author: Juraj Bezdek
8
- Author-email: juraj.bezdek@gmail.com
9
- Requires-Python: >=3.9,<4.0
10
- Classifier: License :: OSI Approved :: MIT License
11
- Classifier: Operating System :: OS Independent
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.9
14
- Classifier: Programming Language :: Python :: 3.10
15
- Classifier: Programming Language :: Python :: 3.11
16
- Classifier: Programming Language :: Python :: 3.12
17
- Classifier: Programming Language :: Python :: 3.13
18
- Classifier: Programming Language :: Python :: 3 :: Only
19
- Requires-Dist: motor (>=3.7.1,<4.0.0)
20
- Requires-Dist: pymongo (>=4.13.2,<5.0.0)
21
- Project-URL: Documentation, https://github.com/ju-bezdek/mongo#readme
22
- Project-URL: Homepage, https://github.com/ju-bezdek/mongo-orm
23
- Project-URL: Repository, https://github.com/ju-bezdek/mongo
24
- Description-Content-Type: text/markdown
25
-
26
- # mongo-orm
27
-
28
- A MongoDB ORM for Python
29
-
30
- ## Usage
31
-
32
- ### Defining an Entity
33
-
34
- Use the `@entity` decorator to map a class to a MongoDB collection. Your class should inherit from `BaseEntity`.
35
-
36
- ```python
37
- from mongo_orm import BaseEntity, entity
38
-
39
- @entity("users")
40
- class User(BaseEntity):
41
- name: str
42
- email: str
43
-
44
- # Define indexes
45
- __indexes__ = [
46
- {"keys": [("email", 1)], "unique": True},
47
- {"keys": [("name", 1)]}
48
- ]
49
- ```
50
-
51
- ### Index Management
52
-
53
- The ORM can automatically manage your MongoDB indexes based on the `__indexes__` attribute. This behavior is controlled by the `MONGODB_INDEX_AUTOAPPLY` environment variable.
54
-
55
- #### Configuration (`MONGODB_INDEX_AUTOAPPLY`)
56
-
57
- - `never` (default): No automatic index management.
58
- - `always`: Checks and applies indexes every time an entity class is initialized (on startup).
59
- - `auto-lock`: Checks and applies indexes once. After a successful check, it writes a hash of the index to `mongo-orm.lock`. Subsequent startups will skip the check if the hash is present in the lock file.
60
-
61
- #### Manual Index Application
62
-
63
- You can also trigger index application manually for all registered entities:
64
-
65
- ```python
66
- from mongo_orm.utils import apply_all_indexes
67
-
68
- # Apply indexes using the current environment configuration
69
- apply_all_indexes()
70
-
71
- # Or force a specific mode
72
- apply_all_indexes(mode="always")
73
- ```
74
-
75
- ## Development
76
-
77
- ```bash
78
- # Install dependencies
79
- poetry install
80
-
81
- # Run tests
82
- poetry run pytest
83
-
84
- # Format code
85
- poetry run black .
86
- poetry run isort .
87
-
88
- # Type checking
89
- poetry run mypy src/
90
- ```
91
-
92
- ## License
93
-
94
- MIT
@@ -1,69 +0,0 @@
1
- # mongo-orm
2
-
3
- A MongoDB ORM for Python
4
-
5
- ## Usage
6
-
7
- ### Defining an Entity
8
-
9
- Use the `@entity` decorator to map a class to a MongoDB collection. Your class should inherit from `BaseEntity`.
10
-
11
- ```python
12
- from mongo_orm import BaseEntity, entity
13
-
14
- @entity("users")
15
- class User(BaseEntity):
16
- name: str
17
- email: str
18
-
19
- # Define indexes
20
- __indexes__ = [
21
- {"keys": [("email", 1)], "unique": True},
22
- {"keys": [("name", 1)]}
23
- ]
24
- ```
25
-
26
- ### Index Management
27
-
28
- The ORM can automatically manage your MongoDB indexes based on the `__indexes__` attribute. This behavior is controlled by the `MONGODB_INDEX_AUTOAPPLY` environment variable.
29
-
30
- #### Configuration (`MONGODB_INDEX_AUTOAPPLY`)
31
-
32
- - `never` (default): No automatic index management.
33
- - `always`: Checks and applies indexes every time an entity class is initialized (on startup).
34
- - `auto-lock`: Checks and applies indexes once. After a successful check, it writes a hash of the index to `mongo-orm.lock`. Subsequent startups will skip the check if the hash is present in the lock file.
35
-
36
- #### Manual Index Application
37
-
38
- You can also trigger index application manually for all registered entities:
39
-
40
- ```python
41
- from mongo_orm.utils import apply_all_indexes
42
-
43
- # Apply indexes using the current environment configuration
44
- apply_all_indexes()
45
-
46
- # Or force a specific mode
47
- apply_all_indexes(mode="always")
48
- ```
49
-
50
- ## Development
51
-
52
- ```bash
53
- # Install dependencies
54
- poetry install
55
-
56
- # Run tests
57
- poetry run pytest
58
-
59
- # Format code
60
- poetry run black .
61
- poetry run isort .
62
-
63
- # Type checking
64
- poetry run mypy src/
65
- ```
66
-
67
- ## License
68
-
69
- MIT