0

I am actually experimenting with GraphQL and GraphiQL using a Neo4j DB and using an example from the neo4j_movie_recommendations code. I have a very strange problem which seems to be either javascript- or GraphQL-related. I do a simple query and whereas I can see that the data is available to be returned by the resolver (using console.log) GraphQL return a 'null' value. The following is the code segment:

const resolveFunctions = {
    Query: {
        allVoters(_, params) {
            let session = driver.session();
            let query = "MATCH (voter:Voter) RETURN voter;"
            return session.run(query, params)
                .then(result => {
                    return result.records.map(record => {
                        console.log("Voter: " + JSON.stringify(record))
                        return record.get("voter").properties
                    })
                })
        },

    },
    Voter: {
        memberOf(voter) {
            let session = driver.session(),
                params = { voterid: voter.voterid },
                query = `
                        MATCH (v:Voter)-[:MEMBER_OF]->(g:Group)
                        WHERE v.voterid = $voterid
                        RETURN g.name AS groupname;
                        `
            return session
                .run(query, params)
                .then(result => {
                    return result.records.map(record => {
                        console.log("Group Name " + record.get("groupname")) 
                        return record.get("groupname")
                    })
                })
        },

The console.log show the correct value but GraphiQL shows the name, email..correctly but the memberof field it show 'null'. Can anyone see what I am doing wrong here?

This is the Schema....

export default `
type Voter {
  voterid     : String!
  email       : String!
  name        : String!
  nickname    : [String]
  address     : String
  altAddress  : String
  dob         : String
  profession  : String
  telephone   : String
  gender      : String
  skills      : [String]
  votesIn     : PD
  livesIn     : PD 
  memberOf    : [Group]
}
type Group {
  name        : String
  location    : String
  created     : String
  partof      : Division
}
type PD {
  number      : String
  location    : String
  created     : String
  description : String
  partof      : Division 
}
type Division {
  name        : String
  created     : String
  belongsto   : Constituency
 }
 type Constituency {
  name        : String
  created     : String
  reportsto   : Region
 }
 type Region {
  name        : String
  created     : String
  reportsto   : Exec
 }
 type Exec {
  name        : String
  created     : String
 }

type Query {
  allVoters: [Voter]!
  getVoter(voterid: String!): Voter
  }

  schema {
    query: Query
  }
`;

EDIT...add Resolver Resolver code for getvoter:

  getVoter(_, params) {
            let session = driver.session();
            let query = "MATCH (voter:Voter {voterid: $voterid}) RETURN voter;"
            return session.run(query, params)
                .then(result => {
                    return result.records.map(record => {
                        return record.get("voter").properties
                    })
                })
        },
MichaelE
  • 757
  • 14
  • 42

1 Answers1

2

Whatever your resolver returns has to be the correct type as defined by your schema. If you return the wrong type (a number instead of a string), GraphQL may try to coerce it into the correct type, but in most cases it will just return null.

Your memberOf field is supposed to be an array of Group objects. However, in your resolver, it looks like you return an array of strings instead:

return result.records.map(record => {
  return record.get("groupname")
})

You'll need to utilize the toObject method or otherwise convert the record into an Object with fields matching those specified in your schema for Group.

Daniel Rearden
  • 80,636
  • 11
  • 185
  • 183
  • ...yes Daniel the Group is actually an array of objects but I only need obj.name to be retuned. I was trying to return the name only but apparently I have to return the object and graphql sends what was requested by graphiql......thanks for the heads up. – MichaelE Sep 10 '17 at 08:29
  • I have a followup question on the issue of Graphql returning 'null'. I noticed that unless I set the return type to an array of objects I get 'null'. This may not be a problem if the type could be an array but there are queries where the result could not be an array e.g. getVoter by voterid (where voterid is unique). I am getting a 'null' value if I don't use an array of objects as the return type in the query. i.e. getVoter(voterid: String!): Voter gives null while getVoter(voterid: String!): [Voter] works...can you explain this? – MichaelE Sep 11 '17 at 16:34
  • I can't say for sure without looking at the code, but it sounds like your resolver for getVoter is returning an array. Again, the type returned by your resolver and the type specified for that field in the schema need to match. You can't have `User` as the return type in the schema and return an array of objects in your resolver; and you can't have `[User]` as the return type in your schema and return an object (instead of an array of objects) in your resolver. – Daniel Rearden Sep 11 '17 at 20:05
  • @Daniel....I get that...what I don't get.....is what is the difference returning and array or an object. It seems that graphql sees both as the same. I am expecting just a single object in the result which is what I seems to have here: – MichaelE Sep 11 '17 at 21:09
  • following from above....Voter: {"altAddress":"12 Red Rd, Kin 19","profession":"software engineer","access":"12","address":"10 Main St, Kin","gender":"m","skill s":"system design,programming,network adminstration","dob":"24/10/1960","nickname":["Mike","Mikey"],"voterid":"60041810","name":"Michael Ennis","employer":"connect2","tel": "18765551234","email":"mike123@puppydog.com"} from console logging the stringify view of the object returned. IS it that all objects are trreated as an array and I need to do an array to object conversion?? Or am I missing something very basic? – MichaelE Sep 11 '17 at 21:11
  • Can you edit your question to include the code for your resolver for getVoter? – Daniel Rearden Sep 11 '17 at 21:49
  • @Daniel.....the question was edited to include the getVoter resolver. – MichaelE Sep 12 '17 at 04:05
  • So, in your resolver for `getVoter`, you're taking an array of records, calling `map` on it and then... still returning an array. If the return type in your schema is a single User object, not a List (read: Array) of them, then you need to return a single object in your resolver, not a List (i.e. Array) of them. You should modify your resolver to check if `results.records.length` is > 0, and if so return just the first result of the array, or null if length is 0. – Daniel Rearden Sep 12 '17 at 04:38
  • 1
    ...or use something like [lodash's](https://lodash.com/docs/4.17.4#head) `first()` method – Daniel Rearden Sep 12 '17 at 04:40
  • ok....will do.....Will keep you posted...Thanks – MichaelE Sep 12 '17 at 13:32
  • @Daniel...problem solved....using only the first record returned an object. – MichaelE Sep 14 '17 at 01:34