graphql-go / graphql

An implementation of GraphQL for Go / Golang
MIT License
9.86k stars 838 forks source link

[Q] Filtering #625

Closed Edwin-Luijten closed 2 years ago

Edwin-Luijten commented 2 years ago

I'm trying to implement a way to filter results and I feel a bit lost, Is there something I'm missing or not use correctly?

Query & Variables:

{
  "first": 1,
  "skip": 2,
  "age": 5,
}

query($first:Int, $skip:Int, $age:Int) {
  allMonkeys(first:$first, skip:$skip, filter: { age: {eq: $age}}){
    id,
    name,
    age
  }

  allMonkeysMeta{
        count
  }
}

Implementation:

&graphql.Field{
    Name: e.Slug,
    Type: graphql.NewList(iface),
    Args: graphql.FieldConfigArgument{
        "first": &graphql.ArgumentConfig{
            Type: graphql.Int,
        },
        "skip": &graphql.ArgumentConfig{
            Type: graphql.Int,
        },
        "filter": &graphql.ArgumentConfig{
            Type: graphql.NewInputObject(graphql.InputObjectConfig{
                Name: str.ToCamelCase(fmt.Sprintf("%s filter", ent.Slug)),
                Fields: graphql.InputObjectConfigFieldMap{
                    "id": &graphql.InputObjectFieldConfig{
                        Type: graphql.NewInputObject(graphql.InputObjectConfig{
                            Name:   str.ToCamelCase(fmt.Sprintf("%s id filter", ent.Slug)),
                            Fields: s.filters["id"],
                        }),
                    },
                    "age": &graphql.InputObjectFieldConfig{
                        Type: graphql.NewInputObject(graphql.InputObjectConfig{
                            Name: str.ToCamelCase(fmt.Sprintf("%s %s filter", ent.Key, k)),
                            Fields: graphql.InputObjectConfigFieldMap{
                                "eq": &graphql.InputObjectFieldConfig{
                                    Type:        graphql.Int,
                                    Description: "Search for records with an exact match",
                                },
                                "neq": &graphql.InputObjectFieldConfig{
                                    Type:        graphql.Int,
                                    Description: "Exclude records with an exact match",
                                },
                                "in": &graphql.InputObjectFieldConfig{
                                    Type:        graphql.NewList(graphql.Int),
                                    Description: "Filter records that equal one of the specified value",
                                },
                                "notIn": &graphql.InputObjectFieldConfig{
                                    Type:        graphql.NewList(graphql.Int),
                                    Description: "Filter records that do not equal one of the specified values",
                                },
                            },
                        }),
                    },
                },
            }),
        },
    },
    Resolve: func(p graphql.ResolveParams) (interface{}, error) {
        singular := strings.TrimSuffix(strings.TrimPrefix(p.Info.ReturnType.Name(), "all"), "s")
        ent, ok := entities[singular]
        if !ok {
            return nil, fmt.Errorf("invalid entity")
        }
        fmt.Println(p.Args)
        return s.recordRepository.GetAll(p.Args, ent)
    },
}

Result: When I print p.Args map[filter:map[age:map[]]]

Expectation: map[first: 1, skip: 2, filter:map[age:map[eq]: 5]]

When Checking the GraphQL Explorer All looks good: Screenshot from 2022-02-26 20-03-49

Edwin-Luijten commented 2 years ago

Ok, big fail. Looks like I provided a malformed json. My code like above works as intended =D.