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

使用Between运算符查询DynamoDB返回全部结果的问题求助

问题描述

表结构

DynamoDB表结构如下:

key       reference          value
1234      3214#0012345       xxxx
1234      3314#0003455       xxxx
1234      3214#0004231       xxxx

其中reference字段由${accountId}#${idOfItem}拼接而成。

需求

查询指定key下,匹配指定accountId的value数据。

现有Java代码

public Promise<List<Value>> getFiltersByUser(Key key, AccountId accountId) {
        final QuerySpec query = new QuerySpec();
        Map<String, Object> valueMap = new HashMap<>();
        Map<String, String> keyMap = new HashMap<>();

        keyMap.put("#key", PARTITION_KEY_NAME);
        keyMap.put("#reference", RANGE_KEY_NAME);
        valueMap.put(":key", key);
        valueMap.put(":startReference", createFilterRef("0000000", accountId));
        valueMap.put(":endReference", createFilterRef("9999999", accountId));
//createFilterRef simply creates the reference by concatenating the two values with hashtag
        query.withKeyConditionExpression("#key = :key AND #filterRef BETWEEN :startFilterRef AND :endReference")
                .withNameMap(keyMap)
                .withValueMap(valueMap);

        return Blocking.get(() -> {
            final ItemCollection<QueryOutcome> out = table.query(query);
            return newArrayList(out)
                    .stream()
                    .map(this::createValueFromItem)//we can disregard this as it converts the results received to a different structure
                    .collect(Collectors.toList());
        });
    }

遇到的问题

查询条件中的BETWEEN运算符未生效,返回了指定key下的所有结果。


解决方案

问题根源

代码存在两处占位符名称不匹配的问题,导致BETWEEN条件未正确关联到reference字段:

  1. NameMap中定义的范围键占位符是#reference,但KeyConditionExpression里用的是#filterRef,DynamoDB无法识别未映射的占位符,直接忽略该条件片段。
  2. ValueMap中定义的起始值占位符是:startReference,但表达式里用的是:startFilterRef,导致值无法正确绑定。

修正后的代码

修改KeyConditionExpression中的占位符,使其与NameMap和ValueMap的定义完全匹配:

public Promise<List<Value>> getFiltersByUser(Key key, AccountId accountId) {
        final QuerySpec query = new QuerySpec();
        Map<String, Object> valueMap = new HashMap<>();
        Map<String, String> keyMap = new HashMap<>();

        keyMap.put("#key", PARTITION_KEY_NAME);
        keyMap.put("#reference", RANGE_KEY_NAME);
        valueMap.put(":key", key);
        valueMap.put(":startReference", createFilterRef("0000000", accountId));
        valueMap.put(":endReference", createFilterRef("9999999", accountId));

        // 修正占位符名称,与NameMap、ValueMap对应
        query.withKeyConditionExpression("#key = :key AND #reference BETWEEN :startReference AND :endReference")
                .withNameMap(keyMap)
                .withValueMap(valueMap);

        return Blocking.get(() -> {
            final ItemCollection<QueryOutcome> out = table.query(query);
            return newArrayList(out)
                    .stream()
                    .map(this::createValueFromItem)
                    .collect(Collectors.toList());
        });
    }

原理说明

DynamoDB的KeyConditionExpression要求所有名称占位符(以#开头)必须在NameMap中有对应映射,值占位符(以:开头)必须在ValueMap中有对应值。一旦名称不匹配,对应条件片段会被忽略,导致查询仅执行#key = :key这一个条件,返回该分区键下的所有数据。修正后,BETWEEN条件会正确作用在reference字段上,筛选出指定accountId范围内的数据。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 00:36:21