如何将视频节点从解析/数据库传递到graphql中继中的节点定义?
Posted
技术标签:
【中文标题】如何将视频节点从解析/数据库传递到graphql中继中的节点定义?【英文标题】:How to pass video node from resolve/database to node definitions in graphql relay? 【发布时间】:2017-06-08 15:48:57 【问题描述】:我的节点定义如下所示:
class Store
let store = new Store()
let nodeDefs = nodeDefinitions(
(globalId) =>
let type = fromGlobalId(globalId).type
let id = fromGlobalId(globalId).id
if (type === 'Store')
return store
if (type === 'Video')
return docClient.query(
Object.assign(
,
TableName: videosTable,
KeyConditionExpression: 'id = :id',
ExpressionAttributeValues: ':id': id
)
).promise().then(dataToConnection)
return null
,
(obj) =>
if (obj instanceof Store)
return storeType
if (obj instanceof Video)
return videoType
return null
)
问题是视频节点始终为空,即使从数据库返回实际视频也是如此,因为要使其不为空,我需要根据 id 查找它或以某种方式从数据库中获取它。
这是我指的视频节点:
video:
type: videoType,
args: Object.assign(
,
connectionArgs,
id: type: GraphQLString
),
resolve: (_, args) =>
return docClient.query(
Object.assign(
,
TableName: pokemonTable,
KeyConditionExpression: 'id = :id',
ExpressionAttributeValues: ':id': args.id ,
paginationToParams(args)
)
).promise().then(dataToConnection)
,
和
const videoType = new GraphQLObjectType(
name: 'Video',
fields: () => (
id:
type: new GraphQLNonNull(GraphQLID),
resolve: (obj) => obj.id
,
name: type: GraphQLString ,
url: type: GraphQLString
),
interfaces: [nodeDefs.nodeInterface]
)
const allVideosConnection = connectionDefinitions(
name: 'Video',
nodeType: videoType
)
我尝试直接在节点定义中进行数据库查询,但没有成功。
dataToConnection
只是转换 dynamoDB 的输出:
video DATA!! Items:
[ id: 'f4623d92-3b48-4e1a-bfcc-01ff3c8cf754',
url: 'http://www.pokkentournament.com/assets/img/characters/char-detail/detail-pikachuLibre.png',
name: 'YAHOO' ],
Count: 1,
ScannedCount: 1
进入graphql relay可以理解的东西:
video dataToConnection!! edges:
[ cursor: 'ZHluYW1vZGJjb25uZWN0aW9uOmY0NjIzZDkyLTNiNDgtNGUxYS1iZmNjLTAxZmYzYzhjZjc1NA==',
node: [Object] ],
pageInfo:
startCursor: 'ZHluYW1vZGJjb25uZWN0aW9uOmY0NjIzZDkyLTNiNDgtNGUxYS1iZmNjLTAxZmYzYzhjZjc1NA==',
endCursor: 'ZHluYW1vZGJjb25uZWN0aW9uOmY0NjIzZDkyLTNiNDgtNGUxYS1iZmNjLTAxZmYzYzhjZjc1NA==',
hasPreviousPage: false,
hasNextPage: false
函数本身可以在这里找到:https://github.com/dowjones/graphql-dynamodb-connections/pull/3/files
这可能是问题所在。
另外,询问/查询 id 会使整个视频对象为空:
但是在查询中省略 id 会返回一些东西,无论是使用中继 id 查询:
或数据库ID
并查询所有视频作品:
有趣的是,即使我从节点定义中删除视频部分,我也会遇到完全相同的问题:
let nodeDefs = nodeDefinitions(
(globalId) =>
let type = fromGlobalId(globalId).type
let id = fromGlobalId(globalId).id
if (type === 'Store')
return store
return null
,
(obj) =>
if (obj instanceof Store)
return storeType
return null
)
有什么想法吗?
更新:
我做了一些挖掘,发现接口实际上是undefined
const storeType = new GraphQLObjectType(
name: 'Store',
fields: () => (
id: globalIdField('Store'),
allVideosConnection:
type: allVideosConnection.connectionType,
args: Object.assign(
,
connectionArgs
),
resolve: (_, args) =>
return docClient.scan(
Object.assign(
,
TableName: pokemonTable,
paginationToParams(args)
)
).promise().then(dataToConnection)
,
video:
type: videoType,
args: Object.assign(
,
connectionArgs,
id: type: GraphQLString
),
resolve: (_, args) =>
return docClient.query(
Object.assign(
,
TableName: pokemonTable,
KeyConditionExpression: 'id = :id',
ExpressionAttributeValues: ':id': args.id ,
paginationToParams(args)
)
).promise().then(dataToConnection)
),
interfaces: [nodeDefs.nodeInterface]
)
console.dir(storeType.interfaces, depth: null )
打印undefined
为什么?我在顶部清楚地定义了它们!
另外,我可以这样做:
但这不起作用:
这是 video:
解析中返回的内容:
edges:
[ cursor: 'ZHluYW1vZGJjb25uZWN0aW9uOmY0NjIzZDkyLTNiNDgtNGUxYS1iZmNjLTAxZmYzYzhjZjc1NA==',
node:
id: 'f4623d92-3b48-4e1a-bfcc-01ff3c8cf754',
url: 'http://www.pokkentournament.com/assets/img/characters/char-detail/detail-pikachuLibre.png',
name: 'YAHOO' ],
pageInfo:
startCursor: 'ZHluYW1vZGJjb25uZWN0aW9uOmY0NjIzZDkyLTNiNDgtNGUxYS1iZmNjLTAxZmYzYzhjZjc1NA==',
endCursor: 'ZHluYW1vZGJjb25uZWN0aW9uOmY0NjIzZDkyLTNiNDgtNGUxYS1iZmNjLTAxZmYzYzhjZjc1NA==',
hasPreviousPage: false,
hasNextPage: false
不知何故,这对 allVideosConnection
来说是可以的,但对于 video
来说就不行(最终是 null
)
是否需要将节点的 ID 转换为全局 ID?使用toGlobalId
?只为video
?
因为我注意到的另一件事是,如果我
console.log('fromGlobalId', fromGlobalId(globalId))
在我的节点定义中,这个查询:
node(id: "f4623d92-3b48-4e1a-bfcc-01ff3c8cf754")
id
...F1
fragment F1 on Video
url
name
变成这样:
fromGlobalId type: '', id: '\u000e6]_vvxsn\u001eU/\u001bG>SW_]O\u001c>x'
但是,如果我这样做了
我明白了
globalId U3RvcmU6
fromGlobalId type: 'Store', id: ''
【问题讨论】:
可以加入dataToConnection
吗?
storeType
是一个 GraphQLObjectType
并且您将接口传递给构造函数。我不确定是否有这样的评估员。
@brysgo 我的连接(allVideosConnection)和(视频)节点属于同一类型(它们必须是)。我还能怎么做?
我只是在回答您关于记录界面的问题。
@brysgo 如果您在这里查看此示例:github.com/taion/relay-todomvc/blob/master/src/data/… 他们显然正在将接口传递给GraphQLObjectType
【参考方案1】:
所以要使节点定义工作,我所要做的就是:
class Video
let video = new Video()
return Object.assign(video, data.Items[0])
即创建与类型名称同名的类 然后 Object.assign 给它
只是这样做,行不通:
return Video: data.Items[0]
我还需要像这样在数据库中创建 ID:Video:f4623d92-3b48-4e1a-bfcc-01ff3c8cf754
,我基本上将 type
和随机生成的唯一 ID 放在一起,用冒号 (:
) 分隔,然后用 toGlobalId
对其进行编码graphql-relay-js
库的函数(所以我最终得到VmlkZW86ZjQ2MjNkOTItM2I0OC00ZTFhLWJmY2MtMDFmZjNjOGNmNzU0Og==
),所以我可以用fromGlobalId
对其进行解码,以便node definitions
可以同时检索type
和id
( type: 'Video', id: 'f4623d92-3b48-4e1a-bfcc-01ff3c8cf754:'
),之后我仍然需要添加fromGlobalId(globalId).id.replace(/\:$/, ''))
来删除结尾的冒号(:
)。
`
另外,interfaces
并不意味着可访问,它们只是用于配置。
【讨论】:
以上是关于如何将视频节点从解析/数据库传递到graphql中继中的节点定义?的主要内容,如果未能解决你的问题,请参考以下文章
我们如何从 apollo-server 模块传递 ApolloServer 中的数据源和合并的 graphql 模式和解析器?
如何将数据从反应组件传递到 Apollo graphql 查询?