AWS AppSync-使用GSI排序键将全局二级索引添加到DynamoDB和分页

vah*_*det 5 amazon-web-services amazon-dynamodb aws-appsync

我正在尝试创建一种结构,该结构列出具有降序postId排列的帖子评论lastChangeTime

模式中的模型在下面共享。

type Comment {
  id: ID!
  postId: String!
  user: String!
  lastChangeTime: String
  commentBody: String
}
Run Code Online (Sandbox Code Playgroud)

它已经具有支持DynamoDB表和通用CRUD解析器。而id字段是表的主键。

我计划建立一个查询,如下所示:

{
  "version": "2017-02-28",
  "operation" : "Query",
  "index" : "postId-index",
  "query" : {
    "expression": "post = :postId",
    "expressionValues" : {
      ":postId" : {
        "S" : "${ctx.args.postId}"
      }
    }
  },
  "limit": $util.defaultIfNull($ctx.args.first, 20),
  "nextToken": $util.toJson($util.defaultIfNullOrEmpty($ctx.args.after, null)),
  "scanIndexForward": false
}
Run Code Online (Sandbox Code Playgroud)

为了使其正常工作,我该如何在(即)上添加全球二级索引(GSI)?postIdpostId-index

我应该在定义时在其上添加排序键lastChangeTime吗?还是lastChangeTime字段需要对自己的单独索引进行排序?

Ula*_*Ula 7

这很容易。您可以通过两种不同的方式来做到这一点,也可以同时使用两种方式来获得更好的灵活性。(如果您已经解决了该问题,希望对您有所帮助)。

这样,您可以使用查询参数动态设置sortDirection。

详细代码如下。在此之前,请注意这一点。

  1. 第一点是您的评论类型-您正在使用

    type Comment {
      id: ID!
      postId: String!
      ## rest of your type definition
    }
    
    Run Code Online (Sandbox Code Playgroud)

这不是设置链接到帖子的评论类型的最佳方法。

更好的方法是:

type Comment {
    postID: ID!         ## select this as Primary key in DataSource in AppSync console
    commentID: String!    ## select this as Sort key in DataSource in AppSync console
    ## rest of your type definition
}
Run Code Online (Sandbox Code Playgroud)

如果执行此操作,则DynamoDB表的结构将类似于下面显示的结构(来自此AWS网页)。

(在您的情况下,UserId将为PostId,而GameTitle将为CommentID)

在此处输入图片说明

这样,因为所有注释都将彼此相邻记录(在同一PostId下),因此AppSync响应时间将更快。

AppSync文档页面中,他们还使用了以下示例:

在此处输入图片说明

  1. 正如@Lisa M Shon所提到的,您可以在CommentTable上启动GSI,其中PostId是分区键,而addTime是排序键。如果要使用下面提供的解析器,则称其为“ postID-addedTime-index”。确保您在GSI中的addedTime上选择了“ Number”。

在此处输入图片说明

然后,您可以在架构中定义以下类型:

type Comment {
    postID: ID!
    commentID: String!
    content: String!
    addedTime: Int!
}

type CommentConnection {
    items: [Comment]
    nextToken: String
}

type Post {
    id: ID!
    postContent: String!
    addedTime: Int!
    ## Option 1. Gets Post details with all related Comments. 
    ## If 'startFromTime' is provided it will fetch all Comments starting from that timestamp.
    ## If 'startFromTime' is not provided it will fetch all Comments.
    comments(
        filter: TableCommentFilterInput,
        sortDirection: SortDirection,
        startFromTime: Int,
        limit: Int,
        nextToken: String
    ): CommentConnection
}

type Query {
    ## Option 2. It will fetch Comments only for a given PostId.
    ## If 'startFromTime' is provided it will fetch all Comments starting from that timestamp.
    ## If 'startFromTime' is not provided it will fetch all Comments.
    postCommentsByAddTime(
        postID: String!,
        startFromTime: Int!,
        sortDirection: SortDirection,
        filter: TableCommentFilterInput,
        count: Int,
        nextToken: String
    ): PaginatedComments
   ## your other queries
}

    ## rest of your schema definition
Run Code Online (Sandbox Code Playgroud)

您可以同时使用-选项1和选项2并同时使用。

完整的架构代码在这里(展开下面的代码片段):

type Comment {
  id: ID!
  postId: String!
  ## rest of your type definition
}
Run Code Online (Sandbox Code Playgroud)

  1. (与选项1相关)。在右侧面板的AppSync控制台的“架构”页面上,找到“帖子”,并与“ comments(...):CommentConnection”相对,单击“附加”,添加“ CommentTable”作为源,并在VTL中添加以下解析器代码:

请求映射模板中:

    #set( $startFromTime = $util.defaultIfNull($context.args.startFromTime, 0) )
    {
        "version" : "2017-02-28",
        "operation" : "Query",
        "index" : "postID-addedTime-index",
        "query" : {
          "expression": "postID = :postID and addedTime > :startFrom",
            "expressionValues" : {
              ":postID" : { "S" : "$context.source.id" },
              ":startFrom" : { "N" : "$startFromTime" }
            }
        },
        "scanIndexForward":   #if( $context.args.sortDirection )
          #if( $context.args.sortDirection == "ASC" )
              true
          #else
              false
          #end
        #else
            true
        #end,

        #if( ${context.arguments.count} )
            ,"limit": ${context.arguments.count}
        #end
        #if( ${context.arguments.nextToken} )
            ,"nextToken": "${context.arguments.nextToken}"
        #end
    }
Run Code Online (Sandbox Code Playgroud)

响应映射模板中:

{
    "items": $utils.toJson($context.result.items)
    #if( ${context.result.nextToken} )
        ,"nextToken": "${context.result.nextToken}"
    #end
}
Run Code Online (Sandbox Code Playgroud)
  1. (与选项2相关)。在右侧面板的AppSync控制台的“架构”页面上,找到“查询”并与“ postCommentsByAddTime(...):PaginatedComments”相对,单击“附加”,添加CommentTable作为数据源,并在VTL中添加以下解析器代码:

请求映射模板中:

{
    "version" : "2017-02-28",
    "operation" : "Query",
    "index" : "postID-addedTime-index",
    "query" : {
      "expression": "postID = :postID and addedTime > :startFrom",
        "expressionValues" : {
          ":postID" : { "S" : "${context.arguments.postID}" },
          ":startFrom" : { "N" : "${context.arguments.startFromTime}" }
        }
    }
    #if( ${context.arguments.count} )
        ,"limit": ${context.arguments.count}
    #end
    #if( ${context.arguments.nextToken} )
        ,"nextToken": "${context.arguments.nextToken}"
    #end
}
Run Code Online (Sandbox Code Playgroud)

响应映射模板中:

{
    "items": $utils.toJson($context.result.items)
    #if( ${context.result.nextToken} )
        ,"nextToken": "${context.result.nextToken}"
    #end
}
Run Code Online (Sandbox Code Playgroud)

这就对了。

现在,您可以使用以下所有查询:

query ListPosts {
  listPosts{
    items {
      id
      postContent
      ## all below arguments are nullable
      comments(startFromTime: 121111112222, count: 4
      ## default sortDirection is ASC, you can change it this way
      ## sortDirection: DESC
    ) {
        items {
          postID
          commentID
          content
          addedTime
        }
      }
    }
  }
}

query GetPost {
  getPost(id: "6548e596-d1ed-4203-a32f-52cfab8c9b20") {
    id
    comments (
    ## you can also add all three or any or none of these
    ## sortDirection: DESC,
    ## startFromTime: 189283212122
    ## count: 5
    ) {
        items {
        postID
        commentID
        content
        addedTime
      }
  }
  }
}

query GetCommentsByTime {
  postCommentsByAddTime(postID: "6548e596-d1ed-4203-a32f-52cfab8c9b20", startFromTime: 12423455352342, count: 2) {
    items {
      postID
      commentID
      content
      addedTime
    }
  }
}
Run Code Online (Sandbox Code Playgroud)