art049 / art049/odmantic

Handle references within generics of EmbeddedModel

Open
#95 4 comments 1 reaction 0 assignees View on GitHub
feature reference-rework
Dominant language
Python
Stars
1.2k
Forks
97
PR merge metrics
No merged PRs in 30d

Description

# Bug

When i try to reference other model in EmbeddedModel, i get full document inserted instead of reference to it

### Current Behavior
I have these models:
```python
class Need(Model):
name: str

class PetNeed(EmbeddedModel):
need: Need = Reference()
value: int = Field(default=0)

class Pet(Model):
name: str
needs: List[PetNeed] = Field(default=[])
```

If i try to do this:
```python
hunger = Need(name='Hunger')
dog = Pet(name='Dog')
dog.needs.append(PetNeed(need=hunger))
await engine.save_all([hunger, dog])
```
I get this in the database:
```
{
"_id": {
"$oid": "60062e817a596be396df8ab8"
},
"name": "Dog",
"needs": [{
"need": {
"name": "Hunger",
"id": {
"$oid": "60062e817a596be396df8ab7"
}
},
"value": 0
}]
}
```
As you can see full model being inserted into the database with both name and id instead of just reference id to it

However everything is fine if i reference Need model directly:
```python
rest = Need(name='Rest')
cat = Pet(name='Cat', need=rest)
await engine.save_all([rest, cat])
```
Database:
```
{
"_id": {
"$oid": "6006326f0092a86615eeae91"
},
"name": "Cat",
"need": {
"$oid": "6006326f0092a86615eeae90"
}
}
```

### Expected behavior

ODMantic should put reference id in EmbeddedModel instead of putting full Model in the field

### Environment

- ODMantic version: 0.3.2
- MongoDB version: 4.2.11
- Pydantic infos (output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())`):

```
pydantic version: 1.7.3
pydantic compiled: True
install path: D:\_Projects\python\bot\py\Lib\site-packages\pydantic
python version: 3.9.1 (tags/v3.9.1:1e5d33e, Dec 7 2020, 17:08:21) [MSC v.1927 64 bit (AMD64)]
platform: Windows-10-10.0.18362-SP0
optional deps. installed: ['typing-extensions']
```

**Additional context**

It is also impossible to make reference fields `Optional` or put them in a `List`, but I read in the docs that it is planned to make a generic `Reference[T]` type so it's ok

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the issue with the Need, PetNeed, and Pet models shown, then trace how references inside EmbeddedModel fields are serialized during engine.save_all. Done means the embedded need stores only the referenced model's id, while direct references continue to work and the reported generic cases are covered by regression tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
mongodb, python
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.