it-swarm.com.ru

AWS DynamoDB Scan и FilterExpression с использованием массива хеш-значений

Мне трудно найти полезный пример для сканирования с FilterExpression таблицы DynamoDB. Я использую javascript SDK в браузере. 

Я хотел бы отсканировать свою таблицу и вернуть только те записи, которые имеют значения «UID» поля HASH в массиве, который я передаю сканированию

Допустим, у меня есть массив уникальных идентификаторов, которые являются полем хеш-функции моей таблицы Я хотел бы запросить эти записи из моей таблицы DynamoDB. 

Что-то вроде ниже 

var idsToSearch=['123','456','789'] //array of the HASH values I would like to retrieve
var tableToSearch = new AWS.DynamoDB();
var scanParams = {
  "TableName":"myAwsTable",  
  "AttributesToGet":['ID','COMMENTS','DATE'],  
  "FilterExpression":"'ID' in "+idsToSearch+"" 

}
tableToSearch.scan(scanParams), function(err,data){
    if (err) console.log(err, err.stack); //error handler
    else console.log(data); //success response
})
14
jotamon

Вы должны использовать оператор IN. Также проще использовать Заполнители для имен атрибутов и значений атрибутов. Я бы, однако, не рекомендовал использовать Scan в этом случае. Похоже, у вас уже есть значения атрибута ключа хеша, которые вы хотите найти, поэтому было бы более разумно использовать BatchGetItem .

В любом случае, вот как бы вы сделали это на Java:

ScanSpec scanSpec = new ScanSpec()
    .withFilterExpression("#idname in (:val1, :val2, :val3)")
    .withNameMap(ImmutableMap.of("#idname", "ID"))
    .withValueMap(ImmutableMap.of(":val1", "123", ":val2", "456", ":val23", "789"));
ItemCollection<ScanOutcome> = table.scan(scanSpec);

Я хотел бы представить, используя Javascript SDK, это будет что-то вроде этого:

var scanParams = {
  "TableName":"myAwsTable",
  "AttributesToGet": ['ID','COMMENTS','DATE'],
  "FilterExpression": '#idname in (:val1, :val2, :val3)',
  "ExpressionAttributeNames": {
    '#idname': 'ID'
  },
  "ExpressionAttributeValues": {
    ':val1': '123',
    ':val2': '456',
    ':val3': '789'
  }
}
12
mkobit

У меня была эта проблема, и я понял это с помощью параметра contains

// Object stored in the DB looks like this: 
// [
//     'name' => 'myName',
//     'age' => '24',
//     'gender' => 'Male',
//     'visited' => [
//          'countries': ['Canada', 'USA', 'Japan', 'Australia'],
//          'last_trip': '2015/12/13',
//          'reviews_written': 20
//     ]
// 
// ];

$countries = ['Canada', 'USA', 'Japan', 'Australia'];

$paramToMatch = '24';

$client->query([
        'TableName'     => 'MyDyanmoDB',
        'KeyConditions' => [
            'age' => [
                'AttributeValueList' => [
                    $marshaler->marshalValue($paramToMatch)
                ],
                'ComparisonOperator' => 'EQ'
            ]
        ],
        'ExpressionAttributeNames' => [
            '#visited'   => 'visited',
            '#countries' => 'countries'
        ],
        'ExpressionAttributeValues' => [
            ':countries' => $marshaler->marshalValue($countries)
        ],
        'FilterExpression' => 'contains(:countries, #visited.#countries)',
]);
7
tsuz

Вот как я смог использовать «scan» для получения элементов с определенным идентификатором («ContentID») в следующем примере:

var params = {
    TableName: environment.ddbContentTableName,
    ProjectionExpression: "Title, ContentId, Link",
    FilterExpression: "ContentId in (:contentId1, :contentId2, :contentId3, :contentId4),
    ExpressionAttributeValues: {":contentId1":102,":contentId2":104,":contentId3":103,":contentId4":101}
};

var docClient = new AWS.DynamoDB.DocumentClient();
docClient.scan(params, onQuery); 

Затем я могу программно построить FilterExpression и ExpressionAttributeValues ​​на основе известных значений, например,.

    // Create the FilterExpression and ExpressionAttributeValues
    var filterExpression =  "ContentId in ("; 

    var expressionAttributeValues = {};

    for (var i = 0; i < currentFavorites.length; i++) { 
        var contentIdName = ":contentId"+(i+1);

        if (i==0) {
            filterExpression = filterExpression + contentIdName;
        } else {
            filterExpression = filterExpression + ", " + contentIdName;
        }

        expressionAttributeValues[contentIdName] = currentFavorites[i];
    }

    filterExpression = filterExpression + ")";

    var params = {
        TableName: environment.ddbContentTableName,
        ProjectionExpression: "Title, ContentId, Link",
        FilterExpression: filterExpression,
        ExpressionAttributeValues: expressionAttributeValues
    };

    var docClient = new AWS.DynamoDB.DocumentClient();
    docClient.scan(params, onQuery); 
2
xke

Я также искал динамическое решение, чем необходимость вручную вводить каждое из имен параметров в условное выражение. Ниже приведено решение: 

List<String> valList= new ArrayList<String>(); // Populate the Values in a List    
StringJoiner valMap =  new StringJoiner(","); // This will be the dynamic Value Map

int i=1;

        table = dynamoDB.getTable(myTable);
        StringBuilder filterExpression = new StringBuilder();
        Map<String, Object> eav = new HashMap<String, Object>();

        if(!valList.isEmpty())
        {
            for(String attrVal: valList)
             {
                eav.put(":val"+i, attrVal);
                valMap.add(":val"+i);
                i++;
            }   
            filterExpression.append("attrColName in ("+valMap.toString()+")"); //here attrColName is the DB attribute
        }

        ItemCollection<ScanOutcome> items;
            items = table.scan(
                filterExpression.toString(), //FilterExpression
                null, //ProjectionExpression - choose all columns
                null, //ExpressionAttributeNames - not used in this example
                eav);//ExpressionAttributeValues 
0
javatogo