You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DynamoDB中创建带有索引属性的条目?

解决DynamoDB创建条目时索引属性无法查询的问题

你的核心问题是没有提前在表中定义对应的二级索引,所以直接写入date和timestamp只会被当作普通属性,无法通过索引查询。下面是具体的解决步骤和JS代码示例:

1. 先创建/更新表,添加二级索引

DynamoDB的二级索引(全局GSI/局部LSI)必须先在表结构中定义,才能让对应的属性成为索引字段。

示例1:创建表时同时定义全局二级索引

如果你的表还没创建,可以在创建时直接加入索引:

const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB({ region: '你的区域' });

const createTableParams = {
  TableName: 'Posts_Table',
  // 表的主键定义
  KeySchema: [
    { AttributeName: 'username', KeyType: 'HASH' },
    { AttributeName: 'image_id', KeyType: 'RANGE' }
  ],
  // 所有需要用到的属性类型定义(包括索引属性)
  AttributeDefinitions: [
    { AttributeName: 'username', AttributeType: 'S' },
    { AttributeName: 'image_id', AttributeType: 'S' },
    { AttributeName: 'date', AttributeType: 'S' }, // 索引属性的类型
    { AttributeName: 'timestamp', AttributeType: 'N' }
  ],
  // 定义全局二级索引
  GlobalSecondaryIndexes: [
    {
      IndexName: 'DateTimestampIndex', // 索引名称,查询时要用到
      KeySchema: [
        { AttributeName: 'date', KeyType: 'HASH' }, // 索引的Hash键
        { AttributeName: 'timestamp', KeyType: 'RANGE' } // 索引的Range键
      ],
      Projection: {
        ProjectionType: 'ALL' // 投影所有属性到索引,也可以指定具体属性
      },
      ProvisionedThroughput: {
        ReadCapacityUnits: 5,
        WriteCapacityUnits: 5
      }
    }
  ],
  ProvisionedThroughput: {
    ReadCapacityUnits: 5,
    WriteCapacityUnits: 5
  }
};

dynamodb.createTable(createTableParams, (err, data) => {
  if (err) console.error('创建表失败:', err);
  else console.log('表创建成功:', data);
});

示例2:给已存在的表添加全局二级索引

如果表已经创建好,可以通过更新表来添加索引:

const updateTableParams = {
  TableName: 'Posts_Table',
  AttributeDefinitions: [
    { AttributeName: 'date', AttributeType: 'S' },
    { AttributeName: 'timestamp', AttributeType: 'N' }
  ],
  GlobalSecondaryIndexUpdates: [
    {
      Create: {
        IndexName: 'DateTimestampIndex',
        KeySchema: [
          { AttributeName: 'date', KeyType: 'HASH' },
          { AttributeName: 'timestamp', KeyType: 'RANGE' }
        ],
        Projection: { ProjectionType: 'ALL' },
        ProvisionedThroughput: {
          ReadCapacityUnits: 5,
          WriteCapacityUnits: 5
        }
      }
    }
  ]
};

dynamodb.updateTable(updateTableParams, (err, data) => {
  if (err) console.error('更新表失败:', err);
  else console.log('表更新成功:', data);
});

2. 插入数据并使用索引查询

当索引创建完成后,你之前的插入代码完全可以用——只要Item包含索引的键属性,DynamoDB会自动把数据同步到索引中。之后查询时需要指定索引名称:

插入数据(你的原代码可以直接用)

const docClient = new AWS.DynamoDB.DocumentClient({ region: '你的区域' });

const params = {
  TableName: 'Posts_Table',
  Item: {
    'username': user,
    'image_id': uuid(),
    'date': date,
    'timestamp': timestamp
  }
};

docClient.put(params, (err, data) => {
  if (err) console.error('插入失败:', err);
  else console.log('插入成功:', data);
});

通过索引查询数据

const queryParams = {
  TableName: 'Posts_Table',
  IndexName: 'DateTimestampIndex', // 指定要使用的索引名称
  KeyConditionExpression: '#dt = :targetDate',
  ExpressionAttributeNames: { '#dt': 'date' }, // 避免关键字冲突
  ExpressionAttributeValues: { ':targetDate': '2024-05-20' } // 要查询的日期值
};

docClient.query(queryParams, (err, data) => {
  if (err) console.error('查询失败:', err);
  else console.log('查询结果:', data.Items);
});

关键注意点

  • 局部二级索引(LSI)必须和表一起创建,不能事后添加,且LSI的Hash键必须和表的Hash键一致,只能指定不同的Range键。
  • 索引创建/更新需要一段时间,完成后才能查询到新插入的数据。
  • 投影类型选择ALL会把所有属性同步到索引,适合小数据量;如果数据量大,建议只投影需要查询的属性,节省存储和读写成本。

内容的提问来源于stack exchange,提问作者henry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 12:40:21