英文:
How does one create a GSI for an Item in a Array in DyanmoDB?
问题
我有一个DynamoDB表格,其中包含:
分区键:State(例如:两个字母的州ID)
排序键:City(州内城市的名称)
"record"中的项是一个数组,假设为Advertisements
"StateShort": "AK",
"City": "Anchorage",
"Ads": [
{
"AdDateAdded": 1674671363999,
"AdDateExpire": 1682447536551,
"AdIDKey": "ABC-123-GUID-Here",
"AdTitle": "This is the Title to Ad 1"
"AdDescription": "Description of the Details to Ad 1",
"AdOwner": "bob@example.com",
},
{
"AdDateAdded": 1674671363999,
"AdDateExpire": 1682447536551,
"AdIDKey": "DEF-456-GUID-Here",
"AdTitle": "This is the Title to Ad 2"
"AdDescription": "Description of the Details to Ad 2",
"AdOwner": "bob@example.com",
}
]
查询以检索特定State和City中的所有广告很容易,因为它们是主键和排序键。
但是,我不想扫描整个表来找到AdOwner为"bob@example.com"的所有广告。他们可能在其他州和城市有广告,需要我扫描整个表格。
*感觉*像是全局二级索引的完美用例。
我已经将AdOwner作为全局二级索引添加了进去,但显然它无法在数组中找到键。
问题:能用全局二级索引解决这个问题吗?如果可以,它会是什么样的结构?
在创建了全局二级索引后,我尝试了这段代码,但它没有返回任何项。
```javascript
const params = {
"TableName": "My_table",
"IndexName": "AdEmail-index",
"KeyConditionExpression": "#IndexName = :AccountID",
"ExpressionAttributeNames": {
"#IndexName": "AdOwner",
},
ExpressionAttributeValues: {
":AccountID": "bob@example",
},
"ScanIndexForward": false
}
try{
const item = await dynamo.query(params).promise()
console.log("what: ", item)
}
catch (e) {
console.log("ERROR", e)
}
<details>
<summary>英文:</summary>
I have a DyanmmoDB table that has:
Partition key: State (IE: two letter State ID)
Sort Key: City (Name of city in the state)
Items in the "record" is an array, let's say Advertisements
"StateShort": "AK",
"City": "Anchorage",
"Ads": [
{
"AdDateAdded": 1674671363999,
"AdDateExpire": 1682447536551,
"AdIDKey": "ABC-123-GUID-Here",
"AdTitle": "This is the Title to Ad 1"
"AdDescription": "Description of the Details to Ad 1",
"AdOwner": "bob@example.com",
},
{
"AdDateAdded": 1674671363999,
"AdDateExpire": 1682447536551,
"AdIDKey": "DEF-456-GUID-Here",
"AdTitle": "This is the Title to Ad 2"
"AdDescription": "Description of the Details to Ad 2",
"AdOwner": "bob@example.com",
}
]
Query to retrieve all ads in State and City, easy-peasy, as they are PK and SK.
but, I do NOT want to Scan to find all the ads that AdOwner has ("bob@example.com"). They may have Ads in other states and city requiring me to Scan entire table.
*FEELS* like a perfect use case for a Global secondary indexes.
I've added AdOwner as a GSI but, clearly it can't find the key in the array.
Question: Is this solvable with a GSI? If so, what structure would that look like?
After creating the GSI, I've tried this code but, it returns no items
const params = {
"TableName": "My_table",
"IndexName": "AdEmail-index",
"KeyConditionExpression": "#IndexName = :AccountID",
"ExpressionAttributeNames": {
"#IndexName": "AdOwner",
},
ExpressionAttributeValues: {
":AccountID": "bob@example",
},
"ScanIndexForward": false
}
try{
const item = await dynamo.query(params).promise()
console.log("what: ", item)
}
catch (e) {
console.log("ERROR", e)
}
</details>
# 答案1
**得分**: 1
不,全局二级索引键必须是顶层属性,且必须是`string`、`number`或`binary`类型。
您应该垂直分片您的项目,这将为您提供更多的灵活性:
|pk | sk | data|AdOwner
---|---|---|---
AK| Anchorage#BC-123-GUID-Here | {} | bob@example.com
AK| Anchorage#BDEF-456-GUID-Here | {} | bob@example.com
在一个州和城市中的所有广告,仍然很容易,使用`Query`:
`SELECT * FROM MY TABLE WHERE pk = 'AK' AND sk BEGINS_WITH 'Anchorage'`
现在,您可以在`AdOwner`上创建一个GSI以满足您的第二个访问模式。
`SELECT * FROM MY TABLE.INDEX WHERE AdOwnder = 'bob@example.com'`
<details>
<summary>英文:</summary>
No, a global secondary index key must be a top level attribute and be of type `string`, `number` or `binary`.
You should vertically shard your items, giving you more flexibility:
|pk | sk | data|AdOwner
---|---|---|---
AK| Anchorage#BC-123-GUID-Here | {} | bob@example.com
AK| Anchorage#BDEF-456-GUID-Here | {} | bob@example.com
All ads in a state and city, still easy, using `Query`:
`SELECT * FROM MY TABLE WHERE pk = 'AK' AND sk BEGINS_WITH 'Anchorage'`
You can now create a GSI on the `AdOwner` to fulfill your second access pattern.
`SELECT * FROM MY TABLE.INDEX WHERE AdOwnder = 'bob@example.com'`
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论