Эффективный способ получить элемент по идентификатору с Appsync и DynamoDB - PullRequest
0 голосов
/ 12 апреля 2019

Я хочу создать и использовать URL-адреса slug для использования с сайтом блога, созданным поверх Appsync и DynamoDB через AWS Amplify.Слизень - это сочетание названия статьи и cuid;например, /article/an-interesting-post-on-bats-123abc вернет сообщение с заголовком "Интересная запись о летучих мышах".Это было бы относительно просто, но с некоторыми ограничениями:

  • Действие GetItem DynamoDB работает только с первичным ключом.
  • Первичный ключ элемента не может быть изменен.Чтобы «изменить» первичный ключ, вы должны удалить и воссоздать элемент.
  • Данные сущности Article поддаются изменению с течением времени, так как пользователь может изменить заголовок, текст статьи и т. Д. Aизменение названия может привести к изменению слизняка.Фактически, пользователь может сохранить Article, еще не введя заголовок, поэтому слаг не может быть основой для первичного ключа (поскольку это необходимо для создания элемента).

Кажется довольно ясным, что сам слаг является плохим выбором для первичного ключа;однако slug - это единственный вход (в качестве параметра пути), доступный в настоящее время для создания запроса. Учитывая эти ограничения, каков наиболее эффективный способ запроса Article, если у меня есть только слаг?

На данный момент я достаточно рано на этапе проектирования, что несколькоресурсы могут быть изменены: (1) URL статьи, (2) дизайн DynamoDB (т.е. что такое первичный ключ и ключи сортировки);и (3) схема Appsync.

В настоящее время схема Article содержит:

type Article @model {
  id: ID! // the primary key
  authorId: String
  title: String
  text: String
  slug: String
}

Несмотря на то, что можно сканировать слаг, это кажется неэффективным способом использованияДинамо для регулярного доступа.У меня была мысль сделать authorId первичным ключом с slug в качестве ключа сортировки или локального вторичного индекса.Это похоже на то, как Medium и StackOverflow создают URL-адреса сообщений.

1 Ответ

0 голосов
/ 17 апреля 2019

Вы можете создать вторичный индекс для атрибута slug. Затем вам нужно будет создать еще один запрос GraphQL и соответствующий ему преобразователь, используя операцию запроса DynamoDB. Запрос гораздо более эффективен, чем сканирование.

Для этого у вас есть два варианта. В первом случае вы можете следить за дизайном операции запроса и возвращать список статей вместо одной статьи. Это может быть достигнуто с помощью connectionModels или просто типа, который возвращает список.

Например

## Schema
type ArticleConnection{
  items: [Article]
}

type Query {
    getArticle(id: ID!): Article
    getArticleBySlug(slug: String): ArticleConnection // Query on secundary index
}


## Resolver
## Request Mapping Template
{
    "version": "2017-02-28",
    "operation": "Query",
    "scanIndexForward": true,
    "index" : "slug",
    "select" : "ALL_ATTRIBUTES",
    "query" : {
        "expression" : "slug = :slug",
        "expressionValues" : {
            ":slug" : $util.dynamodb.toDynamoDBJson("${ctx.args.slug}")
        }
    }
}

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

Или, если вы хотите сохранить соответствие с первым запросом, вы можете сделать следующее

## Schema
type Query {
    getArticle(id: ID!): Article
    getArticleBySlug(slug: String): Article // Query on secundary index
}


## Resolver
## Request Mapping Template
{
    "version": "2017-02-28",
    "operation": "Query",
    "scanIndexForward": true,
    "index" : "slug",
    "select" : "ALL_ATTRIBUTES",
    "query" : {
        "expression" : "slug = :slug",
        "expressionValues" : {
            ":slug" : $util.dynamodb.toDynamoDBJson("${ctx.args.slug}")
        }
    }
}

## Response Mapping Template
#if($ctx.result.items.size() > 0)
   $util.toJson($ctx.result.items[0])
#else
    null
#end
...