【问题标题】:How to pass video node from resolve/database to node definitions in graphql relay?如何将视频节点从解析/数据库传递到graphql中继中的节点定义?
【发布时间】: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]_v{vxsn\u001eU/\u001b}G>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

标签: javascript graphql relayjs graphql-js


【解决方案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 并不意味着可访问,它们只是用于配置。

【讨论】:

    猜你喜欢
    • 2018-02-02
    • 2017-07-23
    • 1970-01-01
    • 2019-01-11
    • 1970-01-01
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    • 2012-10-17
    相关资源
    最近更新 更多