Почему использование возвращаемых значений: ‘ALL_NEW’ в операции DynamoDB updateItem возвращает нулевой идентификатор?

#amazon-web-services #aws-lambda #amazon-dynamodb #aws-appsync

Вопрос:

Я выполняю операцию обновления элемента DynamoDB с помощью мутаций AWS AppSync GraphQL, и я хочу, чтобы все значения элемента после операции обновления возвращались через API после успешного обновления.

Элемент обновляется идеально, и я также указал ReturnedValues атрибут, с ALL_NEW помощью которого должны быть возвращены все атрибуты, однако Item.Id null по какой-то причине?.

GraphQL:

 type User {
    id: ID!
    name: String
    avatarUrl: String
    createdAt: String
    updatedAt: String
}

type Mutation {
    updateUser(userId: ID!, name: String, avatarUrl: String): User
}

mutation updateUser {
  updateUser(userId:"USER-14160000000", name:"Test Test", avatarUrl:"www.test.com") {
    id
    name
    avatarUrl
    createdAt
    updatedAt
  }
}
 

Функция лямбда, которая обновляет элемент:

 const AWS = require("aws-sdk")
AWS.config.update({ region: "ca-central-1" })
const dynamoDB = new AWS.DynamoDB.DocumentClient()

async function updateUser(userId, name, avatarUrl) {
  var params = {
    TableName: "Bol-Table",
    Key: {
      "pk": userId,
      "sk": 'USER',
    },
    UpdateExpression: 'SET details.displayName = :name, details.avatarUrl = :avatarUrl, details.updatedAt = :updateDate',
    ExpressionAttributeValues: {
      ':name': name,
      ':avatarUrl':avatarUrl,
      ':updateDate': new Date().toISOString()
    },

    ReturnValues: 'ALL_NEW'
  };
  const Item = await dynamoDB.update(params).promise();
  console.log(Item);
  return { 
      id: Item.pk, 
      name: Item.displayName,
      avatarUrl: Item.avatarUrl,
      createdAt: Item.createdAt,
      updatedAt: Item.updatedAt
  };
}
module.exports = updateUser;
 

Вывод GraphQL из updateUser вызова:

 {
  "data": {
    "updateUser": null
  },
  "errors": [
    {
      "path": [
        "updateUser",
        "id"
      ],
      "locations": null,
      "message": "Cannot return null for non-nullable type: 'ID' within parent 'User' (/updateUser/id)"
    }
  ]
}
 

Вывод console.log(Item) из Amazon CloudWatch:

 2021-10-10T17:47:39.338Z    d06b7a58-541e-456f-b830-1a50eea7c35a    INFO    {
  Attributes: {
    sk: 'USER',
    details: {
      avatarUrl: 'www.test.com',
      createdAt: '2021-10-10T16:40:25.455Z',
      displayName: 'Test',
      updatedAt: '2021-10-10T17:47:38.586Z'
    },
    pk: 'USER-16040000000'
  }
}
 

Почему я получаю ошибку, Cannot return null for non-nullable type: 'ID' within parent 'User' (/updateUser/id) ?

Комментарии:

1. Каков результат console.log(Item); ? Item.pk вероятно, равно нулю.

2. @ErmiyaEskandary Я добавил результат консоли. войдите в исходную запись.

3. Спасибо сумчанам 🙂 подтверждает мои подозрения, добавил ответ

Ответ №1:

Документация AWS для UpdateItem показывает, что значения атрибутов возвращаются во вложенном Attributes объекте в ответе.

 {
   "Attributes": { 
      "string" : { 
         "B": blob,
         "BOOL": boolean,
         "BS": [ blob ],
         "L": [ 
            "AttributeValue"
         ],
         "M": { 
            "string" : "AttributeValue"
         },
         "N": "string",
         "NS": [ "string" ],
         "NULL": boolean,
         "S": "string",
         "SS": [ "string" ]
      }
   },
   ...
}
 

Таким образом , вам нужно будет получить к ним доступ с помощью Item.Attributes , а не пытаться получить к ним доступ Item , поскольку они не существуют на этом уровне.

Это должно сработать:

 return { 
  id: Item.Attributes.pk, 
  name: Item.Attributes.details.displayName,
  avatarUrl: Item.Attributes.details.avatarUrl,
  createdAt: Item.Attributes.details.createdAt,
  updatedAt: Item.Attributes.details.updatedAt
};
 

Комментарии:

1. Серьезно, я пробовал это, но по какой-то причине это не сработало вчера, это работает сейчас. Единственная проблема заключается в том, что он возвращает значение null для поля updatedAt.

2. Двойная проверка, разве это не должно быть Item.Attributes.details.avatarUrl ? Вы вкладываете значения в details объект? В прошлый раз он был внутри data объекта 🙂

3. Нет, это не так. Он должен иметь значение, подобное созданному в

4. моя ошибка, у меня был преобразователь уровня поля, подключенный к updatedAt, я удалил его, теперь он работает.

5. Спасибо, Эрмия, очень благодарна за помощь.