Skip to content
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

Implement datamodel parser validations for two-way embedded many-to-many relations on MongoDB #11553

Closed
tomhoule opened this issue Feb 1, 2022 · 4 comments · Fixed by prisma/prisma-engines#2671
Assignees
Labels
kind/feature A request for a new feature. team/schema Issue for team Schema. topic: m:n many-to-many relations topic: mongodb
Milestone

Comments

@tomhoule
Copy link
Contributor

tomhoule commented Feb 1, 2022

We want to enable relations looking like this:

model Book {
  ...
  author_ids String[] @db.ObjectId
  authors    Author[] @relation(fields: [author_ids], references: id)
}

model Author {
  ...
  book_ids String[] @db.ObjectId
  books    Book[]   @relation(fields: [book_ids], references: id)
}

This is a type of many-to-many relations with the following rules:

  • It is only possible on mongodb
  • The @relation attributes on both sides have both fields: and references: as required arguments.
  • The references: argument must reference a single-field ID on the opposite model. No multi-field ids, no referencing unique criteria other than a single field id.
  • Both sides of the relation must be present
  • Both sides of the relation must have the list arity.

This will be the only type of many-to-many relations allowed on mongodb. In other words, implicit many-to-many relations without fields: [...] with scalar backing fields are not valid. This should be validated.

More importantly,

  • we will need to look at existing relation validations, and filter out which are general, and which are only valid on SQL connectors, then implement that separation.
  • we will need to look at the reformatting logic and make sure
    • there is no automatic reformatting for this type of relations, or that it produces valid code
    • we do not break relation reformatting for other types of relations in the process

Internal design documentation: https://www.notion.so/prismaio/MongoDB-Linking-Referencing-Relations-98b51496ac3f48398e1f0571d13ef790#0708e8c45648492a963ccde0f7d6f1bb


Implementation notes

  • In ParserDatabase, we have 3 relation types: 1:1, 1:m and implicit many-to-many.
    • We need to add explicit many-to-many ("2-way embedded m:n")
  • Implicit many-to-many relations should be forbidden on mong
  • We have to make sure
    • we don't break existing SQL relation validations
    • we don't allow these relations on SQL connectors
    • we still validate 1:m and 1:1 right on mongodb
  • We shouldn't break how these relations are lifted to dml to avoid breaking Client
  • If that's more convenient, we can also at the same time fix the bug of fields and references arguments being accepted on implicit m:n relations (all connectors) [PSL] Do not allow references arg on Many2Many relations on SQL #11241
  • Check reformatting
    • We don't want the reformatter to add scalar fields implicitly for that type of relations
    • Reformatting can add the references. references can only reference a single-field id.
    • fields should not be automatically added
    • detection of these relations: both sides are lists, and they have fields
    • One option would be to basically do no reformatting on these, and open an issue to implement adding references on these relations as a first prisma-fmt-wasm driven code action.
  • We have to write a bunch of tests and check that the error messages make sense (amibiguous relations, etc.)

This is purely datamodel work, nothing to do in introspection and migration engines.

@pantharshit00 pantharshit00 added the kind/feature A request for a new feature. label Feb 1, 2022
@floelhoeffel floelhoeffel added this to the 3.10.0 milestone Feb 2, 2022
@pimeys pimeys assigned pimeys and unassigned pimeys Feb 2, 2022
@janpio janpio added the topic: m:n many-to-many relations label Feb 2, 2022
@pimeys pimeys self-assigned this Feb 8, 2022
@pimeys
Copy link
Contributor

pimeys commented Feb 8, 2022

First nice thing from the formatter, we write this data model:

model A {
  id    String   @id @default(auto()) @map("_id") @db.ObjectId
  b_ids String[] @db.ObjectId
  bs    B[] @relation(fields: [b_ids], references: id)
}

model B {
  id String @id @default(auto()) @map("_id") @db.ObjectId
}

Now save and let the autoformat do it's magic:

model A {
  id    String   @id @default(auto()) @map("_id") @db.ObjectId
  b_ids String[] @db.ObjectId
  bs    B[]      @relation(fields: [b_ids], references: id)
}

model B {
  id  String  @id @default(auto()) @map("_id") @db.ObjectId
  A   A?      @relation(fields: [aId], references: [id])
  aId String? @db.ObjectId
}

Would it be too bad to get rid of this behavior ASAP. If you write the other side before saving, the formatter stays put.

@tomhoule
Copy link
Contributor Author

tomhoule commented Feb 8, 2022

That's the expected behaviour for 1:m for now. I agree we should get rid of it and replace that with code actions, but we should talk with product. I think the code actions wouldn't be a lot of extra work, but it's definitely non trivial extra work.

@pimeys
Copy link
Contributor

pimeys commented Feb 8, 2022

Referential actions in 2-way m:n relations, yay or nay? Ping @dpetrick

@dpetrick
Copy link
Contributor

dpetrick commented Feb 8, 2022

Having this differ from implicit m:n in any form will not be trivial work and is in my book an after-GA task.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/feature A request for a new feature. team/schema Issue for team Schema. topic: m:n many-to-many relations topic: mongodb
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants