1

I have just started learning graphql and I created a query that returns a list of first 10 closed issues along with some attributes. To my surprise, the response objects in JSON that I get are sometimes empty and sometimes they are non empty. The response is random.I have also tested with postman. Since I am mapping the json response to Java classes using jackson and performing some operations, exceptions are thrown when handling empty objects.

1)Basically, I want a non-empty objects of closed issues. Is anything wrong in the query? If yes, can somebody tell the correct query?

2) Also, I would like to know the logic behind returning empty node objects

Query Used


{
  search(first: 20, type: ISSUE, query: "created:<2019-09-21 state:closed") {
    issueCount
    edges {
      node {
        ... on Issue {
          createdAt
          closedAt
          title
          url
          repository {
            name
          }
        }
      }
    }
  }
}

Response 1

{
    "data": {
        "search": {
            "issueCount": 92339271,
            "edges": [
                {
                    "node": {
                        "createdAt": "2019-09-20T23:59:57Z",
                        "closedAt": "2019-09-21T19:59:32Z",
                        "title": "MJPEG stream won't open",
                        "url": "https://github.com/mpv-player/mpv/issues/6964",
                        "repository": {
                            "name": "mpv"
                        }
                    }
                },
                {
                    "node": {
                        "createdAt": "2019-09-20T23:59:50Z",
                        "closedAt": "2019-09-21T01:19:39Z",
                        "title": "Upgrade from v0.5.0 to v0.6.0 with attached volume failed",
                        "url": "https://github.com/longhorn/longhorn/issues/745",
                        "repository": {
                            "name": "longhorn"
                        }
                    }
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {
                        "createdAt": "2019-09-20T23:58:52Z",
                        "closedAt": "2019-09-21T01:55:15Z",
                        "title": "bad linkage",
                        "url": "https://github.com/signalapp/Signal-Desktop/issues/3608",
                        "repository": {
                            "name": "Signal-Desktop"
                        }
                    }
                },
                {
                    "node": {}
                },
                {
                    "node": {
                        "createdAt": "2019-09-20T23:58:36Z",
                        "closedAt": "2019-09-21T00:57:54Z",
                        "title": "Breaks Some Links on Firefox for Mac",
                        "url": "https://github.com/duckduckgo/duckduckgo-privacy-extension/issues/416",
                        "repository": {
                            "name": "duckduckgo-privacy-extension"
                        }
                    }
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {
                        "createdAt": "2019-09-20T23:56:11Z",
                        "closedAt": "2019-09-23T18:43:30Z",
                        "title": "ci: upload coverage reports from GitHub Actions",
                        "url": "https://github.com/hyperledger/aries-framework-go/issues/314",
                        "repository": {
                            "name": "aries-framework-go"
                        }
                    }
                },
                {
                    "node": {}
                },
                {
                    "node": {
                        "createdAt": "2019-09-20T23:56:07Z",
                        "closedAt": "2019-09-21T02:53:35Z",
                        "title": "0xxx.ws",
                        "url": "https://github.com/NanoMeow/QuickReports/issues/1885",
                        "repository": {
                            "name": "QuickReports"
                        }
                    }
                }
            ]
        }
    }
}

Response 2

{
    "data": {
        "search": {
            "issueCount": 92339271,
            "edges": [
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {
                        "createdAt": "2019-09-20T23:58:36Z",
                        "closedAt": "2019-09-21T00:57:54Z",
                        "title": "Breaks Some Links on Firefox for Mac",
                        "url": "https://github.com/duckduckgo/duckduckgo-privacy-extension/issues/416",
                        "repository": {
                            "name": "duckduckgo-privacy-extension"
                        }
                    }
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                },
                {
                    "node": {}
                }
            ]
        }
    }
}
Daniel Rearden
  • 80,636
  • 11
  • 185
  • 183

1 Answers1

3

The type of the node field is SearchResultItem, which is an interface. An interface is an abstract type that represents one or more object types that implement that interface. In other words, the type of any particular node field in the search results could be one of several types -- Issue, PullRequest, Repository, etc.

When querying an abstract type (an interface or a union), we have to use inline fragments in order to specify which fields for each possible type we want to fetch. So for search, we write:

... on Issue {
  # some fields here
}
... on PullRequest {
  # some other fields here
}
... on Repository {
  # yet some other fields here
}

and so on. Inline fragments only tell GraphQL which fields to return for a given type. They do not filter the actual results of the search. You don't have to provide an inline fragment for every possible type, but if you don't provide one and that type is returned in the results, it will be returned as an empty object (again, because you didn't tell GraphQL which fields you wanted for that particular type).

GraphQL does not provide any built-in methods for filtering, sorting or other manipulation of the returned data. It's up to the individual service to implement that functionality if it's needed. In this particular case, even though there's a type argument on the search field, setting the value of the argument to ISSUE will actually still return two different types -- Issue and PullRequest. Therefore, you still need another inline fragment for PullRequest if you want to avoid receiving an empty object for some of the search results.

Daniel Rearden
  • 80,636
  • 11
  • 185
  • 183