-
Notifications
You must be signed in to change notification settings - Fork 235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for embedded documents (aka subdocuments) #195
Comments
Hey @aknoerig , You can do smth like this: class Inner(BaseModel):
num: int
class Sample(Document):
inner_lst: List[Inner] Will this work for you? Or you are looking for some additional methods for this? If so, pls provide some details about your use case. |
Yeah, what you mention is great for creating nested/embedded fields. An embedded document is more than that, as it would have its own unique id (locally unique, but could also be globally unique). This offers easy access to these sub-elements, provides checks for uniqueness of id, etc. So in your example it would have to be: class Inner(Document):
num: int
class Sample(Document):
inner_lst: List[Inner] For reference, see how mongoose treats "subdocuments". |
In the first documentation example, it has no unique ids: {
"_id": "joe",
"name": "Joe Bookreader",
"addresses": [
{
"street": "123 Fake Street",
"city": "Faketon",
"state": "MA",
"zip": "12345"
},
{
"street": "1 Some Other Street",
"city": "Boston",
"state": "MA",
"zip": "12345"
}
]
} But yes, it can have unique ids. For this you need to add a factory for the id field like next: class Inner(Document):
id: UUID = Field(default_factory=uuid4)
num: int
class Sample(Document):
inner_lst: List[Inner] Unfortunately, Beanie doesn't support automatically added unique indexes for the embedded docs, but it can be set up on the parent doc using the path to the embedded id field (in the inner Collection class). Using this you'll be able to save the Inner document to the separated collection and the whole copy will be stored to the Sample doc on inserts/updates of the Sample doc. Action-based events will not work on the saving as the internal doc, as the save/insert and etc method will not be called separately for these docs. I'll take a look at the mongoose implementation - probably I'll implement some patterns from there in Beanie too. Thank you :) |
That's interesting, thanks. I guess what I would like to be able to do is an easy way to do CRUD on these embedded docs. Something along these lines: sample.inner_lst.append(Inner(1))
inner = sample.inner_lst.get(inner_id)
sample.inner_lst.set(inner_id, inner_updates)
sample.inner_lst.delete(inner_id)
sample.save() |
I'm looking for this as well. Porting some code from Ruby + Mongoid where they support embedded documents, you can declare a Document class and give it an attribute like 'embedded_in' and reference another Document.
But it seems Beanie is filtering out the field on serialization because it is called "_id". If I remove the alias, the id field gets written to the DB. I maybe be able to cope with this but the challenge I have now is that I'm going to python code writing documents and ruby code reading them so I'm worried about compatibility. |
@roman-right Odmanic (another python odm) have this feature. https://art049.github.io/odmantic/modeling/, after migrating from odmantic to beanie, this is one of the biggest issue I am facing. |
I'm trying to find an odm for my next project and this project looks better for me than odmantic.. The only thing missing is better many to many and foreign key alike structures like this :/ |
This issue is stale because it has been open 30 days with no activity. |
This issue was closed because it has been stalled for 14 days with no activity. |
Please consider reopening this issue. |
Hi @aknoerig , Like: class Door(BaseModel):
height: int
width: int
class House(Document):
door: Embedded[Door] And the same for lists : But I want to understand the use case a bit better to get which queries should be covered |
I'm not this issue's owner, but I want this feature for better structure. class User(BaseModel):
uid: int
nickname: str
class UserGroup(Document):
gid: int
users: List[User] Without this, I have to update UserGroup (which includes every user in the user group) to update one user's nickname, and it's looks so bad. |
+1 for this feature. I also need to be able to update a nested model by it's nested ID. That said, I think you might be able to accomplish this with array_filters: await UserGroup.find_one(UserGroup.id == group_id).update(
{"$set": {"users.$[u].nickname": "new name"}},
array_filters=[{"u.uid": user_to_update.uid}],
) But it would be great to have a nicer way to do that natively with Beanie |
Actually this is even simpler with mongo's positional $ operator await UserGroup.find_one({UserGroup.id: group_id, "users.uid": user_to_update.uid}).update(
Set({"users.$.nickname": "new name"}),
) |
First of all thanks for this fine and very useful library. Given that it's surprisingly difficult to make FastAPI/pydantic work seamlessly with MongoDb, this effort is very much welcome!
Is there any plan to support embedded documents?
MongoDb supports two basic patterns for modelling slightly more complex data structures: relations and embedded documents. Relations are already well-supported in beanie via the
Link
type, but I could not find any mentioning of how to make use of embedded documents.The text was updated successfully, but these errors were encountered: