Node.JS - Trying to delete certain items from a DynamoDB table - node.js

I am trying to delete all records which have the attribute "code" from a DynamoDB table. Here my params:
var params = {
TableName: table,
Key:{
"email": "email",
},
ConditionExpression:"attribute_exists(code)",
};
This is the error:
{
"message": "The conditional request failed",
"code": "ConditionalCheckFailedException",
"time": "2021-11-12T09:01:04.205Z",
"requestId": "e1d74c46-86a0-4f14-8c62-186102f2aff3",
"statusCode": 400,
"retryable": false,
"retryDelay": 36.80819226584606
}
An example record looks like this:
email - first_name - last_name - hash - code - confirmed
e#icloud.com - Bob - Mann - $2b$10$5/x6BkCks6ndXSr/GRhLgOPk.ettTv3lYpglbZbGnM7FXPX5VRFCe - undefined - undefined

According to the documentation:
ConditionalCheckFailedException
Message: The conditional request failed.
You specified a condition that was evaluated to be false. For example, you might have tried to perform a conditional update on an item, but the actual value of the attribute did not match the expected value in the condition.
OK to retry? No
So the problem is with the ConditionExpression, the code attribute does not exist in some records or it exists with undefined value. try to change attribute_exists with attribute_type:
var params = {
TableName: table,
Key:{
"email": "email",
},
ConditionExpression:"attribute_type(code, S)",
};
The second parameter:
S — String
SS — String Set
N — Number
NS — Number Set
B — Binary
BS — Binary Set
BOOL — Boolean
NULL — Null
L — List
M — Map
read more on comparison and function on amazondynamodb.

Related

Comparing timestamp results from Postgres in Jest

I'm writing some tests in Jest for an API that's returning results from Postgres via the pg library. I post some data (via a faker'ed set of values, template1), and then test that what I get back is the same, allowing for an id value, and modified fields. The template1 data includes an approved property (SQL defn: approved timestamp with time zone), which is generated like so:
{
approved: faker.date.past(),
description: faker.lorem.paragraph(),
groups: faker.lorem.paragraph(),
}
This test is something like this:
expect(response.body.rows).toStrictEqual([
{
...template1,
id: 1,
modified: null,
},
])
The issue is that the test is failing because the returned value of approved appears to be a string:
expect(received).toStrictEqual(expected) // deep equality
- Expected
+ Received
## -1,8 +1,8 ##
Array [
Object {
- "approved": 2019-12-19T03:48:20.613Z,
+ "approved": "2019-12-19T03:48:20.613Z",
"approved_by": "Percy_Hills#yahoo.com",
I've tried casting the template1.approved value just prior to the comparison to both a date, and to a string. Both approaches fail. What am I doing wrong, and how do I fix the issue?
I didn't try hard enough - the answer was to convert the timestamp to JSON:
expect(response.body.rows).toStrictEqual([
{
...template1,
id: 1,
modified: null,
approved: new Date(template1.approved).toJSON(), // here
},
])

DynamoDB FilterExpressions with BETWEEN

I am performing a scan operation on my DynamoDB table then filtering the result to have items between two dates in NODE.js
The DynamoDB table formats data like this:
{
TableName: tableName,
Item: {
"visitorID": visitorIDq, // Primary Key
"dateID": dateTime, // What I am filtering the scan for
"visitorName": "END OF Q",
"employeeName": "END OF Q",
"comments": "END OF Q"
}
Current code:
var date1 = String(threeMonths); // milliseconds since epoch - 3 months in milliseconds
var date2 = String(dateTime); // milliseconds since epoch aka now
var params2 = {
TableName: tableName,
FilterExpression: "dateID BETWEEN :date1 and :date2",
ExpressionAttributeValues: {
":date1": { "S": date1},
":date2": { "S": date2}
}
};
I am getting this error:
ERROR Unable to scan the table. Error JSON: { "message": "Invalid
FilterExpression: Incorrect operand type for operator or function;
operator or function: BETWEEN, operand type: M", "code":
"ValidationException", "time": "2019-07-06T02:00:44.569Z",
"requestId": "REQUESTID1294743204701HHH443", "statusCode": 400,
"retryable": false, "retryDelay": 26.7865000058784 }
After some internet searching I am kind of stuck, not really find anybody else with this issue in node. Any ideas?
For some reason Stack Overflow is telling me this is mostly code. I thought I did a pretty good job of explaining it and giving details. This is placeholder text because I am tryna post. It is still happening. Details. Details. Details.
The correct resolution:
var dateID = String("\""+ threeMonths + "\""); // var for time in milliseconds, stringifying
var params2 = {
ExpressionAttributeValues: {
':msID' : dateID
},
FilterExpression: "dateID >= :msID", // dateID column in DDB is greater than epoch - 3 months
TableName: "Visitor"
};
JSON.stringify(params2); //params are stringified here for the scan
Specifically:
ExpressionAttributeValues: {
':msID' : "15666767546459" // or whatever value you are comparing, the above resolution has dateID there because its a var getting current time
}

How to remove last element in set in dynamo?

I have created a set using dynamoDB document client . I am able to remove items in this set however when i remove to the last element in the set nothing returns until i make a new post. Then all the other data is displayed.
const params = {
TableName: 'beta-user-' + process.env.NODE_ENV,
Key: {
username: request.username
},
UpdateExpression: "DELETE #features :feature",
ExpressionAttributeNames: { "#features" : "features" },
ExpressionAttributeValues: { ":feature": dynamodb.createSet([request.feature]) },
ReturnValues: "NONE"
};
and im calling it like
const dynamoPromise = dynamodb.update(params).promise();
return await dynamoPromise.then(result => { // stuff })
The UpdateExpression i do not think is wrong
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.DELETE
I belive the problem is with ExpressionAttributeValues if i remove
dynamodb.createSet I get many validation errors.
When i make a get request to app i get
{
"message": [
{
"username": "x",
"feature": [
"blah",
"test"
]
},
{
"username": "z",
"feature": [
"blah"
]
},
}
I make a delete request and remove the feature test from username x. This works and returns the same response minus the test feature. I make another delete request to remove blah. Blah is removed however when I make a get request I recieve:
{
"message": {}
}
The other data is returned when i make a new post to that specific user.
EDIT:
I think the issue might be due to dynamo not liking an empty set
The issue was with my return statement in my get request. I assumed that once features were deleted the record would be deleted. I was trying to return features on an object that had no features, therefore, it was erroring out and not returning anything.

Hyperledger composer, queries breaking with more than 2 WHERE conditions

Here's my query
query Q_BUY_SELL{
description: "Select filtered Orders "
statement:
SELECT namespace.Order
WHERE ((((orderType != _$filterType AND orderStatus == _$filterStatus) AND bidTokenPrice == _$bidTokenPrice) AND orderer != _$orderer) AND property == _$property )
}
And here's how i'm using it
return query('Q_BUY_SELL', {
filterStatus: 'PENDING',
filterType: 'SELL',
bidTokenPrice: 10,
orderer:'resource:com.contrachain.User#o1',
property:'resource:com.contrachain.Property#p2'
})
.then(function (assets) {
console.log(assets);
// Some alterations to assets
Here's the only Asset in my db which i wasn't expecting in result because of the 'orderer' field. (See orderer != _$orderer in query)
{
"$class": "com.contrachain.Order",
"orderId": "Thu Feb 22 2018 15:57:05 GMT+0530 (IST)-30",
"orderType": "BUY",
"orderStatus": "PENDING",
"bidTokenPrice": 10,
"tokenQuantity": 30,
"orderTime": "2018-02-22T10:27:05.089Z",
"orderer": "resource:com.contrachain.User#o1",
"property": "resource:com.contrachain.Property#p2"
}
But it's still there in the response in console.
TLDR; I have 5 conditions(1,2,3,4,5) in the query Q_BUY_SELL out of which (1,5) are working fine but the 2nd, 3rd and 4th conditions are not being applied to the results.
I feel silly posting this question as the problem seems trivial, but i've been stuck with this for a while now and need some external perspective to identify what i'm missing here.
**UPDATE: Relevant part of the Models **
asset Property identified by propertyId {
o String propertyId
--> User owner
}
asset Order identified by orderId {
o String orderId
o OrderType orderType
o OrderStatus orderStatus default = 'PENDING'
o Double bidTokenPrice
o Double tokenQuantity
o DateTime orderTime
--> User orderer
--> Property property
}
abstract participant Account identified by emailId {
o String emailId
o String name default = ''
o DateTime joiningDate
o Boolean isActive default=false
}
participant User extends Account {
o Double balanceINR default=0.0
}
transaction PlaceOrder {
o OrderType orderType
o Double bidTokenPrice
o Double tokenQuantity
o DateTime orderTime
--> User orderer
--> Property property
}
enum OrderType {
o BUY
o SELL
}
enum OrderStatus {
o PENDING
o SUCCESSFUL
o VOID
}
its difficult to replicate without the model. But I suggest to 'pare' it back to 4 criteria in your query to begin with (so - remove the property resource comparison for example) and see if it does/doesn't return the orderer (as you wrote). In any case - I would ALSO create a second record so the query does return 'something' that IS EXPECTED to be a match (and hopefully omits the record that shouldn't match), for testing - just so you can see that the query returns an orderer matching your criteria etc etc - bur first try see if the query works with 4 criteria including orderer check. What I'm suggesting is to see if there's a breakage in the aggregation of criteria (or not).
an example of building queries in a transaction and parsing is shown here FYI -> https://github.com/hyperledger/composer/blob/master/packages/composer-tests-functional/systest/data/transactions.queries.js
just to say I don't see the problems you're seeing for multiple criteria - I've tried 5 and six, mixing up - all worked fine?. Perhaps you can give feedback.
I went and tested some queries as follows with parameterised query with criteria (essentially the same as you did, for a different business network) - in online playground (So I create the queries.qry file then call the query in my TP function ( FYI that and the sample function code are at the bottom):
Numbers(below) represent left-side 'fields' in query definition (these fields are shown in the query below (ordinal, left to right)) - my 'data' is at the bottom - essentially I always (except for one test) 'miss out' on a record with tradingSymbol == "1"
query myQryTest {
description: "Select all commodities"
statement:
SELECT org.acme.trading.Commodity
WHERE (tradingSymbol != _$tradingSymbol AND (description == _$description OR description == _$description) AND mainExchange == _$mainExchange AND quantity == _$quantity AND owner == _$owner )
}
}
RESULTS:
(1 AND 2 AND 3 AND 4 AND 5) - ie all with '==' comparisons.(so 1st criteria would changed to be tradingSymbol == "1" above -just for this one test only). All worked fine. 1 record.
(!= 1 AND 2 AND 3 AND 4 AND = 5) - so one negation in criteria. Worked fine. Got the results I wanted (2 records - see my sample data below)
(!=1 AND (2 = "2" OR 2 == "3") AND 3 AND 4 AND 5) - 6 criteria, as shown above - one in parentheses (where field match is an OR). Worked fine. Got the right results. I changed the description in record 3 to be "4" and I get one record,
{
"$class": "org.acme.trading.Commodity",
"tradingSymbol": "1",
"description": "2",
"mainExchange": "3",
"quantity": 4,
"owner": "resource:org.acme.trading.Trader#1"
}
{
"$class": "org.acme.trading.Commodity",
"tradingSymbol": "2",
"description": "2",
"mainExchange": "3",
"quantity": 4,
"owner": "resource:org.acme.trading.Trader#1"
}
{
"$class": "org.acme.trading.Commodity",
"tradingSymbol": "3",
"description": "2",
"mainExchange": "3",
"quantity": 4,
"owner": "resource:org.acme.trading.Trader#1"
}
you can try this out for yourself - you can try this out with the trade-network from online playground https://composer-playground.mybluemix.net/ (deploy trade-network sample) and create a Trader trader 1 record in the Participant.
/**
* Try access elements of an array of B assets
* #param {org.acme.trading.Qry} qry - function to access A elements (and B assets)
* #transaction
*/
function myQryfunc(qry) {
return query('myQryTest', {
"tradingSymbol": "1",
"description": "2",
"mainExchange": "3",
"quantity": 4,
"owner": "resource:org.acme.trading.Trader#1"
})
.then(function (results) {
var promises = [];
for (var n = 0; n < results.length; n++) {
var asset = results[n];
console.log('Query result is ' + (n+1) + ', object is ' + asset);
console.log('Asset identifier is ' + asset.getIdentifier());
}
});
}
Model definition for my Qry transaction (to call it in playground) is
transaction Qry {
--> Commodity commodity
}

Invalid attribute value type: ValidationException on DynamoDB Put

I am trying to do a put item on a Dynamo Table using the nodejs sdk. I tried using the same document and a few other variations but nothing seems to work. Everytime I receive the same error:
"message":"Invalid attribute value type"
"code":"ValidationException"
"time":"2016-10-11T06:32:26.361Z"
"statusCode":400
"retryable":false
The following is the relevant code snippet:
var params = {
TableName: "MY_Table_Name",
Item: {
"stringAtt": "stringValue",
"boolAtt": true,
"numAtt": 123,
},
};
docClient.put(params, function(err, data) {
if (err) ppJson(err); // an error occurred
else ppJson(data); // successful response
});
My table's indexes are as follows:
Primary: Partition Key: stringAtt, Sort Key: boolAtt
GSI: Partition Key: boolAtt, Sort Key: numAtt
I am not sure if it's my query or the index structure that is wrong.
The BOOL data type can't be a key attribute (i.e. Partition or Sort key). The Partition or Sort key data type can be of three types (listed below). If you have created the table with Sort key of type 'B', it means that sort key is of type Binary (i.e. not Bool).
EDIT: You can't use a BOOL attribute as the partition or sort key in a GSI as well.
AttributeType: 'S | N | B'
S - the attribute is of type String
N - the attribute is of type Number
B - the attribute is of type Binary
When the table is created with key of type BOOL, the API would throw the below exception.
Unable to create table. Error JSON: {
"message": "Member must satisfy enum value set: [B, N, S]",
"code": "ValidationException",

Resources