2016-04-18 11 views
0

AWSDynamoDBScanExpressionのfilterExpressionについて質問したいと思います。 問題:という1つのパラメータがarray(必須のuniqueIdsの配列)に格納されている値の1つのテーブル内のすべてのオブジェクトに対して、dbをスキャンします。一つのオブジェクトのためにAWS値の配列でフィルタリングされた複数項目のバッチリクエスト

- それは

AWSDynamoDBScanExpression *scanExpression = [[AWSDynamoDBScanExpression alloc] init]; 
scanExpression.expressionAttributeNames = @{ 
              @"#P": [NSString stringWithFormat:@"%@", property] 
              }; 
scanExpression.filterExpression [email protected]"#P = :val"; 
scanExpression.expressionAttributeValues = @{ 
              @":val" : @"some uniqueID" 
              }; 

で行うのは簡単ですので、同じロジックで、私はマルチオブジェクトに対して

AWSDynamoDBScanExpression *scanExpression = [[AWSDynamoDBScanExpression alloc] init]; 
scanExpression.expressionAttributeNames = @{ 
              @"#P": [NSString stringWithFormat:@"%@", property] 
              }; 
scanExpression.filterExpression = <WHAT SHOULD BE HERE, WHAT EXPRESSION>; 
scanExpression.expressionAttributeValues = @{ 
              @":val" : [@"some unique id 1", 
              @"some unique id 2", 
              @"some unique id 3"] 
              }; 

をデシベルをスキャンするこれをachiveするscanExpression.filterExpressionを変更するにはどのような方法です?

EDIT 1

いいえ、私はscanが最善の解決策であることはよく分かりません。実際にqueryが最良の変種だと思います。

テーブルの構造

enter image description here

#P = :val1 OR #P = :val2 make sense

EDIT2

これは、いくつかのアップデートです:

AWSDynamoDBQueryExpression *query = [[AWSDynamoDBQueryExpression alloc] init]; 
NSMutableDictionary *dictionaryAttributes = [[NSMutableDictionary alloc] init]; 
NSString *expression = @""; 
for (int i = 0; i < filteredHashValues.count; i++) { 
    NSString *variableName = [NSString stringWithFormat:@":val%i", i]; 
    [dictionaryAttributes setValue:filteredHashValues[i] forKey:variableName]; 
    expression = [expression stringByAppendingString:expression.length ? [NSString stringWithFormat:@"OR #P = %@ " , variableName] : [NSString stringWithFormat:@"#P = %@ " , variableName]]; 
} 

query.indexName = @"uniqueId-index"; 
query.expressionAttributeNames = @{ 
            @"#P": [NSString stringWithFormat:@"%@", @"uniqueId"] 
            }; 
query.filterExpression = expression; 
query.expressionAttributeValues = dictionaryAttributes; 

AWSDynamoDBObjectMapper *dynamoDBObjectMapper = [AWSDynamoDBObjectMapper defaultDynamoDBObjectMapper]; 
[[dynamoDBObjectMapper query:className expression:query] continueWithBlock:^id _Nullable(AWSTask * _Nonnull task) { 

    if (task.result) { 
     AWSDynamoDBPaginatedOutput *output = task.result; 
    } 
    return nil; 
}]; 

しかし

を引き起こします

Printing description of expression: #P = :val0 OR #P = :val1 OR #P = :val2 OR #P = :val3

Printing description of dictionaryAttributes: { ":val0" = "8A93A3EA-9FB9-4396-BBF6-D0BD3CBE6BE5"; ":val1" = "08533EBA-D3E5-406C-8CDE-03EECCCA801B"; ":val2" = "954AE402-336E-423D-BF03-7E8AED1446FE"; ":val3" = "F683BDF8-0507-4218-9927-9F14D470E593"; }

Printing description of task->_error: Error `Domain=com.amazonaws.AWSDynamoDBErrorDomain Code=0 "(null)" UserInfo={__type=com.amazon.coral.validate#ValidationException, message=ExpressionAttributeValues contains invalid value: Supplied AttributeValue is empty, must contain exactly one of the supported datatypes for key :awsddbomhashvalueplaceholder}

ExpressionAttributeValuesが空であるように見えます - 私はすべて正しく行っていますか?

答えて

1

スキャン式を使用してもよろしいですか?これは本当に多くの読み込み容量を消費し、ダイナモードのパフォーマンスを損なう可能性があります。スキャンによってテーブル全体が読み込まれ、THENだけがフィルタを適用して値を返します。

あなたの実際のダイナモブロックのテーブル構造を私たちに提供すれば、別の解決策について議論することもできます。たとえば、グローバルなセカンダリインデックス(最終的な一貫性のある読み取りがOKの場合)またはローカルのセカンダリインデックス(制限付き)を作成し、フィルタリングする値の範囲キーを作成することができます。これにより、クエリを使用できるようになります。これは、ベストプラクティスとしてはるかに優れており、アドバイスされています。

+0

を助け

の希望がかなっ同様のへ ":val1とOR #P = val2の#P =" その結果

、あなただけ使用してフィルタに条件を追加することができますと言われて

ANDとOR演算子、 edit1を参照してください – gbk

+0

uniqueId以外に十分頻繁に変更される(つまり、一意ではないが異なる値が多い)フィールドがこのテーブルにありますか?私はgroupIdやparentKeyなどを考えています。これは、プロビジョニングされた容量を最適化した状態でインデックスを作成するために必要です。インデックスは、あなたの容量を損なうことなく、特定のフィールド(あなたのケースではuniqueId)をうまくクエリすることができます – Tom

+0

編集2を参照してください参照してください – gbk

関連する問題