如何将视频节点从解析/数据库传递到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 可以同时检索typeid( type: 'Video', id: 'f4623d92-3b48-4e1a-bfcc-01ff3c8cf754:' ),之后我仍然需要添加fromGlobalId(globalId).id.replace(/\:$/, '')) 来删除结尾的冒号(:)。 `

另外,interfaces 并不意味着可访问,它们只是用于配置。

【讨论】:

以上是关于如何将视频节点从解析/数据库传递到graphql中继中的节点定义?的主要内容,如果未能解决你的问题,请参考以下文章

我们如何从 apollo-server 模块传递 ApolloServer 中的数据源和合并的 graphql 模式和解析器?

如何将请求标头传递给 graphql 解析器

如何将数据从反应组件传递到 Apollo graphql 查询?

如何从 Graphql 解析函数中的回调返回值?

如何使用graphql将mongodb中多个集合中的数据传递到1个反应表

在 GraphQL 中将参数从根传递到子查询