尝试使用Golang和GraphQL查询Neo4j数据库时出现错误。

huangapple go评论96阅读模式
英文:

Error when trying to query neo4j database using golang and graphql

问题

我尝试使用neo4j数据库创建一个简单的graphql和go服务器,但是我一直遇到这个错误:

{
  "data": {
    "movieByTitle": null
  },
  "errors": [
    {
      "message": "User Error: expected iterable, but did not find one for field Query.movieByTitle.",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "movieByTitle"
      ]
    }
  ]
}

当我发起请求时出现这个错误。这是我的graphql字段:

var getMovieByTitle = &graphql.Field{
	Type: graphql.NewList(models.MovieType),
	Args: graphql.FieldConfigArgument{
		"title": &graphql.ArgumentConfig{
			Type: graphql.String,
		},
	},
	Resolve: func(params graphql.ResolveParams) (interface{}, error) {
		title := params.Args["title"].(string)

		configuration := data.ParseConfiguration()
		driver, err := configuration.NewDriver()
		if err != nil {
			log.Fatal(err)
		}
		defer data.UnsafeClose(driver)

		session := driver.NewSession(neo4j.SessionConfig{
			AccessMode:   neo4j.AccessModeRead,
			DatabaseName: configuration.Database,
		})
		defer data.UnsafeClose(session)

		movie, err := session.ReadTransaction(func(tx neo4j.Transaction) (interface{}, error) {
			records, err := tx.Run(
				`MATCH (movie:Movie {title:$title})
				  OPTIONAL MATCH (movie)<-[r]-(person:Person)
				  WITH movie.title as title,
						 collect({name:person.name,
						 job:head(split(toLower(type(r)),'_')),
						 role:r.roles}) as cast 
				  LIMIT 1
				  UNWIND cast as c 
				  RETURN title, c.name as name, c.job as job, c.role as role`,
				map[string]interface{}{"title": title})
			if err != nil {
				return nil, err
			}
			var result models.Movie
			for records.Next() {
				record := records.Record()
				title, _ := record.Get("title")
				result.Title = title.(string)
				name, _ := record.Get("name")
				job, _ := record.Get("job")
				role, _ := record.Get("role")
				switch role.(type) {
				case []interface{}:
					result.Cast = append(result.Cast, models.Person{Name: name.(string), Job: job.(string), Role: data.ToStringSlice(role.([]interface{}))})
				default: // handle nulls or unexpected stuff
					result.Cast = append(result.Cast, models.Person{Name: name.(string), Job: job.(string)})
				}
			}
			return result, nil
		})
		if movie == nil {
			log.Println(movie)
			return nil, fmt.Errorf("movie not found")
		}
		fmt.Println(movie)
		return movie, nil
	},
}

我正在使用gin来运行服务器。我尝试使用http端点而不是graphql运行相同的查询,并获得了预期的响应。我该如何修复这个错误?我正在使用neo4j中的示例电影数据集。

英文:

I tried making a simple server for graphql and go using a neo4j database but I keep getting this error:

{
&quot;data&quot;: {
&quot;movieByTitle&quot;: null
},
&quot;errors&quot;: [
{
&quot;message&quot;: &quot;User Error: expected iterable, but did not find one for field Query.movieByTitle.&quot;,
&quot;locations&quot;: [
{
&quot;line&quot;: 2,
&quot;column&quot;: 3
}
],
&quot;path&quot;: [
&quot;movieByTitle&quot;
]
}
]
}

when I make a request. This is my graphql field:

var getMovieByTitle = &amp;graphql.Field{
Type: graphql.NewList(models.MovieType),
Args: graphql.FieldConfigArgument{
&quot;title&quot;: &amp;graphql.ArgumentConfig{
Type: graphql.String,
},
},
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
title := params.Args[&quot;title&quot;].(string)
configuration := data.ParseConfiguration()
driver, err := configuration.NewDriver()
if err != nil {
log.Fatal(err)
}
defer data.UnsafeClose(driver)
session := driver.NewSession(neo4j.SessionConfig{
AccessMode:   neo4j.AccessModeRead,
DatabaseName: configuration.Database,
})
defer data.UnsafeClose(session)
movie, err := session.ReadTransaction(func(tx neo4j.Transaction) (interface{}, error) {
records, err := tx.Run(
`MATCH (movie:Movie {title:$title})
OPTIONAL MATCH (movie)&lt;-[r]-(person:Person)
WITH movie.title as title,
collect({name:person.name,
job:head(split(toLower(type(r)),&#39;_&#39;)),
role:r.roles}) as cast 
LIMIT 1
UNWIND cast as c 
RETURN title, c.name as name, c.job as job, c.role as role`,
map[string]interface{}{&quot;title&quot;: title})
if err != nil {
return nil, err
}
var result models.Movie
for records.Next() {
record := records.Record()
title, _ := record.Get(&quot;title&quot;)
result.Title = title.(string)
name, _ := record.Get(&quot;name&quot;)
job, _ := record.Get(&quot;job&quot;)
role, _ := record.Get(&quot;role&quot;)
switch role.(type) {
case []interface{}:
result.Cast = append(result.Cast, models.Person{Name: name.(string), Job: job.(string), Role: data.ToStringSlice(role.([]interface{}))})
default: // handle nulls or unexpected stuff
result.Cast = append(result.Cast, models.Person{Name: name.(string), Job: job.(string)})
}
}
return result, nil
})
if movie == nil {
log.Println(movie)
return nil, fmt.Errorf(&quot;movie not found&quot;)
}
fmt.Println(movie)
return movie, nil
},
}

I am using gin to run the server. I tried running the same query with an http endpoint instead of graphql and I got the expected response. How can I fix the error? I am using the example movie dataset in neo4j.

答案1

得分: 1

看起来Query.movieByTitle字段的类型是一个Movie对象的数组,但是你的解析器返回的是单个电影而不是列表/数组。

在其他GraphQL服务器实现中,通常会优雅地处理这个问题,不确定你正在使用的Go GraphQL实现是否也是如此。

英文:

It looks like the type of the Query.movieByTitle field is an array of Movie objects, but is your resolver returning a single movie instead of a list/array?

In other GraphQL server implementations, this is typically handled gracefully, not sure about the Go GraphQL implementation you're using.

huangapple
  • 本文由 发表于 2023年3月11日 00:47:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75698863.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定