如何在DynamoDB中为数组中的项目创建GSI?

huangapple go评论44阅读模式
英文:

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 &quot;record&quot; is an array, let&#39;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 (&quot;bob@example.com&quot;). 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&#39;ve added AdOwner as a GSI but, clearly it can&#39;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&#39;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(&quot;what: &quot;, item)
}
catch (e) {
    console.log(&quot;ERROR&quot;, 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 = &#39;AK&#39; AND sk BEGINS_WITH &#39;Anchorage&#39;`

现在,您可以在`AdOwner`上创建一个GSI以满足您的第二个访问模式。

`SELECT * FROM MY TABLE.INDEX WHERE AdOwnder = &#39;bob@example.com&#39;`

<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 = &#39;AK&#39; AND sk BEGINS_WITH &#39;Anchorage&#39;`

You can now create a GSI on the `AdOwner` to fulfill your second access pattern. 


`SELECT * FROM MY TABLE.INDEX WHERE AdOwnder = &#39;bob@example.com&#39;`


</details>



huangapple
  • 本文由 发表于 2023年2月8日 22:59:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75387622.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定