Code Monkey home page Code Monkey logo

Comments (10)

sogko avatar sogko commented on July 21, 2024 9

Hi @kmulvey

Maybe you could share how far you've gotten into the go version, we could help you better that way :)

In the meantime, this is how I would do:

  1. First I'd define the schema using GraphQL Schema Language (shameless plug: cheat sheet here )
type RootQuery {
    post: Post
}
type Post {
    _id: String!
    title: String
    content: String
    author: Author
}
type Author {
    _id: String!
    name: String
}
  1. Next, here's is a rough equivalent of the JS version that you posted.
    Note that I've left out the business / app logic to retrieve/find posts/author etc.

Hope this helps you move into the right direction, let me know if you need further help.

Cheers!

package main

import (
    "github.com/graphql-go/graphql"
    "fmt"
)
// Define GraphQL Schema
var AuthorObject = graphql.NewObject(graphql.ObjectConfig{
    Name: "Author",
    Description: "This respresents an Author",
    Fields: graphql.Fields{
        "_id": &graphql.Field{
            Type: graphql.NewNonNull(graphql.String),
        },
        "name": &graphql.Field{
            Type: graphql.String,
        },
    },
})
var PostObject = graphql.NewObject(graphql.ObjectConfig{
    Name: "Post",
    Description: "This respresents an Post",
    Fields: graphql.Fields{
        "_id": &graphql.Field{
            Type: graphql.NewNonNull(graphql.String),
        },
        "title": &graphql.Field{
            Type: graphql.NewNonNull(graphql.String),
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                // get title from source
                title, _ := p.Source["title"].(string)

                if title == "" {
                    // return error
                    return nil, fmt.Errorf("Does not exists")
                }
                return title, nil
            },
        },
        "content": &graphql.Field{
            Type: graphql.String,
        },
        "author": &graphql.Field{
            Type: AuthorObject,
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                // get title from source
                title, _ := p.Source["title"].(string)

                // add business logic to retrieve find for given post title
                return author, nil
            },
        },
    },
})
var RootQuery = graphql.NewObject(graphql.ObjectConfig{
    Name: "BlogSchema",
    Description: "Root of the Blog Schema",
    Fields: graphql.Fields{
        "posts": &graphql.Field{
            Type: graphql.NewList(PostObject),
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                // add business logic to retrieve list of Posts
                return PostsList
            },
        },
        "echo": &graphql.Field{
            Type: graphql.String,
            Description: "Echo what you enter",
            Args: graphql.FieldConfigArgument{
                "message": &graphql.ArgumentConfig{
                    Type: graphql.String,
                },
            },
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                // get arg value
                message, _ := p.Args["message"].(string)
                return message, nil
            },
        },
    },
})

from graphql.

bbuck avatar bbuck commented on July 21, 2024 1

@artshpakov

query posts {
  posts {
    title
    author {
      name
    }
  }
  user {
    name
    posts {
      title
    }
  }
}

I'm not sure your question is related to the issue you posted in. Nor am I sure exactly what you're asking.

from graphql.

bbuck avatar bbuck commented on July 21, 2024 1

@artshpakov Ah, okay. So basically, in the case of types that have to reference other types and the requirement for the type to be non-null in GraphQL you'd delay field definition.

Define your Post type without Authors, and define your Authors type without posts, then once the two exist without reference each other use Object.AddFieldConfig to tie them together (add a posts to Author and add a author to Post).

from graphql.

kmulvey avatar kmulvey commented on July 21, 2024

thanks @sogko for the quick reply. I was able to advance your example a bit and get the correct structure out but now the values are coming out null. I have a feeling I made a silly mistake somewhere but can't seem to spot it. Also authorObject (commented out) won't compile if i leave the "posts" section in. Thanks for your help.

https://gist.github.com/kmulvey/4843061d16492a24ce2663e497dda528

{
  "data": {
    "posts": [
      {
        "author": {
          "name": null
        },
        "title": null
      },
      {
        "author": {
          "name": null
        },
        "title": null
      },
       etc ...
    ]
  }
}

from graphql.

sogko avatar sogko commented on July 21, 2024

hi @kmulvey

Actually you almost had it.
Since you are returning Golang structs in Resolve() functions, you need to let graphql-go know how to map the struct fields to your GraphQL fields.
Currently we use json tags for this.

(This is shown in the examples, but unfortunately we have not done a good job with the documentation to highlight this)

Simply update your struct implementations with the json tags, mapping it to the field names defined in your schema. (Note the capitalisation)

// User respresents an author
type User struct {
    ID    int    `json:"_id"`
    Age   int    `json:"age"`
    Name  string `json:"name"`
    Posts []Post `json:"posts"`
}

// Post is a blog post
type Post struct {
    ID     int    `json:"_id"`
    UserID int    `gorm:"index"` // json-tag not needed since you are not using this field currently
    Title  string `gorm:"type:varchar(100);unique_index" json:"title"`
}
{
  "data": {
    "posts": [
      {
        "author": {
          "name": "userOne"
        },
        "title": "post one"
      },
      {
        "author": {
          "name": "userOne"
        },
        "title": "post two"
      },
      {
        "author": {
          "name": "userTwo"
        },
        "title": "post three"
      },
      {
        "author": {
          "name": "userTwo"
        },
        "title": "post four"
      }
    ]
  }
}

If I find the time, I can do a complete implementation of the example gist you gave earlier, to compare notes.

Cheers!

from graphql.

artshpakov avatar artshpakov commented on July 21, 2024

What if I need to perform both
{posts {title,author {name}}}
and
{user {name,posts {title}}}
queries?

from graphql.

artshpakov avatar artshpakov commented on July 21, 2024

@bbuck
Sorry if I misunderstood some graphql concepts in general, but I was referring to the golang code snippet above. It shows how to implement your Post and User types in case you want to query posts with authors embedded. So you've got to have your AuthorObject to be defined when you define PostObject. What I'm asking about is the case when you need both posts with nesting author
posts{title text author{name}} and authors with nested posts author(id:1){name posts{title text}}. You cannot have a "posts" field on AuthorObject because you have no PostObject defined yet.

Like, in Ruby graphql gem you can have that with

PostType = GraphQL::ObjectType.define do
  field :title, !types.String
  field :text, !types.String

  field :author, types[UserType] do
    resolve -> (obj, args, ctx) { User.find(obj.user_id) }
  end
end

UserType = GraphQL::ObjectType.define do
  field :name, !types.String

  field :posts, types[PostType] do
    resolve -> (obj, args, ctx) { obj.posts }
  end
end

QueryType = GraphQL::ObjectType.define do
  field :posts, types[PostType] do
    resolve ->(obj, args, ctx) { Post.all }
  end

  field :user do
    type UserType
    argument :id, !types.ID
    resolve -> (obj, args, ctx) { User.find(args["id"]) }
  end
end

What I'm asking is if there's any way to do the same with graphql-go.

from graphql.

artshpakov avatar artshpakov commented on July 21, 2024

@bbuck I see. That will quickly become clumsy though -- at least when your APIs start to grow and you decide to have your type definitions in separate files.

from graphql.

bbuck avatar bbuck commented on July 21, 2024

We use it in production and don't see any issues with it. I'm not sure how it can become clumsy.

from graphql.

lanceblais avatar lanceblais commented on July 21, 2024

Sorry to revive an old thread - I can open a new issue but it's related to this comment: #129 (comment).

In the example, the RootQuery has a posts field that has a Resolve that fetches all the posts and returns them.

My understanding is that then the PostObject resolvers start trying to figure out the _id, title, content and author. The author resolver uses p.Source to determine which author to look up and return.

I have a local example of something very similar, but for the author resolve function, p.Source is []Posts where I expected it to be a single Post and just have graphql-go call my resolver once for each Post the initial resolver received.

Is this a graphql thing?

How am I supposed to use p.Source to determine a particular author if I'm getting an array back?

from graphql.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.