gqlify icon indicating copy to clipboard operation
gqlify copied to clipboard

Support Firestore sub-collections

Open jthegedus opened this issue 6 years ago • 5 comments

Is your feature request related to a problem? Please describe. It is unclear at this time how to use firestore subcollections with @gqlify/firestore.

Describe the solution you'd like I imagine creating the type like so:

type Book @GQLifyModel(dataSource: "firestore", key: "books") {
  id: ID! @unique @autoGen
  title: String!
  author: Author!
}

type Author @GQLifyModel(dataSource: "firestore", key: "books/*/authors") {
  id: ID! @unique @autoGen
  name: String!
}

and then updating or creating a field requires a where params list like so:

type AuthorWhereUniqueInupt {
  bookId: ID!
  authorId: ID!
}

or could we use a Firestore sub-collection specific where param where the id field is the document path? Eg:

type AuthorWhereUniqueInupt {
  parentPath: String!
  authorId: ID!
}

where the parentPath is more like the current path usage in Firestore SDK:

variables = {
  parentPath: `books/${someBookId}`
}

Issues with this solution:

  • how do we query sub-collections?
  • what syntax do we use to represent the document in the collection/document/collection path key? That is, does books/*/authors work well enough?

Describe alternatives you've considered Using root-level Firestore collections is a viable alternative since relationships/foreign-keys are already supported. There are performance implications with doing so though where sub-collections would be desirable.

Additional context Just starting a discussion of the idea :smile:

jthegedus avatar Jan 28 '19 04:01 jthegedus

@jthegedus Wow!

Thanks for the detailed information!

IMO, in GQLify, @GQLifyModel defines a root level data-model, so maybe we can introduce different directive like GQLifySubResource. It can work for Embedded Documents in MongoDataSource as well.

type Book @GQLifyModel(dataSource: "firestore", key: "books") {
  id: ID! @unique @autoGen
  title: String!
  author: Author! @GQLifySubResource(key: "authors")
}

type Author {
  id: ID! @unique @autoGen
  name: String!
}

GQLifySubResource(key: string)

For firestore, key parameter indicates the name of subcollection. GQLify will know the key should be postfixed after its parent GQLifyModel key and makes it /books/{bookId}/authors/{authorId} if GQLify wants to locates the subcollection document.

GQLify can generate create/update/delete mutations for GQLifySubResource field. For example, createAuthorInBook updateAuthorInBook and deleteAuthorInBook.

As for query, GQLify can generate query like authorInBook to be able to find one author for specified book with bookId and authorId.

Let me know how you think about GQLifySubResource directive 😄

wwwy3y3 avatar Jan 29 '19 04:01 wwwy3y3

Brilliant idea! Much more flexible across dataSources and therefore useful. I would certainly be happy with this new directive, especially because the association between the two types is more clear, and the type of association is more clear than a "normal" GraphQL type.

Do you foresee any issues with the naming convention of: createAuthorInBook, updateAuthorInBook etc? Deep nesting could get rather messy, do you have any other ideas here? (I haven't thought of anything yet :wink: )

Some more ideas to think about: presumably the SubResource is always contained in the same datasource as the parent type? Would there be a need for otherwise?

jthegedus avatar Jan 29 '19 04:01 jthegedus

Well, regarding the naming convention, I doubt anyone would put subcollection so nested (ex: createAuthorInIssueThreadCommentSubcomment) that it becomes a problem. If it really becomes a problem, we can always add another api to deal with it (ex: createSubResource(path: string, input: Input)) in the future.

As for SubResource data-source, it would be simpler to understand and also implement if we defined it to be contained in the same data-source as the parent type.

wwwy3y3 avatar Jan 30 '19 02:01 wwwy3y3

@wwwy3y3 I agree completely, just wanted to raise the thoughts.

I think createSubResource(path: string, input: Input) is a great solution should it become a heavily requested feature.

jthegedus avatar Jan 30 '19 02:01 jthegedus

@jthegedus We're always glad to hear thoughts from the community 😄

Please don't hesitate to share your thoughts.

Hope to hear more from you when we release Canner v3 in a few days later.

wwwy3y3 avatar Jan 30 '19 02:01 wwwy3y3