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

Interface types #83

Open
marktani opened this issue Jan 31, 2017 · 66 comments

Comments

@marktani
Copy link
Contributor

@marktani marktani commented Jan 31, 2017

This feature request serves as central place to discuss how interface types and related operations could look like in Prisma.

@schickling schickling added this to Backlog in Roadmap Feb 9, 2017
@schickling schickling moved this from Backlog to Planned March in Roadmap Feb 9, 2017
@schickling schickling moved this from Planned March to Backlog in Roadmap Feb 9, 2017
@stevewpatterson

This comment has been minimized.

Copy link

@stevewpatterson stevewpatterson commented Feb 27, 2017

Use Case: Add a User interface so multiple models can inherit from it and get authentication out of the box

@marktani

This comment has been minimized.

Copy link
Contributor Author

@marktani marktani commented Feb 27, 2017

Thanks @stevewpatterson, this would be useful! Another use case: interface for createdAt/updatedAt

@marktani

This comment has been minimized.

Copy link
Contributor Author

@marktani marktani commented Feb 27, 2017

The File model could be pulled out as an interface. If you have relations between File and multiple other models, you currently have many null values.

@sedubois

This comment has been minimized.

Copy link

@sedubois sedubois commented Apr 27, 2017

Similarly, I want to create Users and Communities which have Slugs and the slug needs to be unique across all of them. Right now when linking User with Slug and Community with Slug, it creates two relations from Slug to Community and from Slug to User. But only exactly one of these relations should have data at any given time. I understand that interface types would fix this issue.

@amonks

This comment has been minimized.

Copy link

@amonks amonks commented May 15, 2017

Another use case: implement a global permissions system across multiple types.

Here's a gist with an example schema:
https://gist.github.com/amonks/989c815eca601d7ae63ded8fa5f9d530

I don't know how to see notifications for gist comments, but I'm happy to answer questions here.

@MrLoh

This comment has been minimized.

Copy link

@MrLoh MrLoh commented Jun 4, 2017

I'm working on a CRM style application and need either Union Types or Interfaces to model content. I would need a ContentElement interface that can be implemented by a TextNode or a ImageNode, for example so that I can then build the content of my page based on these different elements.

Hope this is coming really soon, as it is so essential for many more complex use cases.

@brandf

This comment has been minimized.

Copy link

@brandf brandf commented Aug 30, 2017

Am I missing an obvious workaround? It seems like any non-trivial model would need this or unions. For example, take this: https://www.graph.cool/docs/faq/graphcool-relation-tag-in-idl-schemas-jor2ohy6uu/ and try to make it so Users can comment on either Posts or Users:

https://gist.github.com/brandf/c8b06dae80b0fd994f06838d69f5437f

@marktani marktani added area/datamodel and removed area/schema labels Sep 17, 2017
@sebasibarguen

This comment has been minimized.

Copy link

@sebasibarguen sebasibarguen commented Sep 21, 2017

+1 this feature request. Our use case is with regards to a Notification model. So an interface would really be helpful to be able to create a relationship between Notification model, and other types of models like Message, Task, Project.

@marktani marktani removed the stage/wip label Sep 25, 2017
@ptpaterson

This comment has been minimized.

Copy link

@ptpaterson ptpaterson commented Sep 26, 2017

@marktani if the stage/wip label is being removed, is it being demoted in priority? Where can we expect it in the roadmap? waiting? I understand that there may be no specific timeline (#165) but a feeling of priority would help.

We see interfaces as filling a major requirement for our application and I'd be jumping at scaphold.io for their integration of interfaces if it didn't look like they were dying as a service. Not to play down many of the other killer things you folks are doing! :)

Is there just a difference in philosophy, like graph.cool would prefer users to strictly normalize the types and use relations to connect them back together? Thanks.

@marktani

This comment has been minimized.

Copy link
Contributor Author

@marktani marktani commented Sep 26, 2017

Hey @ptpaterson, thanks so much for your feedback! This matter absolutely did not decrease in priority and is on our near-future roadmap together with #165. We're in the process of changing the way we communicate and structure our roadmap, and the "stage" labels have become obsolete in the process.

You can now follow along our two-week roadmap in Github projects. The upcoming milestone 1.5 is tracked here: https://github.com/graphcool/graphcool/projects/3. Our immediate focus lies on getting the Resolver + CLI beta out to everyone, as together, they enable completely new workflows and cover a lot of popular feature requests (#213, #39, ...).

Afterwards, I can see us to focus on raw API capabilities (like cascading deletes #47, for example) as well as schema primitives (interfaces, unions, relations, ...), but this is still in flux and remains to be seen 🙂 Rest assured that you are definitely heard though, and I really appreciate your input.

@sorenbs

This comment has been minimized.

Copy link
Member

@sorenbs sorenbs commented Sep 26, 2017

@amonks I love the idea of using Interfaces to simplify permission management!

The other major use case is to have a relation to an interface and be able to use the regular relation filters.

There are several different ways to implement interface support on the database level. Each implementation represents a different set of tradeoffs and it is not obvious that one of them is best in all cases. Providing detailed use cases will help us implement interfaces in a way that supports the most use cases.

If you have a use case for interfaces, please take the time to describe it here :-)

I'll list different implementations here so we can can start a more detailed discussion.

Consider the following data model:

interface User {
  id: String
  name: String
}

type Customer implements User {
  customerNumber: Int
}

type Employee implements User {
  department: String
}

Single table

A single table called User contains fields from the User interface as well as both Customer and Employee:

User

  • id
  • name
  • Customer_customerNumber
  • Employee_department

Individual tables for concrete types

Each concrete type has a dedicated table with both interface fields and type fields:

Customer

  • id
  • name
  • customerNumber

Employee

  • id
  • name
  • department

Individual table for Interface and concrete types

Fields on the interface are in a separate table:

User

  • id
  • name

Customer

  • customerNumber

Employee

  • department
@ptpaterson

This comment has been minimized.

Copy link

@ptpaterson ptpaterson commented Sep 27, 2017

  • TLDR:
    • Big problem
    • Need to arbitrary data linked to arbitrary data
    • Need to bootstrap auth, permissions, integrations, etc.
    • Problem well defined with real-life use cases, but solution not set in stone. Base assumptions need challenged

I only after initially posting here, I discovered that Amazon Aurora is sitting on the back-end. The implementation that I am working on has been focusing on some tricks that No-SQL makes easy. I essentially need an entity-attribute-value model so that the user can create arbitrary connections to all sorts of arbitrary data. SQL is not kind to my data, but JSON is nice.

Understanding the backend a bit more makes me skeptical we can get this running on graphcool and still achieve the efficiency and flexibility of configuration we are shooting for.

Maybe custom database is the first feature I need to look out for :) I'd love to still go through the exercise, though.

Here is the blog-post worthy description of my use case.

Thanks!

@sorenbs

This comment has been minimized.

Copy link
Member

@sorenbs sorenbs commented Sep 27, 2017

Thanks Paul!

I think a helpful exercise for you would be to define all query paths to better understand where your performance constraint will be.

It might turn out that you will be able to store your flexible configuration in a Json field together with a few values that are required for filtering.

If defining a few fields required for filtering is not possible, maybe allowing filtering on data in a Json field is really what you want: #148 This will allow Graphcool to be used in a similar way as MongoDB, but you loose some of the benefits of the GraphQL type system.

@welf

This comment has been minimized.

Copy link

@welf welf commented Oct 12, 2017

Please let define in interface various directives and all types which are implementing that interface should inherit all directives. For example:

interface Product @model {
  id: ID! @isUnique
  vendor: Vendor! @relation(name: "VendorProducts")
  orders: [Order!]! @relation(name: "OrderProducts")
  name: String!
  description: String
  slug: String! @isUnique
  price: Float! @relation(name: "ProductPrice")
  images: [Image!]! @relation(name: "ProductImages")
  belongsToCollections: [Collection!] @relation(name: "CollectionProducts")
  isPublished: Boolean! @defaultValue(value: false)
  materialInfo: MaterialInfo!
  colorInfo: ColorInfo!
  createdAt: DateTime!
  updatedAt: DateTime!
}

All types implementing interface Productshould be @model types, all isPublished fields in those types should have @defaultValue(value: false), all images fields should have @relation(name: "ProductImages") etc.

@lucid-kyle

This comment has been minimized.

Copy link

@lucid-kyle lucid-kyle commented Apr 17, 2018

@marktani - any update on this issue? We would love to be able to push forward with Prisma, but this is our primary blocker at the moment. Seems like this request has been on the table for over a year, and the public roadmap from #2142 has no content at all, so it's a bit hard to hold out hope at the moment...

@rohitghatol

This comment has been minimized.

Copy link

@rohitghatol rohitghatol commented Apr 24, 2018

@marktani - Just wondering if there any active development on this issue. Any indication if this will be fixed or not, will help us a lot.

@jhalborg

This comment has been minimized.

Copy link

@jhalborg jhalborg commented May 18, 2018

+1 for an update or ETA. I know you're super busy with a bunch of stuff, but it's been almost 2 months now since the last team update on this issue. Also +1 for @adamjking3 's use case, where users can have more than one role, and interfaces would be a nice way of achieving this. A simple admin-boolean or even a user enum doesn't solve more complex requirements

@FrankSandqvist

This comment has been minimized.

Copy link

@FrankSandqvist FrankSandqvist commented Jun 7, 2018

+1 ETA

Starting to build a database using a workaround now, but there is a lot of verbosity... And there is no way to properly enforce required fields

@schickling

This comment has been minimized.

Copy link
Member

@schickling schickling commented Jul 26, 2018

While there is no concrete update yet for the timeline of this feature, it's definitely high on our priority list.

Also, as mentioned in #2114, I think inheritance is a really interesting concept to consider as well for data modeling when implementing interfaces & type polymorphism.

@viztor

This comment has been minimized.

Copy link

@viztor viztor commented Aug 13, 2018

Anyone working on this issue? Really need it for some higher level architecturing of the app.

@schickling

This comment has been minimized.

Copy link
Member

@schickling schickling commented Aug 13, 2018

It would be very helpful for us to see some examples of the data model you'd like to design (assuming it would work). Having many different examples helps us to better design the capabilities and syntax of this feature.

cc @viztor @FrankSandqvist @jhalborg @rohitghatol ...

@kbrandwijk

This comment has been minimized.

Copy link
Contributor

@kbrandwijk kbrandwijk commented Aug 13, 2018

Gonna copy&paste an example from one of the earlier comments:

interface Vehicle { numberOfWheels: Int }
type Car implements Vehicle {
   numberOfWheels: Int
   horsePower: Int
}
type Bike implements Vehicle {
   numberOfWheels: Int
   color: String
}

type User {
  vehicle: Vehicle
}
@viztor

This comment has been minimized.

Copy link

@viztor viztor commented Aug 13, 2018

@schickling a prisma pseudo-schema of a virtual application might be

interface Transactable {
  id: ID @unique
  transactions: [Transactions!]!
}

interface Transactions {
   id: ID @unique
   subject: Transactable!
}

type TransferOwnership implements Transactions {
  id: ID @unique
}

type Car implements Transactable {
  id: ID @unique
  transactions: [Transactions!]!
}
@tibotiber

This comment has been minimized.

Copy link

@tibotiber tibotiber commented Aug 13, 2018

example of the schema I'm using:

interface Conviction {
  id: ID!
  fromUpdate: BucketUpdate!
  row: Int!
  assetClass: AssetClass!
  isin: String!
  ticker: String
  name: String!
  inceptionDate: String
  prr: Int!
  ltv: Int!
  archived: Boolean!
  restricted: Boolean!
}

type Equity implements Conviction {
  # interface
  id: ID!
  fromUpdate: BucketUpdate!
  row: Int!
  assetClass: AssetClass!
  isin: String!
  ticker: String!
  name: String!
  inceptionDate: String!
  prr: Int!
  ltv: Int!
  archived: Boolean!
  restricted: Boolean!
  # custom fields
  threePtUpdateLink: String
  stockReportsLink: String
  tradeNotesLink: String
  threePtUpdate: String
}

type Fund implements Conviction {
  # interface
  id: ID!
  fromUpdate: BucketUpdate!
  row: Int!
  assetClass: AssetClass!
  isin: String!
  ticker: String
  name: String!
  inceptionDate: String
  prr: Int!
  ltv: Int!
  archived: Boolean!
  restricted: Boolean!
  # custom fields
  factsheetLink: String
}

type Bond implements Conviction {
  # interface
  id: ID!
  fromUpdate: BucketUpdate!
  row: Int!
  assetClass: AssetClass!
  isin: String!
  ticker: String
  name: String!
  inceptionDate: String!
  prr: Int!
  ltv: Int!
  archived: Boolean!
  restricted: Boolean!
  # custom fields
  tradeNotesLink: String
  threePtUpdate: String
  coco: Boolean
}
@goulderb

This comment has been minimized.

Copy link

@goulderb goulderb commented Aug 13, 2018

My team has need of this to standardize a few things throughout our data model:

  1. We include createdAt and updatedAt on every type to make these fields accessible
  2. We also include the ability to add key/value pair attributes to any type so users can define their own fields to store non-standard data

Our ideal SDL would look something like this:

type Attribute {
  id: ID! @unique
  createdAt: DateTime!
  updatedAt: DateTime!
  name: String!
}

type AttributeValue {
  id: ID! @unique
  createdAt: DateTime!
  updatedAt: DateTime!
  attribute: Attribute!
  value: String!
}

interface Common {
  id: ID! @unique
  createdAt: DateTime!
  updatedAt: DateTime!
  attributes: [AttributeValue!]!
}

type Customer implements Common {
  # Includes all fields from the interface plus the field below
  name: String!
}

So, the "Customer" type would get expanded to:

type Customer implements Common {
  id: ID! @unique
  createdAt: DateTime!
  updatedAt: DateTime!
  attributes: [AttributeValue!]!
  name: String!
}
@jhalborg

This comment has been minimized.

Copy link

@jhalborg jhalborg commented Aug 13, 2018

Another use case:

A timeline for a user, where a TimelineEvent can be one of multiple types, i.e. a UserComment, UserUpload, UserStatusChanged and so forth, so that a client can show a paginated view of TimelineEvents, showing a different view component based on the implementation of the TimelineEvent

@stigi

This comment has been minimized.

Copy link

@stigi stigi commented Aug 13, 2018

My use case is in a chat application where a Message has a Payload which can be of a concrete type TextPayload or ImagePayload and other payload types that I’ll add later on.

@jide

This comment has been minimized.

Copy link

@jide jide commented Sep 11, 2018

My use case :
We have a video editing app where "cues" can be placed along a timeline. These cues have a reference to "contents", and these contents may be of different types, with different fields: Movie, Music, Bio...

@peterschussheim peterschussheim referenced this issue Sep 22, 2018
0 of 19 tasks complete
@mavilein

This comment has been minimized.

Copy link
Member

@mavilein mavilein commented Nov 1, 2018

I have just published a spec that touches on this topic. We would love to hear your feedback on this one.

@stale

This comment has been minimized.

Copy link

@stale stale bot commented Jan 8, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 10 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the status/stale label Jan 8, 2019
@bizmedia

This comment has been minimized.

Copy link

@bizmedia bizmedia commented Jan 10, 2019

Period: interface for startDate/endDate

@impowski

This comment has been minimized.

Copy link

@impowski impowski commented Mar 19, 2019

Any update on this?

@ianjanicki

This comment has been minimized.

Copy link

@ianjanicki ianjanicki commented Mar 26, 2019

@schickling, I see in your FAQ for Datamodel 1.1 that Polymorphic relations will not be part of Datamodel 1.1, and will be addressed later. Could you inform this thread as to where you see it in your priority list? Is this something you will accomplish this year? Next quarter? etc.

I think many of us on this thread will find it helpful to properly plan ahead, and perhaps implement a work-around before a stable version is released.

@divyenduz

This comment has been minimized.

Copy link
Contributor

@divyenduz divyenduz commented Mar 27, 2019

@ianjanicki - we are currently working on large architectural improvements to the Prisma query engine. These improvements will bring a number of benefits, including better performance and an architecture that support advanced features such as Polymorphic Relations. We expect this work to complete some time in Q3.

Datamodel 1.1 is a small intermediate step that prepares us for the real jump that will happen later this year.

Polymorphic Relations continue to be a high priority feature for us, but I can't give you a more precise timeline.

We recently introduced a roadmap that details our ongoing work. We update this roadmap with every release (2 week cycles).

Thanks for remaining a passionate Prisma user!

@HuzaifaaAli

This comment has been minimized.

Copy link

@HuzaifaaAli HuzaifaaAli commented Sep 25, 2019

Hi Guys, So I tried implementing an interface that had some basic fields that need to be implemented by some type but when I implemented that interface on some type, it didn't restrict the type to have all the fields of interface and I was able to skip few interface fields and deploy. I want to know is this issue related to Prisma or I am doing something wrong. Thanks in advance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Roadmap
Backlog
You can’t perform that action at this time.