使用IN过滤DynamoDB查询

时间:2016-09-19 15:12:42

标签: amazon-dynamodb

我尝试使用IN过滤器查询DynamoDB表。当我将单个值传递给IN时,我的查询有效,但当我传入多个时,我没有匹配。

这是params对象的初始设置。

  var params = {
    TableName: "Interactions",
    IndexName: "environment-time-index",
    KeyConditionExpression: "#environment = :environment and #time between :start and :end",
    FilterExpression: "#product = :product",
    ExpressionAttributeNames: {
      "#product": "product",
      "#environment": "environment",
      "#time": "time"
    },
    ExpressionAttributeValues: {
      ":product": product,      
      ":environment": environment,
      ":start": start,
      ":end": end
    }
  };

接下来,如果用户提供了一个公司查询参数,我会像这样修改params对象。这是我使用IN运算符的地方。

  if (req.query.firm) {
    var firms = req.query.firm;
    console.log('debug', firms);
    params.FilterExpression += " AND #firmCode IN (:firms)";
    params.ExpressionAttributeNames["#firmCode"] = "firmCode";
    params.ExpressionAttributeValues[":firms"] = firms;
  }

最后,我像这样运行查询。

  docClient.query(params, function(err, data) {
    if (err) {
      log.error(`Unable to scan. Error: ${JSON.stringify(err, null, 2)}`);
      res.status(500).json({ error: "Oh, snap!" });
    } else {
      data.Parameters = params.ExpressionAttributeValues;
      log.info(`Scan succeeded. Received ${data.Count} items.`)
      res.send(data);
    }
  });

当firm参数包含单个值时,我会得到结果。

Level="INFO", Date="2016-09-19 14:26:03,373", Message="batchinsight received GET for /api/history/interactions2", Product="Exhaust", Service="batchinsight", AppDomain="Exhaust_batchinsight"
debug TW7ZN
Level="INFO", Date="2016-09-19 14:26:03,623", Message="Scan succeeded. Received 19 items.", Product="Exhaust", Service="batchinsight", AppDomain="Exhaust_batchinsight"

但是当它包含多个值时,我得不到任何结果。

Level="INFO", Date="2016-09-19 14:35:16,896", Message="batchinsight received GET for /api/history/interactions2", Product="Exhaust", Service="batchinsight", AppDomain="Exhaust_batchinsight"
debug TW7ZN,TEXK4
Level="INFO", Date="2016-09-19 14:35:16,991", Message="Scan succeeded. Received 0 items.", Product="Exhaust", Service="batchinsight", AppDomain="Exhaust_batchinsight"

DynamoDB文档建议IN运算符可以接受以逗号分隔的值列表,但我无法使其工作。请帮忙! http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.SpecifyingConditions.html#ConditionExpressionReference

2 个答案:

答案 0 :(得分:1)

实际上,您指的是与FilterExpression不同的ConditionExpression参考文档。

条件表达式表示在您阅读时设置的限制(请不要将此与查询/扫描混淆)并在表格中写入项目。

你实际上正在查询表格。 FilterExpression 用于查询和扫描数据。

  

IN:检查两组中的匹配元素。 AttributeValueList   可以包含一个或多个String类型的AttributeValue元素,   数字或二进制(不是设置类型)。比较这些属性   针对项目的现有set type属性。如果有任何要素   输入集存在于item属性表达式中   评估为真。

请注意,IN用于检查SET数据类型中是否存在单个值。

您可以引用类似的帖子here,其中OR条件用于比较SET数据类型中的多个值。

同样,如果firmCode是STRING或SET数据类型,则应使用 OR条件

答案 1 :(得分:1)

很容易假设IN运算符采用字符串列表,但是请记住,这是DynamoDB,因此它需要一个变量列表。即(:string1, :string2)

我写了一个要点here,下面是该要点的简化版本。

const listToObjectMappings = (list) => {
    let x = {}
    list.map(item => x[':' + item] = item)
    return x
}

let statuses = ['available', 'in-transit', 'delivered']
let mappings = listToObjectMappings(statuses)
let joined = Object.keys(mappings).join();

query = {
    FilterExpression: '#stat IN (' + joined + ')',
    ExpressionAttributeNames: {
        '#stat' : 'status'
    },
    ExpressionAttributeValues: mappings
}

编辑:要点实际上更安全。此版本不适用于包含重复值的列表。但是,如果每个项目都是唯一的,那就很好。