Amplify-js: [Question] [Help Wanted] AWS Amplify - how to query DynamoDB table

Created on 3 Apr 2018  路  3Comments  路  Source: aws-amplify/amplify-js

I have created an app using react-native.

After a little struggling I can now connect it to my Dynamodb table and using AWS Amplify I can insert items with PUT and get a specific item back with GET.

So far so good.

I now want to be able to query the table and get back a subset of records. The aws documentation suggests using aws-sdk and that the syntax should be like this:

// Return all of the songs by an artist, with a particular word in the title...
// ...but only if the price is less than 1.00

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SQLtoNoSQL.ReadData.Query.html

{
TableName: "Music",
KeyConditionExpression: "Artist = :a and contains(SongTitle, :t)",
FilterExpression: "price < :p",
ExpressionAttributeValues: {
":a": "No One You Know",
":t": "Today",
":p": 1.00
}
}

Is there a way that I can do this sort of query using Amplify?

For info: I setup the app and its API like this:

create-react-native-app dbapp
cd dbapp
aws mobile init
npm install aws-amplify --save
awsmobile cloud-api enable --prompt

Thanks,

API question

Most helpful comment

@TheRealRed7 You can do this a few different ways.

  1. Use Lambda / API Gateway (basically what you are saying)
    This would be the most secure way, with the most "overhead" in terms of back-end. When you bootstrap using awsmobile init and enable cloud-logic, you would get a default backend lambda function that you could then include and query dynamo. You can see an example of something similar to that here:
    https://github.com/aws-samples/aws-serverless-ember/blob/master/cloud/index.js

with Amplfiy / CLI this is basically:

$ awsmobile features

Select database and cloud-api (as you noted) then awsmobile push to update your back-end. Then edit your awsmobilejs/backend lambda javascript file.

  1. Setup your cognito auth role to have access to your dynamodb table then run your queries directly on the client. This can be done similar to this:
    https://github.com/aws-samples/aws-mobilehub-ember/blob/master/app/adapters/note.js

For this you'd just pass through and call the queries directly on the underlying aws-sdk, utilizing Amplify for the Auth portion (just make sure your auth role has permissions to query dynamodb table):
https://aws.github.io/aws-amplify/media/quick_start#working-with-aws-service-interface-objects

So for example:

import DynamoDB from 'aws-sdk/clients/dynamodb';

...

Auth.currentCredentials()
  .then(credentials => {
    const db= new DynamoDB.DocumentClient({
      credentials: Auth.essentialCredentials(credentials)
    });

    // now you can run queries with dynamo and current scoped credentials i.e. db.query(...)
  })

All 3 comments

@TheRealRed7 You can do this a few different ways.

  1. Use Lambda / API Gateway (basically what you are saying)
    This would be the most secure way, with the most "overhead" in terms of back-end. When you bootstrap using awsmobile init and enable cloud-logic, you would get a default backend lambda function that you could then include and query dynamo. You can see an example of something similar to that here:
    https://github.com/aws-samples/aws-serverless-ember/blob/master/cloud/index.js

with Amplfiy / CLI this is basically:

$ awsmobile features

Select database and cloud-api (as you noted) then awsmobile push to update your back-end. Then edit your awsmobilejs/backend lambda javascript file.

  1. Setup your cognito auth role to have access to your dynamodb table then run your queries directly on the client. This can be done similar to this:
    https://github.com/aws-samples/aws-mobilehub-ember/blob/master/app/adapters/note.js

For this you'd just pass through and call the queries directly on the underlying aws-sdk, utilizing Amplify for the Auth portion (just make sure your auth role has permissions to query dynamodb table):
https://aws.github.io/aws-amplify/media/quick_start#working-with-aws-service-interface-objects

So for example:

import DynamoDB from 'aws-sdk/clients/dynamodb';

...

Auth.currentCredentials()
  .then(credentials => {
    const db= new DynamoDB.DocumentClient({
      credentials: Auth.essentialCredentials(credentials)
    });

    // now you can run queries with dynamo and current scoped credentials i.e. db.query(...)
  })

Thank you, I was really stuck with that.

Always nice to have choices - I chose option 2:

// Initialize the Amazon Cognito credentials provider
AWS.config.region = 'eu-west-1';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'eu-west-1:5f7af6b8-c701-4b54-a1ec-blahblahblah',
});

//I needed this to stop CRC errors (not too sure why they happened)
AWS.config.update({
dynamoDbCrc32: false
});

//create the db object
const db = new AWS.DynamoDB.DocumentClient({
apiVersion: '2012-08-10'
});

// setup the query params
var params = {
TableName : "blahblahprojectv-mobilehub-1547222168-blah blahblah",
ProjectionExpression:"hub_id, details.on_time, details.sensor_name",
KeyConditionExpression: "hub_id = :hid",
ExpressionAttributeValues: {
":hid":"PG2018f"
}
};

//then execute using db to query the dynamoDB table
db.query(params, function(err, data) {
if (err) {
console.log("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log("Query succeeded.");
data.Items.forEach(function(details) {
console.log(details.hub_id,details.sensor_name);
//this is where I will populate the variables in my app
});
}
});
}

Thank you, I was really stuck with that.

Always nice to have choices - I chose option 2:

// Initialize the Amazon Cognito credentials provider
AWS.config.region = 'eu-west-1';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'eu-west-1:5f7af6b8-c701-4b54-a1ec-blahblahblah',
});

//I needed this to stop CRC errors (not too sure why they happened)
AWS.config.update({
dynamoDbCrc32: false
});

//create the db object
const db = new AWS.DynamoDB.DocumentClient({
apiVersion: '2012-08-10'
});

// setup the query params
var params = {
TableName : "blahblahprojectv-mobilehub-1547222168-blah blahblah",
ProjectionExpression:"hub_id, details.on_time, details.sensor_name",
KeyConditionExpression: "hub_id = :hid",
ExpressionAttributeValues: {
":hid":"PG2018f"
}
};

//then execute using db to query the dynamoDB table
db.query(params, function(err, data) {
if (err) {
console.log("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log("Query succeeded.");
data.Items.forEach(function(details) {
console.log(details.hub_id,details.sensor_name);
//this is where I will populate the variables in my app
});
}
});
}

Hi ,

I am having an issue.. I am trying to do the same thing.

But , when I am querying from React JS code , request seems to be going on forever.

I have listed the issue here : https://github.com/aws-amplify/amplify-js/issues/2056

Can you please help me with this issue ?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

guanzo picture guanzo  路  3Comments

callmekatootie picture callmekatootie  路  3Comments

rayhaanq picture rayhaanq  路  3Comments

ddemoll picture ddemoll  路  3Comments

romainquellec picture romainquellec  路  3Comments