Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can i make omit empty in grpahql query struct #49

Open
parithiban opened this issue Nov 1, 2019 · 4 comments
Labels

Comments

@parithiban
Copy link

@parithiban parithiban commented Nov 1, 2019

I have the following struct in which the Topics in the field tag can be optional so I made it as a pointer. Now while try calling the graphql it is resulting in error

type Topic struct {
	Name githubv4.String
}
type TopicsNode struct {
	Topic Topic
}

type RepositoryTopics struct {
	Nodes []TopicsNode
}

type Repository struct {
	Name        githubv4.String
	Description githubv4.String
	Topics      *RepositoryTopics `graphql:"repositoryTopics(first: 20)"`
}

type Execute struct {
	Repository *Repository `graphql:"repository(owner:$orgName,name: $repositoryName)"`
}

I tried calling the graphql


	repos := Repository{
		Name: "MY_REPO",
	}

	query := Execute{
		Repository: &repos,
	}

	variables := map[string]interface{}{
		"repositoryName": githubv4.String(RepoName),
		"orgName":        githubv4.String(GithubOrg),
	}

	err := GraphQL.Query(context.Background(), &query, variables)

I am getting the topics field always. How can i make it as optional

I tried two ways

Topics      *RepositoryTopics `graphql:"repositoryTopics(first: 20)" json:",omitempty"`
Topics      *RepositoryTopics `graphql:"repositoryTopics(first: 20) omitempty"`
@dmitshur dmitshur added the question label Nov 2, 2019
@dmitshur

This comment has been minimized.

Copy link
Member

@dmitshur dmitshur commented Nov 2, 2019

Now while try calling the graphql it is resulting in error

What error do you get? Can you paste it here?

I am getting the topics field always. How can i make it as optional

You'll need to use GraphQL syntax for this, not JSON. GraphQL has a directive called "include":

https://graphql.github.io/graphql-spec/June2018/#sec--include

So you can do something like:

Topics *RepositoryTopics `graphql:"repositoryTopics(first: 20) @include(if: $includeTopics)"`

Then set the includeTopics variable to true or false:

variables := map[string]interface{}{
	"repositoryName": githubv4.String(RepoName),
	"orgName":        githubv4.String(GithubOrg),
	"includeTopics":  githubv4.Boolean(false),
}

Is that what you're looking to do?

@parithiban

This comment has been minimized.

Copy link
Author

@parithiban parithiban commented Nov 3, 2019

@dmitshur

Thanks for the reply this is what exactly I needed. One query reg @include tag will this include GraphQL resource limitations i.e will it include the node limit & rate limit.

What error do you get? Can you paste it here?

If I change the structure as below. That is changing

  • RepositoryTopics
  • TopicsNode
  • Topic

struct to pointer

type Topic struct {
	Name *githubv4.String
}
type TopicsNode struct {
	Topic *Topic
}

type RepositoryTopics struct {
	Nodes *[]TopicsNode
}

type Repository struct {
	Name        githubv4.String
	Description githubv4.String
	Topics      *RepositoryTopics `graphql:"repositoryTopics(first: 20)"`
}

type Execute struct {
	Repository *Repository `graphql:"repository(owner:$orgName,name: $repositoryName)"`
}

And then calling the graphql as above i get the below error

slice doesn't exist in any of 1 places to unmarshal

@parithiban

This comment has been minimized.

Copy link
Author

@parithiban parithiban commented Nov 3, 2019

I have one more scenario where I need to find the codeowner existence in a repo. According to Github the codeowners can be found in three different locations.. Is there a way can I combine a struct group and assign it to the repository struct


type Blob struct {
	Text string
}

type CodeOwnerLocation struct {
	Blob Blob `graphql:"... on Blob"`
}

type GithubCodeOwner struct {
	Blob Blob `graphql:"... on Blob"`
}

type DocsCodeOwner struct {
	Blob Blob `graphql:"... on Blob"`
}

type GetCodeOwners struct {
	CodeOwner       CodeOwnerLocation `graphql:"codeowner:object(expression: \"HEAD:CODEOWNERS\")"`
	GithubCodeOwner GithubCodeOwner   `graphql:"object(expression: \"HEAD:.github/CODEOWNERS\")"` 
	DocsCodeOwner   DocsCodeOwner     `graphql:"object(expression: \"HEAD:docs/CODEOWNERS\")"` 
}

type Repository struct {
	Name        githubv4.String
	Description githubv4.String
	CodeOwners  *GetCodeOwners // This doesn't work
        GithubCodeOwner GithubCodeOwner `graphql:"object(expression: \"HEAD:.github/CODEOWNERS\")"` // This works fine
}
@dmitshur

This comment has been minimized.

Copy link
Member

@dmitshur dmitshur commented Nov 4, 2019

And then calling the graphql as above i get the below error

slice doesn't exist in any of 1 places to unmarshal

Thanks. I'll need a complete runnable snippet that can reproduce this problem to investigate further. Do you mind putting one together?


Is there a way can I combine a struct group and assign it to the repository struct

Yes. Instead of doing:

Name        githubv4.String
Description githubv4.String
CodeOwners  *GetCodeOwners // This doesn't work

You need to do something like:

Name           githubv4.String
Description    githubv4.String
*GetCodeOwners // Embed this struct.

Or:

Name            githubv4.String
Description     githubv4.String
CodeOwner       CodeOwnerLocation `graphql:"object(expression: \"HEAD:CODEOWNERS\")"`
GithubCodeOwner CodeOwnerLocation `graphql:"object(expression: \"HEAD:.github/CODEOWNERS\")"` 
DocsCodeOwner   CodeOwnerLocation `graphql:"object(expression: \"HEAD:docs/CODEOWNERS\")"` 

When you do CodeOwners *GetCodeOwners instead of embedding GetCodeOwners, the generated GraphQL query looks like:

{
	codeOwners {
		docsCodeOwner: object(expression: "HEAD:docs/CODEOWNERS" {
			... on Blob {
				text
			}
		}
		githubCodeOwner: object(expression: "HEAD:.github/CODEOWNERS" {
			// ...
		}
		// ...
	}
}

Which isn't valid, because of "codeOwners". Embedding that struct means its contents are directly inserted, which is what you want.

In general, I suggest coming up with the GraphQL query that does what you want first, testing it via GitHub GraphQL API Explorer at https://developer.github.com/v4/explorer/, and then converting it to Go code that executes the GraphQL query.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
2 participants
You can’t perform that action at this time.