Confused on creating an update request for DynamoDB using API Gateway - amazon-dynamodb

I'm writing a lambda function to get the resources by posting the phone number. below is my code.
exports.handle = function (e, ctx, cb) {
var body = JSON.parse(e.body);
var params = {
TableName: 'userAddresses',
FilterExpression: '#phone = :phone',
ExpressionAttributeNames: {
"#phone": "phone"
},
ExpressionAttributeValues: {
":phone": body.phone
}
}
dynamodb.scan(params).promise().then(function (data) {
var uw = data.Items[0];
var res = {
"statusCode": 200,
"headers": {},
"body": JSON.stringify(uw)
};
ctx.succeed(res);
});
}
this is working fine. but I want to do the same with put and patch. Can some one please point me in a right direction.
for patch, it should be something like, the phone should be passed as a queryParameter and the body to be updated in just json body
Thanks

Is the phone number a hash key? If so, use dynamodb.get() or dynamodb.query() instead...
Here's a quick and dirty example, it may help you to get started with DynamoDB updates:
const AWS = require('aws-sdk);
const bluebird = require('bluebird');
AWS.config.setPromisesDependency(bluebird);
const dynamodb = new AWS.DynamoDB.DocumentClient();
let update = (id, attributes) => {
var params = {
TableName: 'MyTableName',
Key: {
myHashKeyAttr: id
},
AttributeUpdates: attributes
};
return dynamodb.update(params).promise();
};
exports.handler = (event, context, callback) => {
console.log(JSON.stringify(event, null, 2));
let body = JSON.parse(event.body);
let attributes = {
firstName: {
Action: 'PUT',
Value: body.firstName
},
lastName: {
Action: 'PUT',
Value: body.lastName
},
updatedAt: {
Action: 'PUT',
Value: new Date()
}
};
// only if the phone number is a hash key...
update(event.queryStringParameters.phone, attributes)
.then(
(result) => {
console.log(result);
callback({
statusCode: 200,
headers: {},
body: JSON.stringify({message: 'updated!'})
});
}
).catch(
(error) => {
console.error(error);
callback({
statusCode: 500,
headers: {},
body: JSON.stringify({message: 'ops!'})
});
}
);
}

Related

Recognize Text REST endpoint returns no results on success

I'm using the recognizeText REST endpoint from javascript running locally on my dev machine. I can successfully call the endpoint, get the operation-location url for the result and send a GET request to that url.
The issue is the return from the operation-location url is 200 success (meaning the operation has completed and doesn't need more time), but the body of the result is always empty.
How can I get the extracted text from the response?
My code:
var subscriptionKey: string = "my key";
var endpoint: string = "https://eastus.api.cognitive.microsoft.com/";
var uriBase: string = endpoint + "/vision/v2.0/recognizeText?mode=Printed";
const fetchData = {
headers: {
"Content-Type": "application/json",
"Ocp-Apim-Subscription-Key": subscriptionKey
},
body:
'{"url": "https://www.bing.com/th/id/OIP.nZoyhANat4WNndv0jeoXFAHaLp?w=183&h=289&c=7&o=5&dpr=1.5&pid=1.7"}',
method: "POST"
};
fetch(uriBase, fetchData).then(data => {
var operationLocation = data.headers.get("Operation-Location");
if (operationLocation) {
const resultFetchData = {
headers: {
"Content-Type": "application/json",
"Ocp-Apim-Subscription-Key": subscriptionKey
},
method: "GET"
};
setTimeout(function(operationLocation, resultFetchData) {
fetch(operationLocation, resultFetchData).then(resultData => {
alert(JSON.stringify(resultData, null, 2));
});
}, 10000);
}
});
}
There is something wrong with your fetch request code block, try this :
fetch(uriBase, fetchData).then(data => {
var operationLocation = data.headers.get("Operation-Location");
if (operationLocation) {
const resultFetchData = {
headers: {
"Content-Type": "application/json",
"Ocp-Apim-Subscription-Key": subscriptionKey
},
method: "GET"
};
setTimeout(()=> {
fetch(operationLocation, resultFetchData).then(resultData => {
return resultData.json();
}).then((data)=>{
console.log(JSON.stringify(data, null, 2));
});
},10000);}
});
Result :

DynamoDb Update an Item from Node.js

I had the following code which originally worked for creating a user.
var params = {
TableName: 'myproject-user',
Item: {
id: req.body.userName,
email: req.body.email
}
};
if(req.body.currency) {
params.Item.currency = {
type: req.body.currency.type,
bank: req.body.currency.bank,
amount: req.body.currency.amount,
}
}
docClient.put(params, function(err, data) {
if (err) {
res.send({
success: false,
message: 'Error: ' + err
});
} else {
const { Items } = data;
res.send({
success: true,
message: 'Added user',
email: req.body.email
});
}
});
I'm now switching to put to update, as I want to be able to keep any existing values on the object while updating the email or name. In addition I have added the following line in the params object to specify the key which is id.
Key: { id : req.user.sub },
The doc.update code executes and I get back status 200 as if there was no problem, but when I look at the table the information hasn't been updated.
Do I need to use an expression or something to get update to work?
Code with changes:
var params = {
TableName: 'myproject-user',
Key: {"id":req.user.sub},
Item: {
id: req.body.userName,
email: req.body.email
}
};
docClient.update(params, function(err, data) {
if (err) {
res.send({
success: false,
message: 'Error: ' + err
});
} else {
const { Items } = data;
res.send({
success: true,
message: 'Added user',
email: req.body.email
});
}
});
I was able to get this working by using UpdateExpression, ExpressionAttributeValues, and ReturnValues attributes instead of Item, as described here:
var params = {
TableName: 'krncdev-user',
Key: {"id":req.user.sub},
UpdateExpression: "set email=:e",
ExpressionAttributeValues:{
":e": req.body.email
},
ReturnValues:"UPDATED_NEW"
};

How to post multipart/formdata using fetch in react-native?

i want to post Form Data like that.
what should i prepare for sending image file data?
i have Uri, type, filename, size.
then will use fetch for it.
Content-type in header is 'multipart/formdata'
thanks for helping
You should have an upload function, which should look like this:
upload(url, data) {
let options = {
headers: {
'Content-Type': 'multipart/form-data'
},
method: 'POST'
};
options.body = new FormData();
for (let key in data) {
options.body.append(key, data[key]);
}
return fetch(requestUrl, options)
.then(response => {
return response.json()
.then(responseJson => {
//You put some checks here
return responseJson;
});
});
}
And you call it this way, sending the image blob path:
this.upload('http://exampleurl.com/someApiCall', {
file: {
uri: image.path,
type: image.mime,
name: image.name,
}
}).then(r => {
//do something with `r`
});
You need to create an instance of FormData and pass that as the body to fetch, like so:
const data = new FormData()
data.append("something", something)
fetch(url, { method: 'POST', body: form })
React Native code
fetch("url" ,{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
method:'POST',
body: JSON.stringify(this.state.imageholder)
}).catch(function(error) {
console.log('There has been a problem with your fetch operation: ' + error.message);
throw error;
});
Spring boot code
#PostMapping(value="/",consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> saveCustomerOrder(#RequestBody String[] file) throws SerialException, SQLException {
TestImg imgObj=null;
for (String img : file) {
imgObj=new TestImg();
byte[] decodedByte = Base64.getDecoder().decode(img);
Blob b = new SerialBlob(decodedByte);
imgObj.setImg(b);
testRepo.save(imgObj);
}

appending javascript json/object to daynamoDB existing list "L" through apigClient and Lambda

Lambda function to append existing list:
var doc = require('aws-sdk');
var dynamo = new doc.DynamoDB({
convertEmptyValues: true
});
exports.handler = function(event, context) {
var params = {
TableName: 'F_Items',
Key: { // The primary key of the item (a map of attribute name to AttributeValue)
"APIuserID": {
"N": event.APIuserID
},
"f_name": {
"S": event.f_name
},
},
UpdateExpression: "SET #bks.#nm = list_append(#bks.#bl, :vals)",
ExpressionAttributeNames: {
"#bks": "Books",
"#bl": "booklist",
},
ExpressionAttributeValues: {
":vals": event.bVal,
},
ReturnValues: 'UPDATED_NEW',
ReturnConsumedCapacity: 'NONE',
ReturnItemCollectionMetrics: 'NONE',
};
dynamo.updateItem(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else context.succeed(data); // successful response
});
}
passing below values from javascript frontend Through API Getaway;
var JSitem = {
"aVal": "a",
"bVal": "b",
"nVal": 12
};
var apigClient = apigClientFactory.newClient();
var body = {
"APIuserID": "1",
"f_name": "abc",
"bVal": JSitem
}
apigClient.addingbookitemsPut({}, body, {})
.then(function(result) {
console.log("passed");
}).catch(function(result) {
console.log("err");
});
issue here JSitem has to be "L" to be able to append it to list, how can I structure it so apigClient pass it as "L"
below structure doesn't help me
var JSitem = [];
JSitem["aVal"] = "a";
JSitem["bVal"] = "b";
JSitem["nVal"] = 12;
or
var JSitem = [{
aVal: 'a',
bVal: 'b',
nVal: 12
}];
I would suggest you to use document client rather than dynamodb object. There seems to be an issue on list_append when you use dynamodb object.
The below code has the necessary changes that you require in your code.
var doc = require('aws-sdk');
var dynamo = new doc.DynamoDB({
convertEmptyValues: true
});
var docClient = new doc.DynamoDB.DocumentClient();
exports.handler = function(event, context) {
var params = {
TableName: 'F_Items',
Key: {
"APIuserID": event.APIuserID,
"f_name": event.f_name,
},
UpdateExpression: "SET #bks.#nm = list_append(#bks.#bl, :vals)",
ExpressionAttributeNames: {
"#bks": "Books",
"#bl": "booklist",
},
ExpressionAttributeValues: {
":vals": event.bVal,
},
ReturnValues: 'UPDATED_NEW',
ReturnConsumedCapacity: 'NONE',
ReturnItemCollectionMetrics: 'NONE',
};
docClient.update(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else context.succeed(data); // successful response
});
}
Request:-
{
"APIuserID" : 3,
"f_name" : "name",
"bVal" : ["somevalue"]
}

JSON Data not displaying in ng-grid in angular

I've got a controller that makes an HTTP Call to the database. It returns the data, verified by the $log command but does not display it in the grid. Here's the code..
Thanks in advance...
eventsApp.controller('TerrController',
function TerrController($scope, territoryData) {
$scope.territory = [];
//$scope.gridOptions = {
// data: 'territory', columnDefs: [
// { field: 'TerritoryID', displayName: 'ID'},
// { field: 'TerritoryDescription', displayName: 'Description' },
// { field: 'RegionID', displayName: 'RegionID' }]
//};
territoryData.getTerritories().then(function (response) {
var tmpData = angular.fromJson(response);
$scope.territory = tmpData;
});
$scope.gridOptions = {
data: 'territory', columnDefs: [
{ field: 'RegionID', displayName: 'RegionID', visible: true },
{ field: 'TerritoryDescription', displayName: 'Description', visible: true },
{ field: 'TerritoryID', displayName: 'ID', visible: true }]
};
});
eventsApp.factory('territoryData', function ($http, $q, $log) {
return {
getTerritories: function () {
var deferred = $q.defer();
$http({ method: 'GET', url: '/Home/GetTerritories' }).
success(function (result, status, headers, config) {
angular.forEach(result, function (c) {
$log.log(c.TerritoryDescription);
});
deferred.resolve(result);
}).
error(function (result, status, headers, config) {
deferred.reject(status)
});
return deferred.promise;
}
}
});

Resources