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

Creation of many-to-many relationship when inserting a new record #456

Open
ryusei-48 opened this issue May 10, 2024 · 2 comments
Open

Creation of many-to-many relationship when inserting a new record #456

ryusei-48 opened this issue May 10, 2024 · 2 comments

Comments

@ryusei-48
Copy link

Hello, I am new to the Rust language itself.
I am a beginner in the Rust language itself. I am currently learning and developing an application in TAURI.

https://prisma.brendonovich.dev/writing-data/create#create
I have run into a bit of a problem and am stumped.
The documentation above explains how to create a relationship, but in this example, if there are pre-existing posts, you can specify the ID of the post to be associated with when creating a comment.

However, if I have a "bookmark" and a "tags" table, for example, and they are in a many-to-many relationship with each other, how can I insert both IDs in the intermediate table when inserting a new bookmark?

The following is the current situation

model Bookmark {
  id            Int         @id @default(autoincrement())
  type          String
  content       String
  update_at     DateTime    @updatedAt
  register_at   DateTime    @default(now())
  Tags          BookmarkTag[]
}

model Tag {
  id            Int             @id @default(autoincrement())
  name          String          @unique
  icon          Bytes?
  icon_type     String?
  update_at     DateTime        @updatedAt
  register_at   DateTime        @default(now())
  TagStructure  TagStructure[]
  Bookmarks     BookmarkTag[]

  @@index([name])
}

model BookmarkTag {
  bookmark_id   Int
  tag_id        Int
  bookmark      Bookmark    @relation(fields: [bookmark_id], references: [id], onDelete: Cascade)
  tag           Tag         @relation(fields: [tag_id], references: [id], onDelete: Cascade)
  @@id([bookmark_id, tag_id])
}

According to the type of prisma.rs generated, this is how it is written, but "BookmarkIdTagIdEquals()" does not know the ID of the record in the "bookmark" table that is newly inserted.

let result = state.storage.bookmark().create(
      data_json.rtype, data_json.content, vec![
        bookmark::tags::connect(vec![bookmark_tag::UniqueWhereParam::BookmarkIdTagIdEquals(5 /* don't know */, 2)])
      ]
    ).exec().await.map_err(|e| e.to_string())?;

Is there any better way to write prepared?
Thank you very much.

@Brendonovich
Copy link
Owner

Brendonovich commented May 10, 2024

Two things:

  1. Right now you can only make records for 1 model at a time, so first make your bookmark and second make your relation record. You can't connect in this case since there's no BookmarkTag record that already exists to connect to. Creating nested relations is being tracked in Nested create #44
  2. Don't use UniqueWhereParam, instead use bookmark_tag::bookmark_id_tag_id(...)

@ryusei-48 ryusei-48 reopened this May 11, 2024
@ryusei-48
Copy link
Author

Thank you for your response.
I edited the code as advised and as a result I was able to build the relationship, but still had problems.

Below is the current prisma schema file.

model Bookmark {
  id              Int           @id @default(autoincrement())
  type            String
  url             String?       @unique
  domain          String?
  title           String?
  description     String?
  icon            Bytes?
  icon_type       String?
  thumbnail       Bytes?
  thumbnail_type  String?
  content         String?
  update_at       DateTime      @updatedAt
  register_at     DateTime      @default(now())
  Tags            BookmarkTag[]

  @@index([url, type])
}

model Tag {
  id            Int             @id @default(autoincrement())
  name          String          @unique
  icon          Bytes?
  icon_type     String?
  update_at     DateTime        @updatedAt
  register_at   DateTime        @default(now())
  TagStructure  TagStructure[]
  Bookmarks     BookmarkTag[]

  @@index([name])
}

model BookmarkTag {
  bookmark_id   Int
  tag_id        Int
  bookmark      Bookmark    @relation(fields: [bookmark_id], references: [id], onDelete: Cascade)
  tag           Tag         @relation(fields: [tag_id], references: [id], onDelete: Cascade)
  @@id([bookmark_id, tag_id])
}

I initially attempted to set up a relationship using the following procedure, but while the code runs fine, nothing is actually inserted into the "BookmartTag" intermediate table.

pub struct Create {
    pub tags: Vec<i32>, pub domain: Option<String>,
    pub rtype: String, pub content: Option<String>,
    pub title: Option<String>, pub url: Option<String>,
    pub description: Option<String>, pub icon: Option<Vec<u8>>,
    pub icon_type: Option<String>, pub thumbnail: Option<Vec<u8>>,
    pub thumbnail_type: Option<String>
  }

let parse_data: structs::bookmark::Create = data.create.unwrap();
    let result = state.storage.bookmark().create(
      parse_data.rtype, vec![
        bookmark::title::set( parse_data.title ),
        bookmark::description::set( parse_data.description ),
        bookmark::url::set( parse_data.url ),
        bookmark::icon::set( parse_data.icon ),
        bookmark::icon_type::set( parse_data.icon_type ),
        bookmark::thumbnail::set( parse_data.thumbnail ),
        bookmark::thumbnail_type::set( parse_data.thumbnail_type ),
        bookmark::domain::set( parse_data.domain ),
        bookmark::content::set( parse_data.content )
      ]
    ).exec().await.map_err(|e| e.to_string())?;

let _updated = state.storage.bookmark().update(bookmark::id::equals( result.id ), vec![
      bookmark::tags::set( parse_data.tags.iter().map(|&id| {
        bookmark_tag::bookmark_id_tag_id(result.id, id)
      }).collect())
    ]).with(bookmark::tags::fetch(vec![])).exec().await.map_err(|e| e.to_string())?;*/

We then tried to insert the data directly into the intermediate table as follows with success. This method is currently used.

for id in parse_data.tags.clone() {
      state.storage.bookmark_tag().create(
        bookmark::id::equals( result.id ), tag::id::equals(id), vec![]
      ).exec().await.map_err(|e| e.to_string())?;
    }

Is this a bug?
Or am I doing something wrong?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants