MongoDB: Support for embedded documents
See original GitHub issueProblem
One of the major features of MongoDB is how you can store embedded data within a record. MongoDB also offers rich querying capabilities to work with this data.
Currently the Prisma Client supports writing embedded documents with the Json type
model User {
name String
address Json
}
prisma.user.create({
data: {
name: "Alice"
address: {
street: "1234 Wonderland Ave"
zip: "12351"
}
}
})
Unfortunately this isn’t type-safe. Nothing stops you from adding another random field to the address or writing “street” as “st”.
Additionally, we currently only support a few operations on the Json type for MongoDB.
Goal
- We’d like to introduce a new way to store and query embedded data in a type-safe way.
- We’d like to be able to apply this new approach to other DBs with JSON support like Postgres.
Suggested solution
Add support for embeds. Potentially introduce an embed
keyword in the Prisma schema
model User {
name String
address Address
}
embed Address {
street String
zip String
}
Alternatives
While above feels clean, one issue is that embed seems to be an attribute of the Address, not a defining feature of the Address. You might want Address to be embedded in some model, but relational in others. That makes me think that the caller should decide, not the definer.
model User {
name String
address Address @embed
}
model Address {
street String
zip String
}
The upside to this is that there’s no new blocks either.
Additional context
- Original MongoDB issue
Issue Analytics
- State:
- Created 2 years ago
- Reactions:115
- Comments:19 (7 by maintainers)
Top GitHub Comments
Hey everyone! I just want to share that we’ve come up with a design for this. Please let me know what you think and if you have any questions!
Also if you feel like discussing the proposal in more detail, you can schedule a short call with me here: https://calendly.com/matthewmueller/embedded-documents.
Overview of the solution
This solution extends the Prisma Schema to support defining your own custom types.
In the following example, we define
Address
andPet
as embedded types that we use within ourUser
model:Outcome
This solution has the following design goals:
By achieving these goals, developers using MongoDB will be able to work with embedded documents in the same way they can work with relational documents. There won’t be anything new to learn and you get a new way of storing and accessing data.
This can solution can be ported to SQL databases that support a
json
column, giving developers a type-safe embedded data access for relational databases.Lastly, this may give us a way to “mixin” types with models, allowing developers to reuse fields inside a model.
FAQ
Is it a property of the “relation” or a property of the embedded model itself?
In Prisma1, it was basically both - a relation to a model annotated with embed
Do embeds need IDs?
No, embed aren’t addressable on their own. They are always reached from a model which does have an ID.
What about uniques in embeds?
Depends on the underlying capability. If it’s possible in the underlying source it should be possible. However, it doesn’t seem like it’s currently possible https://joegornick.com/2012/10/25/mongodb-unique-indexes-on-single/embedded-documents/
Do embeds have backrelations (e.g. accessing posts from authors)?
No. Since the embeds are not a top-level, standalone model, there isn’t a case where you have an embed and need to reach the model.
Can embeds have relations to other models?
If the underlying datasource can define a foreign key on the embedded type, it should be possible, but this would be out of scope for the first iteration. You could always pull the foreign key and lookup the relation in a separate query.
Can an embed be nested within another embed (type in a type)?
Nothing should prevent this, but not a high priority for the first iteration of the solution.
Embeds as an ID?
This should be possible because MongoDB supports objects as primary keys, but supporting this use case is low priority.
Do embeds need to be uniquely named?
Yes, for now because it simplifies the solution. Since types are a purely Prisma construct and not tied to the database, you could have a type name that’s also a model name.
References
Hey all, I just wanted to share that Embedded Document support for MongoDB is now in Preview!
It’s easy to get started. First, install the latest Prisma (3.10.0) and add the
mongoDb
preview feature flag:Then you’ll have a new
type
keyword in your Prisma Schema (or will get schemas withtype
for your existing MongoDB databases that use Embedded Documents when runningprisma db pull
), for example:Once you run
prisma generate
, you’ll have a new type-safe API for working with these types.For example, here’s how you’d create a new Order with an embedded shipping address:
This is just the tip of the iceberg. Dive deeper in our documentation.
If you have any feedback for us, I’d love to jump on a call with you.
We’re actively working towards getting MongoDB production ready, so now’s the time to give this a try and share your thoughts!