Skip to content
This repository was archived by the owner on Sep 3, 2021. It is now read-only.

question: can the database schema be different from the public schema? #104

Closed
jorroll opened this issue Sep 15, 2018 · 3 comments
Closed

Comments

@jorroll
Copy link

jorroll commented Sep 15, 2018

Is it possible for the database graphql schema to be different from the public facing schema?

Example: in the database schema, a person has many primary email addresses

type Person {
  primaryEmailAddresses: [EmailAddress!]!
}

In the public facing schema, a person only has one primary email address:

type Person {
  primaryEmailAddress: EmailAddress
}

If someone requests a person, unbenounced to them, their user id is used to filter the email address field and return zero or one email address:

MATCH (this)-[:PERSON_PRIMARY_EMAIL_ADDRESS]->(email)<-[:VIEWABLE_BY_USER]-(:User {id: $userId}) RETURN email

This might be accomplished by either

A) having neo4j-graphql-js use a different schema from the public facing one, allowing for

resolver: (object, params, context, resolveInfo) => {
  if (!context.user) return null;

  return neo4jgraphql(object, {id: context.user.id}, ctx, resolveInfo);
  //                            ^^ again, the public facing schema doesn't accept an "id" param
}

B) letting the user resolve a particular node by dynamically passing in the cypher for it. Something like:

resolver: (object, params, ctx, resolveInfo) => {
  if (!context.user) return null;

  const cypher = {
    statement: "MATCH (this)-[:PERSON_PRIMARY_EMAIL_ADDRESS]->(email)<-[:VIEWABLE_BY_USER]-(user :User {id: $userId}) RETURN email",
    params: {userId: context.user.id},
  }

  return neo4jgraphql(cypher, resolveInfo);
}

In scenario b, this cypher statement would be batched and sent along with all the other "auto generated" queries. This would probably be my preferred option, as it would allow for the most freedom.

Thanks!

@johnymontana
Copy link
Contributor

Hey @thefliik - this is a really good use case. Thanks for opening the issue.

I see this as an extension of our initial middleware support. If we by convention passed through a specific object from the context as parameters to the @cypher Cypher query then your example above would be possible with just a @cypher directive and would not require a custom resolver implementation.

So the middlware would just have to create the appropriate cypherParams object in the context.

If those values were available as parameters in the @cypher Cypher query, would that solve your issue?

@jorroll
Copy link
Author

jorroll commented May 13, 2019

@johnymontana thanks for the reply! I'm very sorry I missed it.

Even though this is super late: I think your proposal would address the example cited in this issue. You are saying that a graphql schema might have something like:

type Person {
  @cypher(statement: "MATCH (this)-[:PERSON_PRIMARY_EMAIL_ADDRESS]->(email)<-[:VIEWABLE_BY_USER]-(:User {id: $cypherParams.userId}) RETURN email")
  primaryEmailAddress: EmailAddress
}

Where I would have some ability to define the the$cypherParams param and pass it to the neo4jgraphql middleware (or something similar)? I think that would do the trick.

@johnymontana
Copy link
Contributor

We've now added the ability to inject values from the context into @cypher directive Cypher statements as Cypher parameters. See the docs on this here

For example:

type Query {
  currentUser: User @cypher(statement: """
    MATCH (u:User {id: $cypherParams.currentUserId})
    RETURN u
  """)
}

Fixed by #200

# for free to subscribe to this conversation on GitHub. Already have an account? #.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants