Open calendardays opened 5 years ago
Hey @calendardays -
You are correct that GraphQL schema directives are not exposed via introspection, this is part of the GraphQL specification. There is a discussion currently about whether this should be the case.
I wonder though if for your use case inspecting the Neo4j database is what you want, instead of the GraphQL API. You can accomplish this via the call db.schema.nodeTypeProperties()
and call db.schema.relTypeProperties()
procedures.
That's an interesting discussion. Even if a spec extension that allows explicitly exposing chosen directives to introspection doesn't materialize, I think I was originally imagining something similar to what @deprecated
does, exposing the arguments of the @relation
directive by adding properties. For example, the query...
{
__type (name: "Book") {
fields {
name
type {
kind
name
ofType {
kind
name
}
}
_isRelation
_relationName
_relationDirection
}
}
}
...could return...
{
"data": {
"__type": {
"fields": [
{
"name": "title",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
"_isRelation": false,
"_relationName": null,
"_relationDirection": null
},
{
"name": "Editor",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "Person",
}
}
"_isRelation": true,
"_relationName": "EDITS",
"_relationDirection": "IN"
},
{
"name": "Author",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "Person",
}
}
"_isRelation": true,
"_relationName": "AUTHORS",
"_relationDirection": "IN"
}
]
}
}
}
That may be a bad idea, but that's what I was picturing.
The operation I was hoping to perform was "given a list of node types, produce a list of all relations in the database that exist among those node types." The information I think I need, then, is a set of correspondences {NodeTypeA, RelationType, NodeTypeB, Direction}
.
It looks like those correspondences can be derived from call db.schema.visualization()
, which could be put into a @cypher
directive... I'm not sure exactly how this would go, but it's an interesting avenue to try.
Thanks!
Does graphql^15.x.x introspection has directives on field level now? @calendardays I have a similar use case for identifying relationships on a type in client. Just wondering if you were able to solve it.
Hi @harshil4076, I haven't touched this in a long enough that I'd forgotten my own solution. Looking back, it appears I settled on making a very comprehensive (perhaps redundant) schema, with type names chosen to make everything very explicit to the point where I could do parsing and string comparisons on type names. This way, I could get everything I needed by analyzing the schema that pops out of an introspectionQuery
.
Partial schema to demonstrate:
type Person {
# Node Properties
name: String!
# Related Nodes
ThisAuthorsBookNode: [Book] @relation(name: "AUTHORS", direction: "OUT")
ThisEditsBookNode: [Book] @relation(name: "EDITS", direction: "OUT")
# Relations
ThisAuthorsBookRelation: [PersonAuthorsBook]
ThisEditsBookRelation: [PersonEditsBook]
}
type Book implements Publication & Product {
# Node Properties
title: String!
# Related Nodes
PersonAuthorsThisNode: [Person] @relation(name: "AUTHORS", direction: "IN")
PersonEditsThisNode: [Person] @relation(name: "EDITS", direction: "IN")
# Relations
PersonAuthorsThisRelation: [PersonAuthorsBook]
PersonEditsThisRelation: [PersonEditsBook]
}
type PersonAuthorsBook @relation(name: "AUTHORS") {
from: Person
to: Book
}
type PersonEditsBook @relation(name: "EDITS") {
from: Person
to: Book
}
The
@relation
directive is useful for taking relations in an underlying Neo4j database and encoding them in a GraphQL schema. I'd like to be able to derive the type names (labels) of relations in the database from a schema object, as well as the relation direction. This seems like a natural thing to do, because the type names and directions are passed as arguments to the@relation
directive.For example, part of a GraphQL schema might be:
I can obtain a schema object by doing something like this:
But currently, neither "EDITS" nor "AUTHORS" (in any capitalization pattern) is to be found in the returned schema. Correct me if I'm wrong, but I've confirmed that those strings don't appear in a
JSON.stringify
printout of the schema object.My use case:
I'm working on a web-based interface for importing new data, in spreadsheet form, to an underlying Neo4j database, using GraphQL. When a user provides a spreadsheet, I can use introspection on the schema to generate a list of all node types (represented as identically-named GraphQL types) and their properties (fields), so that the user can assign which properties correspond to which columns of data in the sheet. I would also like to be able to automatically generate a list of all the relations in the database so that the user can check boxes for which ones should be created based on the new data. Currently, I can at least generate a list of pairs such as "Book-Person", but I cannot derive the relation names ("Edits" and "Authors") from schema introspection.
If any given pair of node types corresponded to at most one relation type (e.g., every Book-Person relation has type AUTHORS), then this wouldn't be an issue, so I've selected the "Edits" vs. "Authors" example to highlight the problem. A user could come with Column A = titles and Column B = names, and I don't have a good way to help them choose which of these two relation types should be created during data import, because schema introspection doesn't give me access to the terms "Edits" and "Authors".
I've been thinking about this in terms of the
@relation
field directive. Similar logic might apply to the@relation
type directive, or maybe clever naming patterns or extra fields in the schema allow for an easier workaround in that case.