Java 条件DynamoDb查询

Java 条件DynamoDb查询,java,amazon-dynamodb,Java,Amazon Dynamodb,我有一个叫做用户的DynamoDb表。我试图执行一个非常简单的查询,其中用户的姓氏像“John*”Johnson、Johnston、Johnny等等,但是我找不到一个非常直接的示例 下面是我的代码片段: public class DynamoDbUsersTest extends ApplicationTest { @Autowired private DynamoDb dynamoDb; private Table usersTable = dynamoD

我有一个叫做用户的DynamoDb表。我试图执行一个非常简单的查询,其中用户的姓氏像“John*”Johnson、Johnston、Johnny等等,但是我找不到一个非常直接的示例

下面是我的代码片段:

public class DynamoDbUsersTest extends ApplicationTest {
      @Autowired
      private DynamoDb dynamoDb;

      private Table usersTable = dynamoDb.getTable("Users");

      public void getUsersByLastNameContainsTest(){
          //userTable.contains(user.getLastName());  // No such method.
          userTable.scan(new ScanFilter("lastName").contains("John");
          ...
      }
}
有人能给我指一下正确的方向吗?我试着查看查询对象,但我不确定它是否能满足我的需要

我不得不勉强使用Scan对象来完成这项工作,但是它会对每个查询进行完整的表扫描。 是否有人找到了更好/更快的搜索部分值的方法? 下面的速度会更快吗?

以下是使用contains部分匹配字符串的ScanSpec

Table table = dynamoDB.getTable("tablename");

        Map<String, Object> attributeValueMap = new HashMap<>();
        attributeValueMap.put(":lastNameValue", "John");

        ScanSpec scanSpec = new ScanSpec().withFilterExpression("contains (lastName,:lastNameValue)")
                .withValueMap(attributeValueMap);
        IteratorSupport<Item, ScanOutcome> scanOutcome = null;

        scanOutcome = table.scan(scanSpec).iterator();

while (scanOutcome.hasNext()) {
            System.out.println("Output ==============>" + scanOutcome.next().toJSON());
        }
编辑:-

如其他答案中所述,如果您知道哈希键,并且lastname未定义为哈希键,则可以使用QuerySpec。此外,您只能在FilterExpression上使用contains。换句话说,它不能用于KeyConditionExpression


QuerySpec需要KeyConditionExpression,它只支持哈希键属性上的相等运算符。然后在FilterExpression上,您可以在非键属性上使用contains。

子字符串匹配是ElasticSearch很好的方法。我建议您打开DynamoDB表的流,并在AWS ElasticSearch集群中为您的项目/文档编制索引。

您不能在查询中使用contains,只能使用scan;但是,如果您只关心以特定值开头的结果,那么可以使用begins_with query操作符:begins_with a,substr,其中a是您的键名。要使其工作,该键必须是排序键,而不是分区键。请参见和

谢谢。这与我上面提到的有什么不同?我想知道您是否可以使用QuerySpec来代替ScanskySpec,以避免使用完整的表ScanskySpec QuerySpec=new QuerySpecnew QueryFilterlastName.containsjohn;表1.queryquerySpec;更新了答案。希望澄清。谢谢。我今天会检查并确保密钥是已排序的密钥。那么,考虑到我有两个键,合同号和供应商名称,是否可以只使用一个键,比如供应商名称,而不必使用另一个键?我不这么认为-范围键是可选的,但分区键是必需的。在这种情况下,我认为您需要指定合同编号=x,并以供应商名称john开头。分区键不必是唯一的,但分区键和范围键的组合必须是唯一的。我很确定,有了这些限制,DynamoDB对于您的用例来说并不是一个好的数据库选择——它实际上只处理您知道要查找什么的情况,它不能很好地处理传统的数据库查询。使用RDS或类似软件可能会更好。我可以使用contractNumber作为分区键,vendorName作为辅助键来启动并运行它。然后我对我要找的东西进行扫描。它能够在2毫秒内处理70K条记录:
Table table = dynamoDB.getTable("tablename");

        Map<String, Object> attributeValueMap = new HashMap<>();
        attributeValueMap.put(":lastNameValue", "John");

        ScanSpec scanSpec = new ScanSpec().withFilterExpression("contains (lastName,:lastNameValue)")
                .withValueMap(attributeValueMap);
        IteratorSupport<Item, ScanOutcome> scanOutcome = null;

        scanOutcome = table.scan(scanSpec).iterator();

while (scanOutcome.hasNext()) {
            System.out.println("Output ==============>" + scanOutcome.next().toJSON());
        }