0
# Field Types & Relationships
1
2
Type-safe field definitions with MongoDB-specific types, automatic indexing capabilities, and document relationships with lazy loading support. These components enable rich data modeling with proper validation and efficient queries.
3
4
## Capabilities
5
6
### Object ID Types
7
8
MongoDB ObjectId field types that integrate seamlessly with Pydantic validation and serialization.
9
10
```python { .api }
11
class PydanticObjectId(ObjectId):
12
"""Pydantic-compatible ObjectId field type for document IDs."""
13
14
def __init__(self, value: Union[str, ObjectId, None] = None):
15
"""Initialize ObjectId from string, ObjectId, or generate new one."""
16
...
17
18
def __str__(self) -> str:
19
"""String representation of ObjectId."""
20
...
21
22
def __repr__(self) -> str:
23
"""Developer representation of ObjectId."""
24
...
25
26
@classmethod
27
def __get_validators__(cls):
28
"""Pydantic validators for ObjectId validation."""
29
...
30
31
@classmethod
32
def validate(cls, value: Any) -> "PydanticObjectId":
33
"""Validate and convert input to PydanticObjectId."""
34
...
35
36
# Alias for backward compatibility
37
BeanieObjectId = PydanticObjectId
38
```
39
40
#### Usage Examples
41
42
```python
43
from beanie import Document, PydanticObjectId
44
from typing import Optional
45
46
class Product(Document):
47
id: Optional[PydanticObjectId] = None
48
name: str
49
category_id: PydanticObjectId
50
51
class Settings:
52
collection = "products"
53
54
# Create with ObjectId
55
product = Product(
56
name="Laptop",
57
category_id=PydanticObjectId("507f1f77bcf86cd799439011")
58
)
59
await product.insert()
60
61
# Access as string
62
print(f"Product ID: {product.id}")
63
print(f"Category ID: {str(product.category_id)}")
64
```
65
66
### Expression Fields
67
68
Special field types for building MongoDB queries and operations programmatically.
69
70
```python { .api }
71
class ExpressionField(str):
72
"""String-based field expressions for query building."""
73
74
def __getitem__(self, item: str) -> "ExpressionField":
75
"""Get sub-field for nested document queries."""
76
...
77
78
def __getattr__(self, item: str) -> "ExpressionField":
79
"""Access nested fields using attribute notation."""
80
...
81
```
82
83
#### Usage Examples
84
85
```python
86
from beanie import Document, ExpressionField
87
88
class User(Document):
89
name: str
90
profile: Dict[str, Any]
91
92
# Create expression fields for queries
93
user_name = ExpressionField("name")
94
profile_age = ExpressionField("profile.age")
95
96
# Use in queries
97
users = await User.find(user_name == "Alice").to_list()
98
adults = await User.find(profile_age >= 18).to_list()
99
```
100
101
### Indexed Fields
102
103
Field annotations that automatically create MongoDB indexes during initialization, supporting various index types and options.
104
105
```python { .api }
106
class IndexedAnnotation:
107
"""Internal annotation class for indexed fields."""
108
_indexed: Tuple[int, Dict[str, Any]]
109
```
110
111
```python { .api }
112
def Indexed(
113
annotation: Any,
114
index_type: Optional[str] = None,
115
unique: bool = False,
116
sparse: bool = False,
117
**kwargs
118
) -> Any:
119
"""
120
Create indexed field annotation for automatic index creation.
121
122
Args:
123
annotation: Base field type (str, int, etc.)
124
index_type: MongoDB index type ("text", "2d", "2dsphere", etc.)
125
unique: Create unique index
126
sparse: Create sparse index (skip None values)
127
**kwargs: Additional index options
128
129
Returns:
130
Annotated field type with index metadata
131
"""
132
...
133
```
134
135
#### Usage Examples
136
137
```python
138
from beanie import Document, Indexed
139
from typing import Annotated, Optional
140
141
class User(Document):
142
# Unique index on email
143
email: Annotated[str, Indexed(unique=True)]
144
145
# Text index for full-text search
146
bio: Annotated[str, Indexed(index_type="text")]
147
148
# Compound index (defined in Settings)
149
first_name: str
150
last_name: str
151
152
# Sparse index (ignores None values)
153
phone: Annotated[Optional[str], Indexed(sparse=True)]
154
155
class Settings:
156
collection = "users"
157
indexes = [
158
[("first_name", 1), ("last_name", 1)], # Compound index
159
[("email", 1), ("phone", 1)] # Multi-field index
160
]
161
162
# Alternative syntax
163
class Product(Document):
164
name: str = Indexed(str, unique=True)
165
price: float = Indexed(float)
166
category: str = Indexed(str, index_type="text")
167
```
168
169
### Document Links
170
171
Reference fields that create relationships between documents in different collections with lazy loading and batch fetching capabilities.
172
173
```python { .api }
174
class Link(Generic[T]):
175
"""Reference to documents in other collections with lazy loading."""
176
177
def __init__(self, ref: DBRef, document_class: Type[T]):
178
"""
179
Initialize document link.
180
181
Args:
182
ref: MongoDB DBRef pointing to the linked document
183
document_class: Target document class
184
"""
185
...
186
187
async def fetch(self, fetch_links: bool = False) -> Union[T, "Link[T]"]:
188
"""
189
Load the referenced document.
190
191
Args:
192
fetch_links: Also fetch nested links
193
194
Returns:
195
Referenced document or Link if not found
196
"""
197
...
198
199
@classmethod
200
async def fetch_one(cls, link: "Link[T]") -> Union[T, "Link[T]"]:
201
"""Fetch a single linked document."""
202
...
203
204
@classmethod
205
async def fetch_list(
206
cls,
207
links: List[Union["Link[T]", T]],
208
fetch_links: bool = False,
209
) -> List[Union[T, "Link[T]"]]:
210
"""
211
Load multiple referenced documents.
212
213
Args:
214
links: List of Link objects or documents
215
fetch_links: Also fetch nested links
216
217
Returns:
218
List of referenced documents or Links
219
"""
220
...
221
222
@classmethod
223
async def fetch_many(cls, links: List["Link[T]"]) -> List[Union[T, "Link[T]"]]:
224
"""Fetch multiple linked documents concurrently."""
225
...
226
227
def to_dict(self) -> Dict[str, str]:
228
"""Convert link to dictionary representation with id and collection."""
229
...
230
231
@staticmethod
232
def serialize(value: Union["Link[T]", BaseModel]) -> Dict[str, Any]:
233
"""Serialize link or document for JSON output."""
234
...
235
```
236
237
#### Usage Examples
238
239
```python
240
from beanie import Document, Link
241
from typing import Optional, List
242
243
class Category(Document):
244
name: str
245
description: str
246
247
class Settings:
248
collection = "categories"
249
250
class Product(Document):
251
name: str
252
price: float
253
category: Link[Category] # Single reference
254
related_products: List[Link[Product]] = [] # Multiple references
255
256
class Settings:
257
collection = "products"
258
259
# Create linked documents
260
category = Category(name="Electronics", description="Electronic devices")
261
await category.insert()
262
263
product = Product(
264
name="Smartphone",
265
price=599.99,
266
category=category # Link automatically created
267
)
268
await product.insert()
269
270
# Fetch linked document
271
await product.category.fetch()
272
print(f"Category: {product.category.name}")
273
274
# Fetch with nested links
275
await product.fetch_all_links()
276
```
277
278
### Back Links
279
280
Reverse reference fields that automatically maintain bidirectional relationships between documents.
281
282
```python { .api }
283
class BackLink(Generic[T]):
284
"""Back-reference field for bidirectional relationships."""
285
286
def __init__(
287
self,
288
document_class: Type[T],
289
original_field: str,
290
lazy: bool = True
291
):
292
"""
293
Initialize back link.
294
295
Args:
296
document_class: Source document class
297
original_field: Field name in source document
298
lazy: Enable lazy loading
299
"""
300
...
301
302
async def fetch(self, limit: Optional[int] = None) -> List[T]:
303
"""
304
Fetch documents that reference this document.
305
306
Args:
307
limit: Maximum number of documents to fetch
308
309
Returns:
310
List of referencing documents
311
"""
312
...
313
314
def to_dict(self) -> Dict[str, str]:
315
"""Convert back link to dictionary representation with collection info."""
316
...
317
```
318
319
#### Usage Examples
320
321
```python
322
from beanie import Document, Link, BackLink
323
from typing import List
324
325
class Author(Document):
326
name: str
327
books: List[BackLink["Book"]] = BackLink("Book", "author")
328
329
class Settings:
330
collection = "authors"
331
332
class Book(Document):
333
title: str
334
author: Link[Author]
335
336
class Settings:
337
collection = "books"
338
339
# Create author and books
340
author = Author(name="Jane Doe")
341
await author.insert()
342
343
book1 = Book(title="First Book", author=author)
344
book2 = Book(title="Second Book", author=author)
345
await book1.insert()
346
await book2.insert()
347
348
# Access books through back link
349
books = await author.books.fetch()
350
print(f"Author has {len(books)} books")
351
```
352
353
### Link Rules
354
355
Enumerations that control how linked documents are handled during write and delete operations.
356
357
```python { .api }
358
class WriteRules(Enum):
359
"""Rules for handling linked documents during write operations."""
360
DO_NOTHING = "DO_NOTHING" # Don't save linked documents
361
WRITE = "WRITE" # Save linked documents too
362
363
class DeleteRules(Enum):
364
"""Rules for handling linked documents during delete operations."""
365
DO_NOTHING = "DO_NOTHING" # Leave linked documents unchanged
366
DELETE_LINKS = "DELETE_LINKS" # Delete references to this document
367
```
368
369
#### Usage Examples
370
371
```python
372
from beanie import Document, Link, WriteRules, DeleteRules
373
374
class Author(Document):
375
name: str
376
377
class Settings:
378
collection = "authors"
379
380
class Book(Document):
381
title: str
382
author: Link[Author]
383
384
class Settings:
385
collection = "books"
386
# Configure link behavior
387
write_rules = WriteRules.WRITE
388
delete_rules = DeleteRules.DELETE_LINKS
389
390
# When saving book with WriteRules.WRITE:
391
# - Author will be saved automatically if modified
392
book = Book(title="New Book", author=author)
393
await book.save() # Saves both book and author if needed
394
395
# When deleting author with DeleteRules.DELETE_LINKS:
396
# - All book.author references are removed
397
await author.delete() # Books will have author=None
398
```
399
400
## Types
401
402
```python { .api }
403
from typing import TypeVar, Generic, Optional, List, Dict, Any, Union
404
from enum import Enum
405
from bson import ObjectId
406
407
# Generic type for document links
408
T = TypeVar("T", bound="Document")
409
410
# Link rule enumerations
411
class WriteRules(Enum):
412
DO_NOTHING = "DO_NOTHING"
413
WRITE = "WRITE"
414
415
class DeleteRules(Enum):
416
DO_NOTHING = "DO_NOTHING"
417
DELETE_LINKS = "DELETE_LINKS"
418
419
# Field metadata types
420
IndexInfo = Dict[str, Any]
421
FieldInfo = Dict[str, Any]
422
```