Adding a relationship with properties breaks other queries

582 views Asked by At

I was using the GRAND stack starter and recently went through upgrading my packages and the Neo4j database to match the current versions identified in the GRAND starter kit.

This seems to have broken my most basic queries. I am creating a fairly simple demo database for exploration containing recipes. I have a node with a recipe on it that includes a name, instructions, and time.

This node also has relationships that indicate what kind of meal it is and how hard it is. You can see that below:

Illustraing simple relationships

This returns just fine with my query on the front-end or in the Graphql Playground with the following query:

query($searchQuery: String = "baked") {
  RecipesBySubstring(searchQuery: $searchQuery) {
    name
    time
    instructions
    ingredients {
      name
      quantity
    }
    mealtype {
      type
    }
    difficulty {
      value
    }
  }
}

The actual definition in my graphql-schema.js file looks like this:

  RecipesBySubstring(searchQuery: String): [Recipe] @cypher(statement:
    "MATCH (r:Recipe) WHERE toLower(r.name) CONTAINS toLower($searchQuery) OR toLower(r.time) CONTAINS toLower($searchQuery) RETURN r ORDER BY r.name ASC")

However as soon as I try to create a relationship that has properties, it fails to return any results using these exact queries. I create a relationship with this query:

MATCH (r:Recipe{name:"baked spaghetti"}),(i:Ingredient{name:"beef"})
CREATE (r)-[c:Contains{quantity:"1 pound"}]->(i)
RETURN r,i,c

And it adds it to the database just fine.

Relationship successfully added.

I also have defined my ingredients in my graphql-schema.js as follows:

type Ingredient {
  name: String!
  quantity: String @cypher(statement:"MATCH (:Recipe)-[c:Contains]-(this) RETURN q.quantity")
  recipe: Recipe
}

Up until I upgraded things, these items were all working great. I had multiple recipes sharing ingredients I could query off of, querying a recipe would return all the ingredients and quantities as needed. You can see the previous iteration of the database in the following image and I can confirm this did return in the graphql playground and my front-end: Working relationships with properties

So I am kind of stumped what might have happened or if there is a new way I am suppose to be doing these things. I could roll back but since this is a learning process I want to keep my packages and databases up-to-date to go through these challenges.

The full error coming from the GraphQL Playground when attempting to query an node that has a relationship with properties is as follows:

{
  "data": {
    "RecipesBySubstring": null
  },
  "errors": [
    {
      "message": "Failed to invoke function `apoc.cypher.runFirstColumn`: Caused by: org.neo4j.cypher.internal.util.v3_4.SyntaxException: Variable `q` not defined (line 1, column 93 (offset: 92))",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "RecipesBySubstring"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "code": "Neo.ClientError.Procedure.ProcedureCallFailed",
          "name": "Neo4jError",
          "stacktrace": [
            "Neo4jError: Failed to invoke function `apoc.cypher.runFirstColumn`: Caused by: org.neo4j.cypher.internal.util.v3_4.SyntaxException: Variable `q` not defined (line 1, column 93 (offset: 92))",
            "",
            "    at captureStacktrace (E:\\Recipe Snap\\grand-stack-starter\\api\\node_modules\\neo4j-driver\\lib\\v1\\result.js:200:15)",
            "    at new Result (E:\\Recipe Snap\\grand-stack-starter\\api\\node_modules\\neo4j-driver\\lib\\v1\\result.js:73:19)",
            "    at Session._run (E:\\Recipe Snap\\grand-stack-starter\\api\\node_modules\\neo4j-driver\\lib\\v1\\session.js:116:14)",
            "    at Session.run (E:\\Recipe Snap\\grand-stack-starter\\api\\node_modules\\neo4j-driver\\lib\\v1\\session.js:95:19)",
            "    at _callee$ (E:\\Recipe Snap\\grand-stack-starter\\api\\node_modules\\neo4j-graphql-js\\dist\\index.js:80:28)",
            "    at tryCatch (E:\\Recipe Snap\\grand-stack-starter\\api\\node_modules\\regenerator-runtime\\runtime.js:62:40)",
            "    at Generator.invoke [as _invoke] (E:\\Recipe Snap\\grand-stack-starter\\api\\node_modules\\regenerator-runtime\\runtime.js:296:22)",
            "    at Generator.prototype.(anonymous function) [as next] (E:\\Recipe Snap\\grand-stack-starter\\api\\node_modules\\regenerator-runtime\\runtime.js:114:21)",
            "    at step (E:\\Recipe Snap\\grand-stack-starter\\api\\node_modules\\babel-runtime\\helpers\\asyncToGenerator.js:17:30)",
            "    at E:\\Recipe Snap\\grand-stack-starter\\api\\node_modules\\babel-runtime\\helpers\\asyncToGenerator.js:35:14"
          ]
        }
      }
    }
  ]
}
1

There are 1 answers

1
William Lyon On BEST ANSWER

The error is a Cypher syntax error. The query used in your @cypher directive on Ingredient.quantity in your GraphQL schema definition is incorrect, it is referring to a variable q that has not been defined. Since quantity is a property on the Contains relationship and your query is binding c to that relationship your @cypher directive query should be

quantity: String @cypher(statement:"MATCH (:Recipe)-[c:Contains]-(this) RETURN c.quantity")

Also, v1.0.1 of neo4j-graphql-js introduces better relationship type support so you don't have to use @cypher directives to access relationship properties, instead you can just define a relationship type: https://grandstack.io/docs/neo4j-graphql-js.html#relationships-with-properties