【问题标题】:How to query DynamoDB filtering by value in a list如何按列表中的值查询 DynamoDB 过滤
【发布时间】:2021-01-13 14:20:38
【问题描述】:

数据库中有三个项目:

[
  {
    "year": 2013,
    "info": {
      "genres": ["Action", "Biography"]
    }
  },
  {
    "year": 2013,
    "info": {
      "genres": ["Crime", "Drama", "Thriller"]
    }
  },
  {
    "year": 2013,
    "info": {
      "genres": ["Action", "Adventure", "Sci-Fi", "Thriller"]

    }
  }
]

year 属性作为表的主键,我可以继续使用FilterExpression 来匹配确切的list["Action", "Biography"]

var params = {
    TableName : TABLE_NAME,
    KeyConditionExpression: "#yr = :yyyy",
    FilterExpression: "info.genres = :genres",
    ExpressionAttributeNames:{
        "#yr": "year"
    },
    ExpressionAttributeValues: {
        ":yyyy": 2013,
        ":genres": ["Action", "Biography"]
    }     
};
var AWS = require("aws-sdk");
var docClient = new AWS.DynamoDB.DocumentClient();


let promise = docClient.query(params).promise();
promise.then(res => {
console.log("res:", res);
})

而不是匹配整个列表["Action", "Biography"],我宁愿进行查询以仅返回那些在存储在项目的info.genres 字段中的列表中包含字符串“传记”的表项目。我想知道这是否可能使用 DynamoDB query API?

稍后编辑。

工作解决方案(感谢 Balu)是使用 QueryFilter contains 比较运算符:

var params = {
    TableName: TABLE_NAME,
    Limit: 20,
    KeyConditionExpression: "id = :yyyy",
    FilterExpression: `contains(info.genres , :qqqq)`,
    ExpressionAttributeValues: {
      ":qqqq": { S: "Biography" },
      ":yyyy": { N: 2013 },
    },
  }

let promise = docClient.query(params).promise();
promise.then(res => {
console.log("res:", res);
})

【问题讨论】:

    标签: javascript python typescript amazon-web-services amazon-dynamodb


    【解决方案1】:

    我们可以在过滤器表达式中使用contains,而不是=

    所以,"info.genres = :genres" 可以改为contains(info.genres , :gnOne)

    AWS 仍将在应用过滤器之前查询分区键,在单个查询中提取最多 1 MB 的数据。所以,不管有没有过滤器表达式,我们都将被收取相同的 RCU 费用,但返回给客户端的数据量将是有限的,所以,仍然有用。

    const dynamodb = new AWS.DynamoDB();
    dynamodb.query(
      {
        TableName: "my-test-table",
        Limit: 20,
        KeyConditionExpression: "id = :yyyy",
        FilterExpression: `contains(info.genres , :gnOne)`,
        ExpressionAttributeValues: {
          ":gnOne": { S: "Biography" },
          ":yyyy": { S: "2020" },
        },
      },
      function (err, data) {
        if (err) console.error(err);
        else console.log("dynamodb scan succeeded:", JSON.stringify(data, null, 2));
      }
    );
    

    【讨论】:

      【解决方案2】:

      简短的回答,不。 DDB 允许存储 key:val 对,因此您要查询的元素应该是顶部元素。

      长答案,是的。但是,它正在使用扫描。老实说,就 RCU 的消耗而言,我认为查询和扫描之间没有太大区别。您可以使用Limit 参数来限制您的 RCU 在单个网络调用中的使用。

      如果到目前为止我们还不错,您可以在过滤器表达式中使用Document Paths 来实现您想要做的事情。请参阅this 堆栈溢出帖子和this github 示例。

      但是,请注意,这是一个扫描操作,而不是一个查询,而且它可能会变得非常昂贵,因为它不会使用任何索引并且会遍历表中的每个文档。

      最好将这些属性提取到顶级文档中,并使用二级索引进行相应的查询。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-14
        • 2017-03-20
        • 1970-01-01
        • 1970-01-01
        • 2020-04-30
        • 2012-03-07
        • 1970-01-01
        相关资源
        最近更新 更多