Dynamodb-serverless отношения один ко многим и многие ко многим

Я действительно новичок в мире Dynamodb и NoSQL. Я практикую AWS GSI и LSI. Я использую бессерверный фреймворк. Я разделил свои обработчики на несколько лямбда-функций. Я хочу создать свои данные, в которых я могу видеть все рестораны и цену какого сорта пива. Также я хочу запросить все сорта пива без цены. Я успешно создал ресторан с ключом раздела id. Я могу получить все данные о ресторанах. Но я придерживался пивной логики. Я создаю конечную точку api для такого пива restaurant/{id}/createBeers, когда я делал почтовый запрос, я получал ошибку "message": "One or more parameter values were invalid: Missing the key id in the item", потому что он запрашивал идентификатор ресторана. Я не могу найти логику, в которой я могу добавить идентификатор ресторана для создания пива и как получить все пиво бесплатно.

Ресторан один ко многим. Пиво много ко многим (одно и то же название, разные цены в зависимости от ресторана). Это то, чего я хочу достичь.

[
      {
        "id": 1,
        "name": "restaurent 1",
        "beers": {
            "tap-beers": [{
                    "name": "beer 1",
                    "price": "2$"
                },
                {
                    "name": "beer 2",
                    "price": "2$"
                }
            ],
            "bottle-beers": [{
                    "name": "beer 3",
                    "price": "2$"
                },
                {
                    "name": "beer 4",
                    "price": "2$"
                }
            ]
        }
    },
    
      {
        "id": 2,
        "name": "restaurent 2",
        "beers": {
            "tap-beers": [{
                    "name": "beer 1",
                    "price": "3$"
                },
                {
                    "name": "beer 2",
                    "price": "3$"
                }
            ],
            "bottle-beers": [{
                    "name": "beer 3",
                    "price": "4$"
                },
                {
                    "name": "beer 4",
                    "price": "6$"
                }
            ]
        }
    }
]

Вот как я хочу получить все пиво на столе

[
  {
    "beername": "beer 1"
  },
   {
    "beername": "beer 2"
  },
   {
    "beername": "beer 3"
  },
   {
    "beername": "beer 4"
  }
]

Это мой ресторан

const dynamoDb = new AWS.DynamoDB.DocumentClient();
module.exports.createRestaurant = async event => {
  const resquestBody = JSON.parse(event.body);

  const params = {
    TableName: "table name",
    Item: {
      id: uuid.v1(),
      name: resquestBody.name,
      beers: [] // in here I will add beers when I can create a beer my post method path 
                // is restaurant/{id}/createBeers
    }
  }

  try {
    await dynamoDb.put(params).promise();
    return {
      statusCode: 200,
      body: JSON.stringify(resquestBody),
    };
  } catch (error) {
    return {
      statusCode: 500,
      body: JSON.stringify(error),
    };
  }
};

Это создание обработчика пива

const dynamoDb = new AWS.DynamoDB.DocumentClient();
module.exports.createBeers = async event => {
  const requestBody = JSON.parse(event.body);
  const params = {
    TableName: "table name",
    Item: {
      beer_name: requestBody.beer_name,
      beer_type: requestBody.beer_type,
      beer_price: requestBody.beer_price
    }
  };

  try {
    await dynamoDb.put(params).promise();
    return {
      statusCode: 200,
      body: JSON.stringify(requestBody),
    };
  } catch (error) {
    return {
      statusCode: 500,
      body: JSON.stringify(error),
    };
  }
};

Это мой GSI пиво бесплатно

module.exports.getBeers = async event => {

  const params = {
    TableName: "beer",
    IndexName: "beers",
    KeyConditionExpression: "beer_name = :beer_name",
    ExpressionAttributeValues: {
      ":beer_name": "beer_name"
    },
    Limit: 1
  }

  try {
    let data = await dynamoDb.query(params).promise();
    return {
      statusCode: 200,
      body: JSON.stringify(data.Items),
    };
  } catch (error) {
    return {
      statusCode: 500,
      body: JSON.stringify(error),
    };
  }

}

Это мой бессерверный yml-файл

functions:
  createRestaurant:
    handler: handlers/createRestaurant.createRestaurant
    events:
      - https:
          path: restaurant
          method: post
          cors: true
  getRestaurants:
    handler: handlers/getRestaurants.getRestaurants
    events:
      - https:
          path: restaurant/all
          method: get
          cors: true
  createBeers:
    handler: handlers/createBeers.createBeers
    events:
      - https:
          path: restaurant/{id}/beers
          method: post
          cors: true
  getBeers:
    handler: handlers/getBeers.getBeers
    events:
      - https:
          path: beers/all
          method: get
          cors: true
resources:
  Resources:
    table:
      Type: "AWS::DynamoDB::Table"
      DeletionPolicy: Retain
      Properties:
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
          - AttributeName: beer_name
            AttributeType: S
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        GlobalSecondaryIndexes:
          - IndexName: beers
            KeySchema:
              - AttributeName: beer_name
                KeyType: HASH
            Projection:
              ProjectionType: ALL
            ProvisionedThroughput:
              ReadCapacityUnits: 1
              WriteCapacityUnits: 1
        TableName: "tableName"

См. также:  Использование DevOps Release Pipeline для загрузки артефактов на сервер Linux
Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. Krisna

    Сущности + отношения

    Насколько я понимаю, у вас есть две сущности:

    • Restaurant
      • ID
      • Имя
    • Beer
      • Name

    В каждом ресторане может быть несколько сортов пива, и каждый медведь либо разливается в бутылки, либо разливается, а также имеет цену.

    Шаблоны доступа

    Вы хотите включить эти шаблоны доступа:

    1. Получите список ресторанов
    2. Получите список сортов пива в ресторане
    3. Получите список пива во всех ресторанах

    Макет стола

    Я предлагаю единую таблицу с глобальным вторичным индексом (GSI1), которая выглядит так:

    Первичный вид таблицы

    Первичная ключевая перспектива

    Просмотр таблицы GSI1

    GSI1 Perspective

    Как запросить

    1. Чтобы получить список всех ресторанов, выполните запрос к GSI1 с PK=RESTAURANTS
    import typing
    import boto3
    import boto3.dynamodb.conditions as conditions
    
    def get_all_restaurants() -> typing.List[dict]:
    
        table = boto3.resource("dynamodb").Table("table-name")
    
        response = table.query(
            KeyConditionExpression=conditions.Key("GSI1PK").eq("RESTAURANTS"),
            IndexName="GSI1"
        )
    
        return response["Items"]
    
    1. Чтобы получить список всех сортов пива в данном ресторане, вы выполняете запрос по первичному индексу с помощью PK=R<restaurant-id> and SK begins_with B (вы можете заменить B на B-TP для списка всех сортов разливного пива или B-BB для всех сортов пива в бутылках. Избавьтесь от условия SK для получения всей информации о ресторане.)
    import typing
    import boto3
    import boto3.dynamodb.conditions as conditions
    
    def get_beers_in_restaurant(restaurant_id: str) -> typing.List[dict]:
    
        table = boto3.resource("dynamodb").Table("table-name")
    
        response = table.query(
            KeyConditionExpression=conditions.Key("PK").eq(f"R#{restaurant_id}") \
                & conditions.Key("SK").begins_with("B-")
        )
    
        return response["Items"]
    
    def get_tap_beers_in_restaurant(restaurant_id: str) -> typing.List[dict]:
    
        table = boto3.resource("dynamodb").Table("table-name")
    
        response = table.query(
            KeyConditionExpression=conditions.Key("PK").eq(f"R#{restaurant_id}") \
                & conditions.Key("SK").begins_with("B-TB")
        )
    
        return response["Items"]
    
    def get_bottled_beers_in_restaurant(restaurant_id: str) -> typing.List[dict]:
    
        table = boto3.resource("dynamodb").Table("table-name")
    
        response = table.query(
            KeyConditionExpression=conditions.Key("PK").eq(f"R#{restaurant_id}") \
                & conditions.Key("SK").begins_with("B-BB")
        )
    
        return response["Items"]
    
    1. Чтобы получить список всех сортов пива, выполните запрос к GSI1 с PK=BEERS. Вы получите дубликаты, поэтому вам нужно удалить их на стороне клиента.
    import typing
    import boto3
    import boto3.dynamodb.conditions as conditions
    
    def get_all_beers() -> typing.List[dict]:
    
        table = boto3.resource("dynamodb").Table("data")
    
        response = table.query(
            KeyConditionExpression=conditions.Key("GSI1PK").eq("BEERS"),
            IndexName="GSI1"
        )
        
        list_with_duplicates = [item["name"] for item in response["Items"]]
        list_without_duplicates = list(set(list_with_duplicates))
    
        return [{"beername": name} for name in list_without_duplicates]
    

    Добавление предметов в таблицу

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

    Добавление ресторана

    Рестораны довольно простые, им нужен только идентификатор и имя. Из этой информации мы можем вычислить ключевые атрибуты:

    import boto3
    
    def create_restaurant(restaurant_id: str, name: str) -> None:
        table = boto3.resource("dynamodb").Table("data")
    
        item = {
            "PK": f"R#{restaurant_id}",
            "SK": "META",
            "GSI1PK": "RESTAURANTS",
            "GSI1SK": f"R#{restaurant_id}",
            "type": "RESTAURANT",
            "id": restaurant_id,
            "name": name
        }
    
        table.put_item(
            Item=item
        )
    

    Добавьте пиво в ресторан

    Пиво всегда принадлежит ресторану, поэтому нам нужен его идентификатор — у него всегда есть цена и название.

    import boto3
    
    def create_beer_for_restaurant(restaurant_id: str, name: str, price: str, is_tap: bool):
    
        table = boto3.resource("dynamodb").Table("data")
    
        sk = f"B-TB#{name}" if is_tap else f"B-BB#{name}"
    
        item = {
            "PK": f"R#{restaurant_id}",
            "SK": sk,
            "GSI1PK": "BEERS",
            "GSI1SK": f"B#{name}",
            "name": name,
            "price": price
        }
    
        table.put_item(
            Item=item
        )
    

    Могу я поболтать с тобой ?? person Krisna; 08.03.2021

    Я предпочитаю оставлять это в комментариях, чтобы будущие читатели могли извлечь из этого пользу. person Krisna; 08.03.2021

    аааа Правдивая история. person Krisna; 08.03.2021

    Я изучаю код. Не могли бы вы показать мне в коде, как мне это сделать? person Krisna; 08.03.2021

    Я не говорю на узле, но я добавил несколько примеров на Python. Я забыл обновить несколько названий в таблице образцов — для некоторых сортов пива в названии отображается неправильный номер. person Krisna; 08.03.2021

    Черт возьми. Я не так хорошо знаю Python. person Krisna; 08.03.2021

    AttributeDefinitions: — AttributeName: PK AttributeType: S — AttributeName: SK AttributeType: S — AttributeName: GSI1PK AttributeType: S — AttributeName: GSI1SK AttributeType: S KeySchema: — AttributeName: PK KeyType: HASHAN — AttributeName: : GSI1 KeySchema: — AttributeName: GSI1PK KeyType: HASH — AttributeName: GSI1SK KeyType: RANGE person Krisna; 08.03.2021

    Я определяю свой бессерверный Yml следующим образом person Krisna; 08.03.2021

    Это вопрос? person Krisna; 08.03.2021

    Нет, сэр, я ломаю голову, как делать публикации и запросы на основе вашего предложения person Krisna; 08.03.2021

    Я чувствую, что близок, но все еще так далеко: tenor.com / view / so-close-dog-Swimming-pool-gif-15044972 person Krisna; 08.03.2021

    На прошлой неделе я опубликовал Intro do DynamoDB в качестве сообщения в блоге, и в конце есть несколько ссылок на полезные доклады о re: discover, может быть, это поможет: aws-blog.de/2021/03/dynamodb-in-15-minutes.html person Krisna; 08.03.2021

    Как я могу создать почтовый запрос на основе ключа сортировки person Krisna; 08.03.2021

    const params = {TableName: TableNAME, Item: {PK: R#${uuid.v1()}, SK: ??? name: resquestBody.name} person Krisna; 08.03.2021

    Что вы пытаетесь сделать? person Krisna; 08.03.2021

    Добавлены примеры создания предметов. person Krisna; 08.03.2021

    Я купил книгу Алекса Дебри. Он объясняет примерно так же, как и вы. Спасибо за помощь. Нужно очень хорошо изучать сущности person Krisna; 09.03.2021

    Позвольте нам продолжить это обсуждение в чате. person Krisna; 09.03.2021

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: