如何在 DynamoDB 中查询不存在的(空)属性

Posted

技术标签:

【中文标题】如何在 DynamoDB 中查询不存在的(空)属性【英文标题】:How do you query for a non-existent (null) attribute in DynamoDB 【发布时间】:2016-03-24 18:43:16 【问题描述】:

我正在尝试查询 DynamoDB 表以查找未设置 email 属性的所有项目。名为EmailPasswordIndex 的全局二级索引存在于包含email 字段的表中。

var params = 
    "TableName": "Accounts",
    "IndexName": "EmailPasswordIndex",
    "KeyConditionExpression": "email = NULL",
;

dynamodb.query(params, function(err, data) 
    if (err)
        console.log(JSON.stringify(err, null, 2));
    else
        console.log(JSON.stringify(data, null, 2));
);

结果:


  "message": "Invalid KeyConditionExpression: Attribute name is a reserved keyword; reserved keyword: NULL",
  "code": "ValidationException",
  "time": "2015-12-18T05:33:00.356Z",
  "statusCode": 400,
  "retryable": false

表定义:

var params = 
    "TableName": "Accounts",
    "KeySchema": [
         "AttributeName": "id", KeyType: "HASH" , // Randomly generated UUID
    ],
    "AttributeDefinitions": [
         "AttributeName": "id", AttributeType: "S" ,
         "AttributeName": "email", AttributeType: "S" , // User e-mail.
         "AttributeName": "password", AttributeType: "S" , // Hashed password.
    ],
    "GlobalSecondaryIndexes": [
        
            "IndexName": "EmailPasswordIndex",
            "ProvisionedThroughput": 
                "ReadCapacityUnits": 1,
                "WriteCapacityUnits": 1
            ,
            "KeySchema": [
                 "AttributeName": "email", KeyType: "HASH" ,
                 "AttributeName": "password", KeyType: "RANGE" ,
            ],
            "Projection":  "ProjectionType": "ALL" 
        ,
    ],
    ProvisionedThroughput:        
        ReadCapacityUnits: 1, 
        WriteCapacityUnits: 1
    
;

dynamodb.createTable(params, function(err, data) 
    if (err)
        console.log(JSON.stringify(err, null, 2));
    else
        console.log(JSON.stringify(data, null, 2));
);

【问题讨论】:

你能提供你的表和索引属性定义吗? @mkobit 已添加,谢谢。 【参考方案1】:

既然 DynamoDB 就是这样,就需要使用非正统的方法来使用数据库。

我只是引入了一个特殊值,它可以是您的域中可以安全识别的任何内容(例如 "--NULL--"),然后在最低数据层将其与 null 进行转换。

查询该字段为 null 的条目只是查询该特殊值。

从习惯 SQL 的人的角度来看,这不是很好,但比扫描更好。

对于旧条目,您将需要一次性迁移。

【讨论】:

【参考方案2】:

@jaredHatfield 如果该字段不存在则正确,但如果该字段为空,则该字段将不起作用。 NULL 是关键字,不能直接使用。但是您可以将它与 ExpressionAttributeValues 一起使用。

const params = 
    TableName: "Accounts",
    FilterExpression: "attribute_not_exists(email) or email = :null",
    ExpressionAttributeValues: 
        ':null': null
    


dynamodb.scan(params, (err, data) => 
    if (err)
        console.log(JSON.stringify(err, null, 2));
    else
        console.log(JSON.stringify(data, null, 2));
)

【讨论】:

谢谢你的精确度,我就是在找那个:)【参考方案3】:

DynamoDB 的全局二级索引允许索引稀疏。这意味着,如果您有一个 GSI,其项目的哈希或范围键未定义,则该项目将根本不包含在 GSI 中。这在许多用例中都很有用,因为它允许您直接识别包含某些字段的记录。但是,如果您正在寻找缺少字段,则此方法将不起作用。

要获取所有未设置字段的项目,您最好的选择可能是使用过滤器进行扫描。此操作将非常昂贵,但它会是如下所示的简单代码:

var params = 
    TableName: "Accounts",
    FilterExpression: "attribute_not_exists(email)"
;

dynamodb.scan(params, 
    if (err)
        console.log(JSON.stringify(err, null, 2));
    else
        console.log(JSON.stringify(data, null, 2));
);

【讨论】:

以上是关于如何在 DynamoDB 中查询不存在的(空)属性的主要内容,如果未能解决你的问题,请参考以下文章

DynamoDB如何查询具有强一致性的非键属性?

可以将HASH密钥更新为预先存在的Dynamodb全局二级索引的另一个属性吗?

DynamoDB GSI - 仅包含一些行

DynamoDB Appsync 查询多个属性

如何按日期(范围键)查询 DynamoDB,没有明显的哈希键?

使用 Amazon Dynamodb 进行不区分大小写的查询