J'ai de la difficulté à trouver un exemple utile d'analyse avec FilterExpression sur une table DynamoDB. J'utilise le SDK javascript dans le navigateur.
Je souhaite analyser ma table et renvoyer uniquement les enregistrements ayant des valeurs "UID" de champ HASH dans un tableau que je transmets à l'analyse.
Disons que j'ai un tableau d'identifiants uniques qui constituent le champ de hachage de ma table J'aimerais interroger ces enregistrements à partir de ma table DynamoDB.
Quelque chose comme ci-dessous
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
})
Vous devriez utiliser l'opérateur IN
. Il est également plus facile d’utiliser Placeholders pour les noms d’attributs et les valeurs d’attributs. Je vous conseillerais toutefois de ne pas utiliser Scan
dans ce cas. Il semble que vous ayez déjà les valeurs d'attribut de clé de hachage que vous souhaitez rechercher. Il serait donc plus logique d'utiliser BatchGetItem
.
Quoi qu'il en soit, voici comment procéder en 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);
J'imagine que, avec le SDK Javascript, cela ressemble à ceci:
var scanParams = {
"TableName":"myAwsTable",
"AttributesToGet": ['ID','COMMENTS','DATE'],
"FilterExpression": '#idname in (:val1, :val2, :val3)',
"ExpressionAttributeNames": {
'#idname': 'ID'
},
"ExpressionAttributeValues": {
':val1': '123',
':val2': '456',
':val3': '789'
}
}
J'ai eu ce problème et l'a trouvé en utilisant contient paramètre
// 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)',
]);
Voici comment j'ai pu utiliser "scan" pour obtenir les éléments avec un identifiant particulier ("ContentID") dans l'exemple ci-dessous:
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);
Je peux ensuite construire par programmation les valeurs FilterExpression et ExpressionAttributeValues en fonction de valeurs connues, par exemple.
// 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);
Je recherchais également une solution dynamique, plutôt que de devoir mettre manuellement chacun des noms de paramètres dans l'expression conditionnelle. Voici une solution:
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