如何向列表中添加项目?

4
我想将一个字符串添加到我的用户表中listOfVideosRated[] 列表中。

1
我认为你需要先获取记录,然后更新记录并推送。在Dynamo中,记录存储为JSON对象,我认为无法修改对象的键,只能替换它们。但我可能错了。 - Seth McClaine
1个回答

30
如果您可以发布模式/解析器映射模板,我可以提供更具体的建议,但我会尽力根据您目前发布的内容进行回答。
简单方法
如果您已经有现有项目,则一种方法是更新现有的键值对并将其传递给现有的突变。
const existingItem = {
  id: "e5eb02ae-04d5-4331-91e6-11efaaf12ea5",
  Pairs: [['a', 'b'],['c', 'd'],['e', 'f']]
}

const newPairs = {
  number1: "g",
  number2: "h"
}

const updateinfo = {
  id: existingItem.id,
  // Note that if existingItem.Pairs is always defined this can be simplified to
  // Pairs: [...existingItem.Pairs, [newPairs.number1, newPairs.number2]]
  Pairs: existingItem.Pairs ?
      [...existingItem.Pairs, [newPairs.number1, newPairs.number2]] : 
      [[newPairs.number1, newPairs.number2]]
}

try {
  await API.graphql(graphqlOperation (UpdateInfo, { input: updateinfo }))  
  //mutation
  console.log('success')
} 
catch (err) {
  console.log(err)
}

使用DynamoDB函数

如果您没有现有的项目或Pairs可能非常大,可以使用AWS DynamoDB的list_append函数。

list_append(operand, operand)

此函数计算为添加了一个新元素的列表。您可以通过反转操作数的顺序将新元素附加到列表的开头或结尾。

这里是一个使用它的具体变异示例。

### SDL
type Item {
    id: ID!
    Pairs: [[String]]
}

input AddPairInput {
    id: ID!
    number1: String!
    number2: String!
}

type Mutation {
    addPairToItem(input: AddPairInput!): Item!
}

...rest of schema omitted for brevity 

### Resolver Request Mapping Template
{
    "version": "2017-02-28",
    "operation": "UpdateItem",
    "key": {
        "id": { "S": "$ctx.args.input.id"}
    },
    "update": {
        ### Note: we also use if_not_exists here so this works if Pairs is not yet defined on the item.
        "expression":"SET Pairs = list_append(if_not_exists(Pairs, :emptyList), :newPair)",
        "expressionValues": 
          { 
            ":newPair":{"L": [{"L":[{"S":"$ctx.args.input.number1"},
                                    {"S":"$ctx.args.input.number2"}]}]},
            ":emptyList":{"L": []}
          }
        }
}

### Resolver Response Mapping Template
$util.toJson($ctx.result)

这种方法也很好,因为如果其他人更新了“Pairs”,您不会覆盖他们的更新。您还可以通过反转参数顺序将新的“Pair”添加到列表的开头,使用list_append函数。

使用AWS Amplify的DynamoDB函数

如果您的项目是由AWS Amplify生成的,则需要添加客户解析器

步骤1:向架构中添加新的mutation

### ./amplify/backend/api/<api_name>/schema.graphql
type Item @model {
  id: ID!
  Pairs: [[String]]
}

type Mutation {
  addPairToItem(input: AddPairToItemInput!): Item!
}

input AddPairToItemInput {
  id: ID!
  number1: String!
  number2: String!
}

步骤2:添加解析器请求映射模板

### ./amplify/backend/api/<api_name>/resolvers/Mutation.addPairToItem.req.vtl
{
    "version": "2017-02-28",
    "operation": "UpdateItem",
    "key": {
        "id": { "S": "$ctx.args.input.id"}
    },
    "update": {
        "expression":"SET Pairs = list_append(if_not_exists(Pairs, :emptyList), :newPair)",
        "expressionValues":
          {
            ":newPair":{"L": [{"L":[{"S":"$ctx.args.input.number1"},{"S":"$ctx.args.input.number2"}]}]},
            ":emptyList":{"L": []}
          }
        }
}

步骤三:添加解析器响应映射模板

### ./amplify/backend/api/<api_name>/resolvers/Mutation.addPairToItem.res.vtl
$util.toJson($ctx.result)

步骤四:将您的自定义解析器添加到CustomResources堆栈中

### ./amplify/backend/api/<api_name>/stacks/CustomResources.json
    "Resources": {
        // ...other resources may exist here
        "AddPairToItemResolver": {
            "Type": "AWS::AppSync::Resolver",
            "Properties": {
                "ApiId": {
                    "Ref": "AppSyncApiId"
                },
                "DataSourceName": "ItemTable",
                "TypeName": "Mutation",
                "FieldName": "addPairToItem",
                "RequestMappingTemplateS3Location": {
                    "Fn::Sub": [
                        "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/Mutation.addPairToItem.req.vtl",
                        {
                            "S3DeploymentBucket": {
                                "Ref": "S3DeploymentBucket"
                            },
                            "S3DeploymentRootKey": {
                                "Ref": "S3DeploymentRootKey"
                            }
                        }
                    ]
                },
                "ResponseMappingTemplateS3Location": {
                    "Fn::Sub": [
                        "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/Mutation.addPairToItem.res.vtl",
                        {
                            "S3DeploymentBucket": {
                                "Ref": "S3DeploymentBucket"
                            },
                            "S3DeploymentRootKey": {
                                "Ref": "S3DeploymentRootKey"
                            }
                        }
                    ]
                }
            }
        }
    },

步骤5:构建和部署您的新更改

  • 运行amplify api gql-compile以查看生成代码中的新更改(可选)。
  • 运行amplify push以部署更改。

现在,您可以运行amplify api console或使用新生成的代码来测试具有新突变的更改。

要生成新代码,可以运行amplify codegen。 然后,您应该能够执行以下操作:

import Amplify, { API, graphqlOperation } from "aws-amplify";
import * as mutations from './graphql/mutations';

// Mutation
const addPairToItem = {
    id: '1',
    number1: 'a',
    number2: 'b'
};

const newItem = await API.graphql(graphqlOperation(mutations.addPairToItem, {input: addPairToItem}));

更多示例

记得将新的解析器添加到CustomResources.json文件中。

向标量值列表中添加单个项

### ./amplify/backend/api/<api_name>/schema.graphql
type Item @model {
    id: ID!
    words: [String]
}

input AddWordInput {
    id: ID!
    word: String!
}

type Mutation {
    addWordToItem(input: AddWordInput!): Item!
}

### ./amplify/backend/api/<api_name>/resolvers/Mutation.addWordToItem.req.vtl
{
    "version": "2017-02-28",
    "operation": "UpdateItem",
    "key": {
        "id": { "S": "$ctx.args.input.id"}
    },
    "update": {
        "expression":"SET words = list_append(if_not_exists(words, :emptyList), :newWord)",
        "expressionValues":
          {
            ":newWord":{"L": [{"S":"$ctx.args.input.word"}]},
            ":emptyList":{"L": []}
          }
        }
}

### ./amplify/backend/api/<api_name>/resolvers/Mutation.addWordToItem.res.vtl
$util.toJson($ctx.result)


### Usage
import Amplify, { API, graphqlOperation } from "aws-amplify";
import * as mutations from './graphql/mutations';

// Mutation
const newWord = {
    id: '1',
    word: 'foo'
};

const newItem = await API.graphql(graphqlOperation(mutations.addWordToItem, {input: newWord}));

向标量值列表添加多个项目

注意:我在这里介绍$util.dynamodb.toDynamoDBJson,以使构建我们的VTL更容易。到目前为止我一直很明确,但这个实用程序可以简化很多工作。此处有更多信息

### ./amplify/backend/api/<api_name>/schema.graphql
type Item @model {
    id: ID!
    words: [String]
}

input AddWordsInput {
  id: ID!
  words: [String!]!
}

type Mutation {
  addWordsToItem(input: AddWordsInput!): Item!
}

### ./amplify/backend/api/<api_name>/resolvers/Mutation.addWordsToItem.req.vtl
{
    "version": "2017-02-28",
    "operation": "UpdateItem",
    "key": {
        "id": { "S": "$ctx.args.input.id"}
    },
    "update": {
        "expression":"SET words = list_append(if_not_exists(words, :emptyList), :newWords)",
        "expressionValues":
          {
            ":newWords": $util.dynamodb.toDynamoDBJson($ctx.args.input.words),
            ":emptyList": $util.dynamodb.toDynamoDBJson([])
          }
        }
}

### ./amplify/backend/api/<api_name>/resolvers/Mutation.addWordsToItem.res.vtl
$util.toJson($ctx.result)


### Usage
import Amplify, { API, graphqlOperation } from "aws-amplify";
import * as mutations from './graphql/mutations';

// Mutation
const newWords = {
    id: '1',
    words: ["bar","xyz","bar"]
};

const newItem = await API.graphql(graphqlOperation(mutations.addWordsToItem, {input: newWords}));

从标量值列表中删除项目

在 DynamoDB 中,使用 REMOVE 操作 可以删除列表中的元素。您必须在更新表达式中指定一个非负索引。如果索引不存在于该项上,则请求不会失败(例如没有索引越界异常)。

type Item @model {
    id: ID!
    words: [String]
}

input RemoveWordInput {
  id: ID!
  wordIndex: Int!
}

type Mutation {
    removeWordFromItem(input: RemoveWordInput!): Item!
}

### ./amplify/backend/api/<api_name>/resolvers/Mutation.removeWordFromItem.req.vtl
{
    "version": "2017-02-28",
    "operation": "UpdateItem",
    "key": {
        "id": { "S": "$ctx.args.input.id"}
    },
    "update": {
        "expression":"REMOVE words[$ctx.args.input.wordIndex]"
    }
}

### ./amplify/backend/api/<api_name>/resolvers/Mutation.removeWordFromItem.res.vtl
$util.toJson($ctx.result)


### Usage
import Amplify, { API, graphqlOperation } from "aws-amplify";
import * as mutations from './graphql/mutations';

// Mutation
const removeWord = {
    id: '1',
    // The index is 0 based so wordIndex: 0
    // would delete the first item,
    // wordIndex: 1 deletes the second, etc.
    wordIndex: 1 
};

const newItem = await API.graphql(graphqlOperation(mutations.removeWordFromItem, {input: removeWord}));

1
@chai86 我添加了一个将单个标量值和多个标量值添加到列表中的示例。这个答案现在变得相当长了。我会创建一个包含更多内容的 GitHub 存储库。 - Nathan Quinn
@NathanQuinn 我快完成我正在开发的应用了(Amplify非常有用)。但是我卡在最后一个部分,需要删除一行,请你紧急帮忙!!!我已经更新了原始帖子并提供了所有信息。谢谢 :) - chai86
@NathanQuinn 如果您有时间,一个带有示例的Github存储库肯定会非常受欢迎。我现在也需要将“对象”添加到列表中,例如具有ID、作者和内容的类型Message以及具有[Message]的类型Collection。 - Purefan
4
非常棒的回答,非常有帮助。希望我能多点赞! - tedsmitt
太棒了,非常有用的答案,感谢分享。 - beevor
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接