Skip to content

Add the ability to set a foreign key on a model to create relationships #296

Closed

Description

@canrozanes

It would be great if developers could be a given the option to create one-to-one relationships using foreign keys. This pattern should feel natural for developers who are familiar with relational databases.

import { factory, primaryKey, foreignKey } from '@mswjs/data'

const db = factory({
  user: {
    id: primaryKey(String),
    publications: manyOf('post'),
  },
  post: {
    id: primaryKey(String),
    userId: foreignKey("user")
    title: String,
  },
})

And then we could get posts belonging to a specific user with the following syntax.

const user = db.user.findFirst({
   where: {
      id: "abc"
   }
})

const userBlogPosts = db.post.findMany({
   where: {
      user_id: user.id
   }
})

Alternatively, the library could implicitly create a userId field on a blogPost if blogPost was declared with a oneOf("user") relationship. I think this is what mirage does.

Activity

  1. kettanaito commented on Dec 1, 2023

    @kettanaito
    Member

    Hi, @canrozanes. Thanks for raising this.

    Tell me, would the usage of transient + derivative properties work for you?

    const db = factory({
      user: {
        id: id(Number),
        // Create a transient "user.city" property.
        // It can be given initial value but it will never
        // be set on the user entities.
        city: transient(oneOf('city')),
        // Derive a public "user.cityId" foreign key
        // from the transient "user.city" one-of relationship.
        cityId: derivative(({ city }) => city.name),
      },
      city: {
        name: id(String),
      },
    })
    
    const user = db.user.create({
      id: 1,
      city: db.city.create({ name: 'London' }),
    })
    
    user.cityId // "London"
    user.city // undefined

    This is a non-existing API (yet).

    I'm tackling this precise use case in the Data rewrite and I could use your feedback.

    Why not use foreignKey()?

    The API you proposed implies that the key given as the value to the user_id property would be identifiable as foreign. But in the context of operations (create/update/etc), those key are taken from the existing extraneous models (like user), and will know nothing about post.userId having to be foreign.

    To put plainly, it becomes problematic to ensure the contract with this kind of API.

  2. locked and limited conversation to collaborators on Dec 2, 2023
  3. converted this issue into a discussion #297 on Dec 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions