【问题标题】:"IN" statement in dynamodbdynamodb 中的“IN”语句
【发布时间】:2018-06-06 20:22:49
【问题描述】:

我有一个“用户”表,这是一个示例:

{
    username:"haddox",
    formattedPhoneNumber:"676767676",
    verified: 0,
}

我希望检索其 formattedPhoneNumber 包含在电话号码数组(从我的联系人中检索)中的所有用户。我创建了一个二级索引,验证为 HASH,formattedPhoneNumber 为 RANGE。这是我的尝试:

var params = {
    TableName: "Users",
    IndexName: "FormattedPhoneSecondaryIndex",
    KeyConditionExpression: "verified  = :v AND formattedPhone IN :n",
    ExpressionAttributeValues: {
        ":v":1,
        ":n": ["672053916", "642117296"]
    },
    ProjectionExpression: "username, formattedPhoneNumber"
};



dynamodb.query(params, function(err, data) {
    if (err)
        console.log(JSON.stringify(err, null, 2));
    else
        console.log(JSON.stringify(data, null, 2));
});

但我收到以下错误:Invalid KeyConditionExpression: Syntax error; token: \":n\", near: \"IN :n\"",

IN 关键字有问题吗? 也许还有另一种方法可以实现这一点?

【问题讨论】:

  • 你试过“(verified = :v) AND (formattedPhone IN (:n))”吗?
  • 嗨!我刚试过,但没用..
  • @HadrienPierreMazelier 你能粘贴你的工作示例吗

标签: amazon-web-services amazon-dynamodb aws-sdk nosql


【解决方案1】:

KeyConditionExpression 不能使用“IN”运算符(请参阅http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScan.html#FilteringResults)。在查询操作中使用 KeyConditions/KeyConditionExpression 的想法是更有效地从 DynamoDB 中读取项目页面,因为具有相同哈希键但不同范围键的项目以连续且有序的顺序存储。 IN 运算符需要提取某些页面的一小部分,这会降低 Query 操作的效率,因此在 KeyConditions 中是不允许的。您可能希望将其添加为 FilterExpression,这是一个方便的参数,可减少从 DynamoDB 返回的项目数量,但不会影响从 DynamoDB 读取数据的方式。

【讨论】:

  • 嗯好的,谢谢!这意味着它将从 db 中获取所有项目,然后对其进行正确过滤?
  • 是的 - 所以保持 KeyConditionExpression 为已验证 = 1,但为 formattedPhoneNumber IN [ ] 添加过滤器表达式。这样请求将只获取已验证 = 1 的项目,然后执行过滤器。
  • scanExpression.filterExpression = @"Id IN (:val)"; scanExpression.expressionAttributeValues = @{@":val":[idList componentsJoinedByString:@","]}; 那怎么用?我试过放置数组但没有成功,这就是加入数组的原因
  • @MinSoe 我和你有同样的问题。如何像你一样使用 In 运算符
【解决方案2】:

我们就是这样解决的。

-(AWSDynamoDBScanExpression *) prepareScanExpressionWithName:(NSString*)name andValues:(NSArray *)vals {

AWSDynamoDBScanExpression *scanExpression = [AWSDynamoDBScanExpression new];

NSMutableString* filterExpression = [NSMutableString string];

NSMutableDictionary* expression = [NSMutableDictionary dictionary];

for(int i = 0; i < vals.count; i++)
    NSString *val = vals[i];
    NSString* key = [NSString stringWithFormat:@":val%i",i];

    [filterExpression appendString:key];
    [expression setObject:val forKey:key];

    if (i < vals.count) {
        [filterExpression appendString:@","];
    }
}

scanExpression.filterExpression = [NSString stringWithFormat:@"#P IN (%@)", filterExpression];
scanExpression.expressionAttributeNames = @{@"#P": name};
scanExpression.expressionAttributeValues = expression;
return scanExpression;
}

【讨论】:

  • 这只是在FilterExpression中使用IN,它仍然会读取大量数据然后在返回之前过滤结果,实际上并不能有效地仅读取满足IN条件的行。
  • 嗨@cryanbhu 你能建议一下吗?是的,我们知道它效率低下,但这是我们能够弄清楚那个时间的唯一方法。
  • 我只是重申最佳答案的观点,即在 DynamoDB 中无法有效地执行 IN 等效项。为了优化查询效率,您必须重新考虑数据,可能会将列表项拆分为列,然后在该列上设置索引。在决策阶段对 SQL 与 noSQL 有一个很好的了解会大有帮助。
猜你喜欢
  • 1970-01-01
  • 2014-09-24
  • 1970-01-01
  • 1970-01-01
  • 2014-12-31
  • 1970-01-01
  • 2021-12-23
  • 2015-02-25
  • 2020-12-31
相关资源
最近更新 更多