在过去的几年中,我不必使用批处理API。在考虑更多时,这并不是我对API有任何反对,而是我从来没有理由与之合作。但是,在过去的几个月中,我看到我在一个项目中两次使用了它,并取得了良好的成功。我的Golang和DynamoDB内容表现良好,所以我认为这可能会有一些食欲。话虽如此,我写了这篇文章,重点介绍了如何使用Golang使用DynamoDB的batchgetItem。
设置
对于这篇文章,我只想使用一个简单的示例,您一定可以从那里延伸。该示例本身可以通过几种不同的设计模型来解决,但是在这种情况下,假设我有一批我想通过其钥匙检索的公司清单。如果有数百万公司,您永远不会这样做,但是对于我的用例以及我的数据的建模方式,我最多将拥有10个。
这是该数据的一个小例子
似乎总是使用DynamoDB,有多种方法可以解决此问题,但是BatchGetItem会做得很好。
执行
因此,用于使用Golang执行batchgetItem,您首先要利用DynamoDB SDK
让我们看一下一些代码以将其拉在一起。 Github Gist of you want to see it in a full window
func (d *DynamoDBCompanyRepository) GetCompanies(ctx context.Context, companyIds []string) ([]models.Company, error) {
var keys []map[string]*dynamodb.AttributeValue
for _, c := range companyIds {
key := models.GetCompanyKey(c)
m := map[string]*dynamodb.AttributeValue{
"PK": {
S: aws.String(key),
},
"SK": {
S: aws.String(key),
},
}
keys = append(keys, m)
}
input := &dynamodb.BatchGetItemInput{
RequestItems: map[string]*dynamodb.KeysAndAttributes{
d.tableName: {
Keys: keys,
},
},
}
log.WithFields(log.Fields{
"input": input,
}).Debug("The query input")
var companies []models.Company
err := d.db.BatchGetItemPagesWithContext(
ctx, input,
func(page *dynamodb.BatchGetItemOutput, lastPage bool) bool {
for _, v := range page.Responses {
for _, v2 := range v {
var c models.Company
_ = dynamodbattribute.UnmarshalMap(v2, &c)
companies = append(companies, c)
}
}
return lastPage
})
if err != nil {
return nil, err
}
return companies, nil
}
所以将其分解。该功能除了上下文之外还采用公司ID片,并返回了许多编组的公司。
func (d *DynamoDBCompanyRepository) GetCompanies(ctx context.Context, companyIds []string) ([]models.Company, error)
接下来,需要指定查询的键。在此示例的情况下
var keys []map[string]*dynamodb.AttributeValue
for _, c := range companyIds {
key := models.GetCompanyKey(c)
m := map[string]*dynamodb.AttributeValue{
"PK": {
S: aws.String(key),
},
"SK": {
S: aws.String(key),
},
}
keys = append(keys, m)
}
附带说明,GetCompanykey只是一个返回钥匙的简单函数。这是
func GetCompanyKey(id string) string {
return fmt.Sprintf("COMPANY#%s", id)
}
一旦将密钥打包了,就该进行查询输入了。看起来像这样
input := &dynamodb.BatchGetItemInput{
RequestItems: map[string]*dynamodb.KeysAndAttributes{
d.tableName: {
Keys: keys,
},
},
}
还有许多其他选项可以探索,但是我只是使用表名和键。请随时在这里查看full documentation。
最后一部分是循环浏览返回的页面,然后处理每个页面的内容
var companies []models.Company
err := d.db.BatchGetItemPagesWithContext(
ctx, input,
func(page *dynamodb.BatchGetItemOutput, lastPage bool) bool {
for _, v := range page.Responses {
for _, v2 := range v {
var c models.Company
_ = dynamodbattribute.UnmarshalMap(v2, &c)
companies = append(companies, c)
}
}
return lastPage
})
if err != nil {
return nil, err
}
return companies, nil
如果您想对选项有更多清晰的清晰度,请再次查看documentation,但总体上的想法是,您循环浏览页面,对于每个页面循环,您提供了一个可以处理输出的函数。在上面的情况下,公司只是被拆除并添加到一个切片中。如果您有任何自定义编组,本文可能会有所帮助
包起来
我希望您能看到,使用Golang使用batchgetItem是一种简单而相当简单的方法,可以在包含一组呼叫的一组中获取您想要的一组有限的项目。同样,请注意您在某种程度上有其他方法可以做到这一点,并且该模型将在很大程度上推动您的方法,但是在上面的示例中,我看到了这在生产中的表现很好。
希望您发现这个有用!