0
votes

I am using Neo4j 3.2 and graphql in nodejs. I have 2 types "School" and "Class" with following relationship:

(School)-[:has]->(Class)// 1 school can have multiple classes .

Their data structure along with relationship in neo4j is similar to the one below:

School{ id: 001, label: "School A"}-[:has]->Class{ id: 001, label: "Class 1"}
School{ id: 001, label: "School A"}-[:has]->Class{ id: 002, label: "Class 2"}

What I am trying to do is to pull the count of classes present in a particular school and store/append this count value (as property) in already existing 3rd type "SchoolData" which has following relation with "School" type. (SchoolData)-[:of]->(School). So as from above example, the count of classes i.e. 2 needs to be stored in "SchoolData" for School A. i.e.

(SchoolData{ classCount: 2, label: "School A", otherInfo: "Already exisiting values are present here" })-[:of]->(School { id: 001, label: "School A"})

I have made a mutation to do so, but the data returned after generating count through cypher is not being stored in the node "SchoolData". Can some one please let me know why i am getting null and how should I handle it?

Here is my graphql type along with the mutation query:

type SchoolData{
   classCount: Int
   label: String
   otherInfo: String
}
// mutation query
countThenAddIntoSchoolData( schoolID: String! ): SchoolData

Here is my resolver mutation query of graphql:

 countThenAddIntoSchoolData(_, params) {
  let classCount = `MATCH (s:School {id: $schoolID })-[:has]->(c:Class) return count(c) as c`;
  let label = `MATCH (s:School {id: $schoolID })-[:has]->(c:Class) return s.label as s`;


  let sessionData = {};
  return Promise.all([
      getDBSession(sessionData).run(classCount, params),
      getDBSession(sessionData).run(label, params)
    ]).then((result) => {
      let data = {
        classCount: result[0].records.map(record => {
          return record.get('c');
        }),
        label: result[1].records.map(record => {
          return record.get('s');
        })
      };
      return data; // till here, it works fine
    }).then((data) => {
      let saveQuery = `MATCH (sd:SchoolData)-[:of]->(s:School {id: $schoolID })
                        SET sd += $data `
      return getDBSession(sessionData).run(saveQuery, params);

    })
    .catch((e) => {

    });
}

Note: getDBSession is already configured in my another file (database.js).

Here is my object "data" returned from Promise.all:

    data:{ 
   classCount: [ Integer { low: 2, high: 0 } ],
   label: [ 'School A' ]
  }

// The solved final query (thenable part):

    .then((data) => {

       params['data'] = {
         classCount: data.classCount[0],
         label: data.label[0]
       };
          let saveQuery = `MATCH (sd:SchoolData)-[:of]->(s:School {id: 
                           $schoolID })
                            SET sd += $data `
          return getDBSession(sessionData).run(saveQuery, params);

        })
        .catch((e) => {

        });
    }

And here is the output of the "SchoolData":

  {
   "classCount": 2,
   "label": "School A"
   "otherInfo": "Details of relevant school..."
  }
1
When the Promise returned by getDBSession(sessionData).run(saveQuery, params) resolves, what does the resulting object look like?Daniel Rearden
it ireturns null, and no any properties are being appended for schoolData node. BTW, Thanks a lot for your effort. Really appreciable !Code Reactor
FYI, And I have added the object "data" returned aboveCode Reactor

1 Answers

1
votes

I think you might need to convert the Integer object returned from the first query into a JavaScript Number before passing it as a parameter in the second query:

return record.get('c').toInt()

The JavaScript Neo4j driver uses a custom Integer object to represent integers, since there is no Int type in JavaScript.

Can you add a console.log(e) in your catch so you can see any errors that occur?