GitHub GraphQL API: only get issues that have over n comments - graphql

I'm playing with GitHub GraphQL API in order to get the list of most commented issues (say, comments > 100) across most popular repositories.
Here's the search query that I'm starting from:
search(query: "stars:>10000 fork:false pushed:>2020-01-01 is:public mirror:false archived:false", type: REPOSITORY)
So far so good, except that it looks like this high level GitHub search doesn't provide any filters related to issues and comments: I can't filter out repos that don't have issues at all, nor can I set a threshold for the number of comments.
Then I try to see if there's a filter specific to the list of issues, but it seems that the filterBy for issues doesn't provide any way to filter by comments or related activity:
search(query: "stars:>10000 fork:false pushed:>2020-01-01 is:public mirror:false archived:false", type: REPOSITORY) {
repositoryCount
nodes {
... on Repository {
issues(first: 100, filterBy: { <!-- Nothing useful here--> }, orderBy: {field: CREATED_AT, direction: ASC}) {
totalCount
edges {
node {
title
comments {
totalCount
}
id
number
}
}
}
}
}
}
Am I missing something obvious, or do I really need to get all issues from the API and then process the result locally to strip away issues that have less than 100 comments?

Related

Can I create two different graphql query for two different folders separately in my Gatsby project

I'm a newbie programmer and Recently I want to add a blog page to my website. I already have a projects page using Graphql and .md files, now my problem is, every time I try to create a blog post with .md, it appears also in my projects page, could you please advice me with some of your kind experience on solving this issue and do I have to create a separate query? even I don't know how?
this is my current query.
export const query = graphql`
query ProjectsPage {
allMarkdownRemark(sort: { fields: frontmatter___date, order: DESC }) {
nodes {
frontmatter {
slug
stack
title
thumb {
childImageSharp {
gatsbyImageData(placeholder: BLURRED, layout: FULL_WIDTH)
}
}
}
id
}
}
}
One easy thing you can do is to add a key field on your markdown files to distinguish between posts and projects. This will allow you to filter GraphQL queries. In the same way, you can also place the markdowns in separate folders and filter them using the relative/absolute path.
export const query = graphql`
query ProjectsPage {
allMarkdownRemark(filter: { frontmatter: {key: { eq: "project" }}, sort: { fields: frontmatter___date, order: DESC }) {
nodes {
frontmatter {
slug
stack
title
thumb {
childImageSharp {
gatsbyImageData(placeholder: BLURRED, layout: FULL_WIDTH)
}
}
}
id
}
}
}
As I said, this approach assumes that you have created a key: project field in your markdown files. You can do the same using key: article.
Alternatively, placing the markdowns in different folders using fileAbsolutePath/relativePath if needed in the same way. This approach will rely on your filesystem structure to determine the available paths. Both approaches are based on a filtered query, choose whatever suits you better.
Use the GraphiQL playground to test all queries, paths and filters at localhost:8000/___graphql

sort content by tag in Gatsby with Conteful API

In Contentful, I create a content with few media pictures. The pictures have two different tags boxon and attaqueGenetique. I want to sort the slideshow by using tags I've added for each media, but I don't find the way to do that. There is an example on the website Gatsby, but is not really clear and my try failed to make it mine.
The example from Gatsby
query FilterByTagsQuery {
allContentfulNumber(
sort: { fields: contentful_id }
filter: {
metadata: {
tags: { elemMatch: { contentful_id: { eq: "numberInteger" } } }
}
}
) {
nodes {
title
integer
}
}
}
I've supposed I must transpose thise code to mine where
allContentfulNumber become allContentfulDiaporama, and
metadata: {
tags: { elemMatch: { contentful_id: { eq: "numberInteger" } } }
}
become
metadata: {
tags: { elemMatch: { contentful_id: { eq: "boxon" } } }
}
but when I try to compile the console return
56:5 error Field "metadata" is not defined by type "ContentfulDiaporamaFilterInput" graphql/template-strings
I don't know where catch metadata from media when it's imported in content... but I'm very beginner with graphql and Contentful. If there is a solution, that's can make my day happy !!!
metadata in Gatsby's example is a GraphQL node valid in their data structure, if yours hasn't it simply don't use it or it will break the code since it's not a valid custom type.
The problem in your query, besides using an invalid field (metadata) is that you are using an elemMatch filter, comparingcontentful_id (number) to boxon (string), so it will never work in your scenario (it works in Gatsbys' because it's the same type). In your case, you may want to use in (for arrays) or eq (for single values). Check the available list at: https://www.gatsbyjs.com/docs/graphql-reference/#filter
As far as I understand your question, it seems that you want to split your diaporama data in two different nodes, the ones that contain boxon and the ones that contain attaqueGenetique. If so, you will need to create different nodes by aliasing them:
query FilterByTagsQuery {
boxon: allContentfulDiaporama(
sort: { fields: contentful_id }
filter: {
metadata: { tags: { in: ["boxon"] } }
}
) {
nodes {
#your data/fields here
}
}
attaqueGenetique: allContentfulDiaporama(
sort: { fields: contentful_id }
filter: {
metadata: { tags: { in: ["attaqueGenetique"] } }
}
) {
nodes {
#your data/fields here
}
}
}
Test the query in the GraphiQL playground, available at localhost:8000/___graphql where it will be much more intuitive for you to add or remove filters and see the available nodes.
The snippet above will generate two different data structures based on the tags aliased. With this: boxon: allContentfulDiaporama, you are aliasing the result of allContentfulDiaporama in boxon so in your page, you will be able to access directly props.data.boxon and props.data.attaqueGenetique respectively.
Keep in mind that the sort filtering method only works on dates or numeric values, in the case of strings, it will sort them alphabetically. So I'm assuming that your data has a contentful_id (I'm not sure how it will be helpful sorting by contentful_id).
According to this pull-request the enableTags feature was fixed in the cutting-edge release(5 days ago) so try to upgrade your plugin dependency.
It seems to be fixed in, according to this GitHub thread:
gatsby-source-contentful#7.5.0-next.0
Or in the next release.

Obtain GitHub issues in a specific milestone using GraphQL and IssueFilters

A similar question was previously asked but doesn't use IssueFilters which is what I want to use in this question.
Using GitHub's GraphQL Explorer, I am able to get issues of a repository using this query:
{
repository(owner: "neovim", name: "neovim") {
hasIssuesEnabled
issues(first: 20, orderBy: {field: CREATED_AT, direction: DESC}, filterBy: {milestone:"*"}) {
nodes {
... on Issue {
number
title
milestone {
number
id
url
title
}
}
}
}
}
}
The milestone is an issueFilter which, according to the documentation, allows you to:
List issues by given milestone argument. If a string representation of an integer is passed, it should refer to a milestone by its number field. Pass in null for issues with no milestone, and * for issues that are assigned to any milestone.
However, using a filter that is not a * but let's say filterBy: {milestone:"9"} (9 being a valid milestone number for the repository I am using), the query returns no nodes:
{
"data": {
"repository": {
"hasIssuesEnabled": true,
"issues": {
"nodes": []
}
}
}
}
I do not understand why this does not work from the documentation I read. Am I missing something regarding what means "it should refer to a milestone by its number field"?

Abstract relay-style connections in Apollo client

I am building an app that will use GraphQL on the backend and Apollo-client on the front-end. I am going to use Relay-style connection types as it would allow us to put metadata on relationships.
However, we don't want our react components to have to deal with the additional complexity added by connections. For legacy reasons and also because it seems cleaner, I would prefer that my react components don't have to deal with nodes and edges. I prefer to pass around:
Snippet 1:
const ticket = {
title: 'My bug'
authors: [{ login: 'user1', login: 'user2' }]
}
rather than
Snippet 2:
const ticket = {
title: 'My bug'
authors: {
nodes: [{
login: 'user1',
login: 'user2',
}]
}
}
Also in typescript, I really don't see myself defining a ticket type that would contain nodes and metadata such as nextPage, lastPage etc...
I am trying to come up with an abstraction, maybe at the apollo client level that would allow me to automatically convert Snippet 2 to Snippet 1 while still allowing access to Snippet 1 when I actually need those metadata.
Has this problem been solved by someone else? Do you have suggestions on a possible solution? Am i heading in the wrong directions?
Rather than trying to solve this client-side, you can simply expose additional fields in your schema. You can see this done with the official SWAPI example:
query {
allFilms {
# edges
edges {
node {
...FilmFields
}
}
# nodes exposed directly
films {
...FilmFields
}
}
}
This way you can query the nodes with or without the connection as needed without having to complicate things on the client side.

GraphQL query based on a specific value of a field

I want to be able to retrieve the latest release from GitHub for a specific repo using their GraphQL API. To do that, I need to get the latest release where isDraft and isPrerelease are false. I have managed to get the first part, but cant figure out how to do the "where" part of the query.
Here is the basic query I have gotten (https://developer.github.com/v4/explorer/):
{
repository(owner: "paolosalvatori", name: "ServiceBusExplorer") {
releases(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {
nodes {
name
tagName
resourcePath
isDraft
isPrerelease
}
}
}
}
Which returns:
{
"data": {
"repository": {
"releases": {
"nodes": [
{
"name": "3.0.4",
"tagName": "3.0.4",
"resourcePath": "/paolosalvatori/ServiceBusExplorer/releases/tag/3.0.4",
"isDraft": false,
"isPrerelease": false
}
]
}
}
}
}
I cant seem to find a way to do this. Part of the reason is that I am new to GraphQL (first time trying to do a query) and I am not sure how to frame my question.
Can one only "query" based on those types that support arguments (like repository and releases below)? Seems like there should be a way to specify a filter on the field values.
Repository: https://developer.github.com/v4/object/repository/
Releases: https://developer.github.com/v4/object/releaseconnection/
Node: https://developer.github.com/v4/object/release/
Can one only "query" based on those types that support arguments
Yes: GraphQL doesn't define a generic query language in the same way, say, SQL does. You can't sort or filter a field result in ways that aren't provided by the server and the application schema.
I want to be able to retrieve the latest [non-draft, non-prerelease] release from GitHub for a specific repo using their GraphQl API.
As you've already found, the releases field on the Repository type doesn't have an option to sort or filter on these fields. Instead, you can iterate through the releases one at a time with multiple GraphQL calls. These would individually look like
query NextRelease($owner: String!, $name: String!, $after: String) {
repository(owner: $owner, name: $name) {
releases(first: 1,
orderBy: {field: CREATED_AT, direction: DESC},
after: $after) {
pageInfo { lastCursor }
nodes { ... ReleaseData } # from the question
}
}
}
Run this in the same way you're running it now (I've split out the information identifying the repository into separate GraphQL variables). You can leave off the after variable for the first call. If (as in your example) it returns "isDraft": false, "isPrerelease": false, you're set. If not, you need to try again: take the value from the lastCursor in the response, and run the same query, passing that cursor value as the after variable value.
{
repository(owner: "paolosalvatori", name: "ServiceBusExplorer") {
releases(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {
nodes(isDraft :false , isPrerelease :false ) {
name
tagName
resourcePath
isDraft
isPrerelease
}
}
}
}
Alternatively please have look at GraphQL directives, as sometimes it's required to skip or include the fields on the basis of the values
#skip or #include.
The skip directive, when used on fields or fragments, allows us to exclude fields based on some condition.
The include directive, allows us to include fields based on some condition
GraphQL Directives

Resources