如何将视频节点从 resolve/database 传递到 graphql 中继中的节点定义?

How to pass video node from resolve/database to node definitions in graphql relay?

我的节点定义如下所示:

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 中继可以理解的东西:

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

可能是问题所在。

此外,asking/querying for id 使整个视频对象为空:

但是从查询中省略了id returns 东西,是否用relay 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]_v{vxsn\u001eU/\u001b}G>SW_]O\u001c>x' }

但是,如果我这样做

我明白了

globalId  U3RvcmU6
fromGlobalId { type: 'Store', id: '' }

所以要使节点定义起作用,我所要做的就是:

class Video {}
let video = new Video()
return Object.assign(video, data.Items[0])

即创建与类型名称同名的 class 然后Object.assign到它

仅仅这样做是行不通的:

return {Video: data.Items[0]}

我还需要像这样在数据库中创建 ID:Video:f4623d92-3b48-4e1a-bfcc-01ff3c8cf754,我实际上是将 type 和随机生成的唯一 ID 放在一起,用冒号分隔 (:)然后使用 graphql-relay-js 库的 toGlobalId 函数对其进行编码(所以我最终得到 VmlkZW86ZjQ2MjNkOTItM2I0OC00ZTFhLWJmY2MtMDFmZjNjOGNmNzU0Og==),然后我可以使用 fromGlobalId 对其进行解码,以便 node definitions可以检索 typeid({ type: 'Video', id: 'f4623d92-3b48-4e1a-bfcc-01ff3c8cf754:' }),之后我仍然需要添加 fromGlobalId(globalId).id.replace(/\:$/, '')) 以删除结尾的冒号 (:)。 `

此外,interfaces 并不意味着可访问,它们仅用于配置。