AWS DynamoDB - 提供的关键元素与架构不匹配

Posted

技术标签:

【中文标题】AWS DynamoDB - 提供的关键元素与架构不匹配【英文标题】:AWS DynamoDB - The provided key element does not match the schema 【发布时间】:2021-03-05 03:20:03 【问题描述】:

我在 AWS Cloud9 上创建了一个 Python 程序,该程序将一个列表写入 DynamoDB 并提示用户访问信息。当我运行程序时,我可以输入 Subject 和 CatalogNbr,但是它会打印一个错误:

Enter the Subject: 
SDEV
Enter the CatalogNbr: 
450
The provided key element does not match the schema

表的键是第一个名为 CourseID 的值,它们被写成字符串:

   ['1','SDEV', '450', 'Advanced Programming', '3'],

我还将哈希键设置为字符串:

        "AttributeDefinitions": [
            
                "AttributeName": "CourseID", 
                "AttributeType": "S"
            
        ], 

        "KeySchema": [
            
                "KeyType": "HASH", 
                "AttributeName": "CourseID"
            
        ], 

我认为它似乎匹配。我已经尝试更改我定义的函数中的值并创建一个新表,但我仍然遇到同样的错误。 AWS 凭证都在 us-east-1 中。我不确定我需要解决什么问题。

这是我正在使用的代码:

import boto3
from boto3.dynamodb.conditions import Key
from botocore.exceptions import ClientError
import sys
# define DynamoDB variables
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('Courses')
# a list of 10 courses
allCourses = [        
    ['1','SDEV', '450', 'Advanced Programming', '3'],
    ['2','SDEV', '325', 'Detecting Software Vulnerabilities', '3'],
    ['3','CMIS', '102', 'Media and Society', '3'],
    ['4','CMIS', '141', 'Indroductory Programming', '3'],
    ['5','CMIS', '242', 'Intermediate Programming', '3'],
    ['6','CMIS', '102', 'Introduction to Problem Solving and Algorithm Design', '3'],
    ['7','CMIS', '320', 'Relational Database Concepts and Applications', '3'],
    ['8','CHEM', '101', 'Intro to Chemistry', '3'],
    ['9','MATH', '200', 'Calculus 1', '3'],
    ['10','ECON', '101', 'Intro to Economics', '3']
]
    
# for each course in the "allCourses" list
for course in allCourses:
    
    # assign values to variables
    CourseID = course[0]
    Subject = course[1]
    CatalogNbr = course[2]
    Title = course[3]
    NumCredits = course[4]
    
    # put item in table "Courses"
    table.put_item(
        Item=
    'CourseID': CourseID,
    'Subject': Subject,
    'CatalogNbr': CatalogNbr,
    'Title': Title,
    'NumCredits': NumCredits
        
    )
    
def check_class_info(Subject, CatalogNbr, dynamodb=None): # checks if class info exists
    if not dynamodb:
        dynamodb = boto3.resource('dynamodb')
    
    try:
        response = table.get_item(Key='Subject': Subject, 'CatalogNbr': CatalogNbr)
        print(get_class_info(Subject, CatalogNbr, Title))
    except ClientError as e:
        print(e.response['Error']['Message'])
        print("Course does not exist. Please try again")
        print(end_navigator())
            
def get_class_info(Subject, CatalogNbr, Title, dynamodb=None): # gets class info from AllCourses
    if not dynamodb:
        dynamodb = boto3.resource('dynamodb')
    try:
        response = table.get_item(Key='Subject': Subject, 'CatalogNbr': CatalogNbr, 'Title': Title) 
        print("The title of ", Subject, " ", CatalogNbr, " is ", Title)
        print(end_navigator())
        
    except ClientError as e:
        print(e.response['Error']['Message'])
        print("Cannot retrieve class info. Please try again.")
        print(end_navigator())
        
def end_navigator():
    user_choice = input("Would you like to search for another title? Y or N\n")
    if user_choice == "Y":
        return navigator()
    elif user_choice =="N":
        sys.exit("Thank you for using the Course Title Navigator")
        
    else:
        print("Invalid entry. Please try again.")
        return end_navigator()
            
def navigator():
    
    print("Welcome to the Course Title Navigator\n") # User prompt
    
    print("Enter the Subject: ")
    Subject = str(input())
    
    print("Enter the CatalogNbr: ")
    CatalogNbr = str(input())
    
    check_class_info(Subject, CatalogNbr)
        
    print(get_class_info(Subject, CatalogNbr, Title))
    
    print(end_navigator())
        
print(navigator())

这是桌子。

    
    "Table": 
        "TableArn": "arn:aws:dynamodb:us-east-1:399520938535:table/Courses", 
        "AttributeDefinitions": [
            
                "AttributeName": "CourseID", 
                "AttributeType": "S"
            
        ], 
        "ProvisionedThroughput": 
            "NumberOfDecreasesToday": 0, 
            "WriteCapacityUnits": 150, 
            "ReadCapacityUnits": 150
        , 
        "TableSizeBytes": 753, 
        "TableName": "Courses", 
        "TableStatus": "ACTIVE", 
        "TableId": "6efba366-56d8-4ad6-86b2-8b14f161c94f", 
        "KeySchema": [
            
                "KeyType": "HASH", 
                "AttributeName": "CourseID"
            
        ], 
        "ItemCount": 10, 
        "CreationDateTime": 1614907161.717
    

【问题讨论】:

能否添加您正在使用的代码或(部分代码)? 你能发布完整的表定义和你正在执行的查询吗?发生此错误通常是因为您没有提供正确的主键我是您的查询。 enter the Subject and CatalogNbr - 这是什么? @samlima 我在帖子中添加了我的代码。 @SethGeoghegan 我使用定义表添加了表信息。这就是你要找的,对吗? 【参考方案1】:

就像评论中提到的@hoangdv一样,您使用的Key参数不正确。您必须使用哈希键才能做到这一点(例如Key='CourseID': '3')。如果要根据SubjectCatalogNbr 获取行,则必须扫描表,然后查找与您要查找的键匹配的结果。下面是一个代码示例,可用于根据SubjectCatalogNbr 获取Title

def get_title(Subject, CatalogNbr):
    response = table.scan()
    row = next(item for item in response['Items'] if item['Subject'] == Subject and item['CatalogNbr'] == CatalogNbr)
    title = row['Title']
    print("The title of ", Subject, " ", CatalogNbr, " is ", title)
    return title

另一种可能的解决方案是更改哈希键,即使用属性Subject 作为哈希键和CatalogNbr 作为排序键。在这种情况下,您只需确保此组合是唯一的。

【讨论】:

以上是关于AWS DynamoDB - 提供的关键元素与架构不匹配的主要内容,如果未能解决你的问题,请参考以下文章

DynamoDB / Scanamo:提供的关键元素与架构不匹配

DynamoDB 简单 UpdateItem 抛出“提供的关键元素与架构不匹配”ValidationException

我们可以通过 AWS SDK 使用 GSI 删除 DynamoDB 中的项目吗?

DynamoDB AmazonServiceException:提供的关键元素与架构不匹配

从 DynamoDB 获取项目时出现“提供的关键元素与架构不匹配”错误

DynamoDB - 关键元素与架构不匹配