Amazon dynamodb DynamoDB批处理执行查询请求

Amazon dynamodb DynamoDB批处理执行查询请求,amazon-dynamodb,Amazon Dynamodb,我有下面的DynamoDB查询,它返回第一条带有hash apple和小于某个时间戳的时间戳的记录 Map-keyConditions=newHashMap(); 放置(“哈希”,新条件()。 与比较器(EQ)相比。 WithAttributeValue列表(新的AttributeValue().With(“苹果”)) ); 放置(“时间戳”,新条件()。 与比较器(LE)相比。 WithAttributeValue列表(新的AttributeValue().withN(某些时间戳))) );

我有下面的DynamoDB查询,它返回第一条带有hash apple和小于某个时间戳的时间戳的记录

Map-keyConditions=newHashMap();
放置(“哈希”,新条件()。
与比较器(EQ)相比。
WithAttributeValue列表(新的AttributeValue().With(“苹果”))
);
放置(“时间戳”,新条件()。
与比较器(LE)相比。
WithAttributeValue列表(新的AttributeValue().withN(某些时间戳)))
);
QueryResult QueryResult=dynamoDBClient.query(
新建QueryRequest()。
withTableName(“表格”)。
withKeyConditions(keyConditions)。
带限制(1)。
向前扫描索引(向前扫描索引)
);
我需要执行许多此类查询,因此我的问题是:是否可以批量执行这些查询?类似于下面的API

Map<String, Condition> keyConditions = newHashMap();

keyConditions.put("HASH", new Condition().
    withComparisonOperator(EQ).
    withAttributeValueList(new AttributeValue().withS("apple")))
);

keyConditions.put("TIMESTAMP", new Condition().
    withComparisonOperator(LE).
    withAttributeValueList(new AttributeValue().withN(some_timestamp)))
);

QueryRequest one = new QueryRequest().
    withTableName("TABLE").
    withKeyConditions(keyConditions).
    withLimit(1).
    withScanIndexForward(SCAN_INDEX_FORWARD);

keyConditions = newHashMap();

keyConditions.put("HASH", new Condition().
    withComparisonOperator(EQ).
    withAttributeValueList(new AttributeValue().withS("pear")))
);

keyConditions.put("TIMESTAMP", new Condition().
    withComparisonOperator(LE).
    withAttributeValueList(new AttributeValue().withN(some_other_timestamp)))
);

QueryRequest two = new QueryRequest().
    withTableName("TABLE").
    withKeyConditions(keyConditions).
    withLimit(1).
    withScanIndexForward(SCAN_INDEX_FORWARD)

ArrayList<String> queryRequests = new ArrayList<String>() {{
    add(one);
    add(two);
}};

List<QueryResult> queryResults = dynamoDBClient.query(queryRequests);
Map-keyConditions=newHashMap();
放置(“哈希”,新条件()。
与比较器(EQ)相比。
WithAttributeValue列表(新的AttributeValue().With(“苹果”))
);
放置(“时间戳”,新条件()。
与比较器(LE)相比。
WithAttributeValue列表(新的AttributeValue().withN(某些时间戳)))
);
QueryRequest one=新建QueryRequest()。
withTableName(“表格”)。
withKeyConditions(keyConditions)。
带限制(1)。
向前使用CANINDEX(向前扫描索引);
keyConditions=newHashMap();
放置(“哈希”,新条件()。
与比较器(EQ)相比。
WithAttributeValue列表(新的AttributeValue().With(“pear”))
);
放置(“时间戳”,新条件()。
与比较器(LE)相比。
WithAttributeValue列表(新的AttributeValue().withN(某些其他时间戳)))
);
QueryRequest two=新建QueryRequest()。
withTableName(“表格”)。
withKeyConditions(keyConditions)。
带限制(1)。
向前扫描索引(向前扫描索引)
ArrayList queryRequests=新的ArrayList(){{
增加(一);
增加(2);
}};
List queryResults=dynamoDBClient.query(queryRequests);

来自AWS论坛上一个非常类似的问题:

DynamoDB的查询API只支持在查询操作中单一地“使用”索引,因此,必须将正在查询的索引的“哈希”指定为EQ条件。DynamoDB目前没有任何类型的“批处理查询”API,因此很遗憾,您现在所寻找的不可能在单个API调用中实现。如果这些是GetItem请求(但不适合您的用例),您可以发出BatchGetItem请求

同时,由于看起来您正在使用Java,我的建议是使用线程并行发出多个查询请求。这里有一些实现这一点的示例代码,但是您将要考虑您希望应用程序如何处理分页/部分结果,以及错误:

/**
*在DynamoDB中通过查询索引来模拟“批量查询”操作
*多个散列键
* 
*如果任何查询超时,结果列表可能不完整。返回一个
*查询结果,以便可以遵循LastEvaluatedKeys。更好的实施
*将回答某些查询失败的情况,处理分页(和
*限制),具有可配置的超时。这方面的一个改进是
*要生成包含查询结果或异常的简单不可变bean,
*以及相关的请求。也许它甚至可以被召回
*以前用于分页的列表。
* 
*@param hashKeyValues(您还需要表名/索引名)
*@返回成功查询的查询结果列表
*@抛出中断异常
*/
公共列表查询(字符串…hashKeyValues)
抛出中断异常{
//相应地初始化
int超时=2*1000;
ExecutorService ExecutorService=Executors.newFixedThreadPool(10);
最终列表结果=
新的ArrayList(hashKeyValues.length);
最终倒计时闩锁闩锁=
新的倒计时锁存器(hashKeyValues.length);
//将哈希键值循环到最终结果列表中的“或”
for(最终字符串hashKey:hashKeyValues){
executorService.submit(新的Runnable(){
@凌驾
公开募捐{
试一试{
//填写参数
QueryResult result=dynamodb.query(新的QueryRequest()
.withTableName(“MultiQueryExample”)
.addKeyConditionsEntry(“城市”,新条件()
.与操作员(“EQ”)相比
.WithAttributeValue列表(新的AttributeValue(哈希键));
//处理并发的多种方式之一
已同步(结果){
结果。添加(结果);
}
}捕获(可丢弃的t){
//记录并处理错误
t、 printStackTrace();
}最后{
倒计时();
}
}
});
}
//等待所有查询完成或超时
等待(超时,时间单位为毫秒);
//返回一份副本以防止同时修改
//面临超时的名单
已同步(结果){
返回新的ArrayList(结果);
}
}

您可以使用batchGetItem API..我不相信我可以,因为文档的第一行说明“batchGetItem操作从一个或多个表返回一个或多个项的属性。您可以通过主键标识请求的项。”但是我希望有效地基于keyConditions(哈希=“apple”)进行查询,并且(TIMESTAMP我不认为有批处理查询api这是在dynamoDB中使用partiQL的批处理解决方案的一个很好的解决方案,为什么不能在批处理中完成,而不是逐个完成呢。
Map<String, Condition> keyConditions = newHashMap();

keyConditions.put("HASH", new Condition().
    withComparisonOperator(EQ).
    withAttributeValueList(new AttributeValue().withS("apple")))
);

keyConditions.put("TIMESTAMP", new Condition().
    withComparisonOperator(LE).
    withAttributeValueList(new AttributeValue().withN(some_timestamp)))
);

QueryRequest one = new QueryRequest().
    withTableName("TABLE").
    withKeyConditions(keyConditions).
    withLimit(1).
    withScanIndexForward(SCAN_INDEX_FORWARD);

keyConditions = newHashMap();

keyConditions.put("HASH", new Condition().
    withComparisonOperator(EQ).
    withAttributeValueList(new AttributeValue().withS("pear")))
);

keyConditions.put("TIMESTAMP", new Condition().
    withComparisonOperator(LE).
    withAttributeValueList(new AttributeValue().withN(some_other_timestamp)))
);

QueryRequest two = new QueryRequest().
    withTableName("TABLE").
    withKeyConditions(keyConditions).
    withLimit(1).
    withScanIndexForward(SCAN_INDEX_FORWARD)

ArrayList<String> queryRequests = new ArrayList<String>() {{
    add(one);
    add(two);
}};

List<QueryResult> queryResults = dynamoDBClient.query(queryRequests);
/**
* Simulate a "Batch Query" operation in DynamoDB by querying an index for 
* multiple hash keys
* 
* Resulting list may be incomplete if any queries time out.  Returns a list of 
* QueryResult so that LastEvaluatedKeys can be followed.  A better implementation 
* would answer the case where some queries fail, deal with pagination (and 
* Limit), have configurable timeouts.  One improvement on this end would be 
* to make a simple immutable bean that contains a query result or exception, 
* as well as the associated request.  Maybe it could even be called back with 
* a previous list for pagination. 
* 
* @param hashKeyValues (you'll also need table name / index name) 
* @return a list of query results for the queries that succeeded
* @throws InterruptedException
*/
public List<QueryResult> queryAll(String... hashKeyValues) 
  throws InterruptedException {
  // initialize accordingly
  int timeout = 2 * 1000;
  ExecutorService executorService = Executors.newFixedThreadPool(10);

  final List<QueryResult> results = 
    new ArrayList<QueryResult>(hashKeyValues.length);
  final CountDownLatch latch = 
    new CountDownLatch(hashKeyValues.length);

  // Loop through the hash key values to "OR" in the final list of results
  for (final String hashKey : hashKeyValues) {

    executorService.submit(new Runnable() {

      @Override
      public void run() {
        try {
          // fill in parameters
          QueryResult result = dynamodb.query(new QueryRequest()
            .withTableName("MultiQueryExample")
            .addKeyConditionsEntry("City", new Condition()
              .withComparisonOperator("EQ")
            .withAttributeValueList(new AttributeValue(hashKey))));
          // one of many flavors of dealing with concurrency
          synchronized (results) { 
            results.add(result);
          }
        } catch (Throwable t) {
          // Log and handle errors
          t.printStackTrace();
        } finally {
          latch.countDown();
        }
      }
    });
  }

  // Wait for all queries to finish or time out
  latch.await(timeout, TimeUnit.MILLISECONDS);
 
  // return a copy to prevent concurrent modification of 
  // the list in the face of timeouts
  synchronized (results) {
    return new ArrayList<QueryResult>(results);
  }
}