如何在DynamoDB中根据数组(或嵌套对象)中的元素进行过滤

4

我的数据如下:

[
  {
    orgId: "ABC",
    categories: [
      "music",
      "dance"
    ]
  },
  {
    orgId: "XYZ",
    categories: [
      "math",
      "science",
      "art"
    ]
  },
  ...
]

我在orgId上有主键,并希望使用DynamoDB的query过滤和仅返回类别为"science"的项目,例如。
(类别不需要成为任何索引的一部分:只要我可以在Dynamo内部进行查询,我愿意接受额外的工作负担。)
我很难让它正常工作。如果可以的话,我可以轻松地将categories更改为嵌套对象吗?
但是在DynamoDB中,比较运算符非常有限,似乎无法按数组元素或嵌套对象进行过滤?
如果不行,这里有更好的方法吗?将每个类别转换为自己的第一级属性,例如:
[
  {
    orgId: "XYZ",
    category_math: true,
    category_science: true
  }
]

当然不是吧?
2个回答

7
 var params = {
  ExpressionAttributeValues: {
   ":orgIdValue": {
     S: "XYZ"
    },
   ":categoriesValue": {
     S: "science"
    }
  }, 
  KeyConditionExpression: "orgId = :orgIdValue", 
  FilterExpression : "categories CONTAINS :categoriesValue", 
  TableName: "MYTABLE"
 };
 dynamodb.query(params, function(err, data) {
   if (err) console.log(err, err.stack); // an error occurred
   else     console.log(data);           // successful response
 });

包含:检查子序列或集合中的值。 AttributeValueList 只能包含一个类型为 String、Number 或 Binary(而非 set 类型)的 AttributeValue 元素。如果比较的目标属性是 String 类型,则运算符检查子字符串匹配。如果比较的目标属性是 Binary 类型,则运算符查找与输入匹配的目标子序列。如果比较的目标属性是 set("SS"、"NS" 或 "BS"),则运算符在集合的任何成员中找到精确匹配时,运算符将计算结果为 true。对于列表,CONTAINS 支持以下操作:"a CONTAINS b" 的求值中,"a" 可以是列表;但是,"b" 不能是 set、map 或列表。 类别是顶级属性,实际上没有嵌套属性。顶级标量属性可以被索引。尽管类别是顶级属性,但它不是标量属性(它是一个集合),因此您无法对其进行索引。
您可以使用 FilterExpression 来缩小查询范围,并且可以在列表上使用 CONTAINS 比较器。

谢谢。那 应该 可以工作,但出于某种原因它没有。它返回 Invalid FilterExpression: Syntax error; token: "CONTAINS"。然而,它引导我找到了一个可行的解决方案(使用 DocumentClient SDK):{ ... QueryFilter: { categories: { ComparisonOperator: "CONTAINS", AttributeValueList: [myCategoryVariable], } ... } - pjb

4
上面发布的答案应该有效,根据文档。但是在使用Node.JS AWS DynamoDB SDK的DocumentClient时,它不起作用。特别是,我尝试了:
  {
    TableName: "site",
    IndexName: "orgId-lastCaptured-index",
    KeyConditionExpression: "orgId = :orgId",
    FilterExpression: "categories CONTAINS :categoriesValue",
    ExpressionAttributeValues: {
      ":orgId": orgId,
      ":categoriesValue": myVariable,
    }
  }

这导致了以下错误:{ ValidationException: Invalid FilterExpression: Syntax error; token: "CONTAINS", near: "categories CONTAINS :categoriesValue"

我将查询调整为以下备选查询格式:
  {
    TableName: "site",
    IndexName: "orgId-lastCaptured-index",
    KeyConditions: {
      orgId: {
        ComparisonOperator: "EQ",
        AttributeValueList: [orgId],
      },
    },
    QueryFilter: {
      categories: {
        ComparisonOperator: "CONTAINS",
        AttributeValueList: [myVariable],
      }
    }
  }

这个操作如预期一样有效,过滤返回的结果,使得categories变量具有与myVariable匹配的元素。
更新:现在您可以使用以下语法执行CONTAINS操作,而无需使用已弃用的QueryFilterFilterExpression: "contains(categories, :categoriesValue)"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接