DynamoDB table is getting created but can not insert new items - amazon-dynamodb

I am using the boto DynamoDBV2 interface for a script to create and populate a table in the DynamoDB. My code for it looks something like this -
my_table = Table.create(table_name, schema=[HashKey('key', data_type=STRING)], connection = self.connection)
my_table.put_item(data={
'key': 'somekey',
'value': value
})
I have created the connection, and when I run it, the table is created properly and I can see it in the AWS console. But I am getting the error "Requested Resource not found" when trying to put values in the table.
I also tried reading table separately and then insert values like this -
Table.create(table_name, schema=[HashKey('key', data_type=STRING)], connection = self.connection)
my_table = Table(table_name, self.connection)
my_table.put_item(data={
'key': 'somekey',
'value': value
})
but still getting the same error on the second line. What am I missing ?

The problem is that you need to wait a little bit after the table is created before inserting items. You can use the waitFor() event to find when the table finishes to be created.
Example with AWS Node SDK:
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB();
const createTableParams = {
// parameters...
}
dynamodb.createTable(createTableParams, (err, data) => {
if (err) return console.log(err, err.stack);
const params = {
TableName: 'MY_TABLE'
};
dynamodb.waitFor('tableExists', params, (err, data) => {
if (err) console.log(err, err.stack);
else insertData();
});
});

Your table will not be immediately ready on creation, you have to wait for it to become active before writing to it. I found a Java code sample that illustrates how to do this, but the problem is not language-specific, it applies to any DynamoDB client.
You can see this in the AWS Management Console as the "Status" of the table, to confirm or deny this theory.

Related

Superbase db query from URL

I'm struggling to formulate a supabase db query from multiple tables, whilst using a value from a URL.
I have 3 tables (simplified)...
series > id, series
authors > id, name
books > id, title, series_id(fk), authors_id(fk)
I want to get a list of books in a series, along with the author and series name from the following URL...
app.com/series. i.e. app.com/harrypotter
I can get the series name using getServerSideProps, but struggling how to write my query to supabase. Every way I write it either gives me a NULL object or a 500 error.
I feel like I should be querying the books table and then be able to get the series and author names through the foreign keys. But the query that it's centred around is the series name, which is in the series table. So unsure of the db query to do it, or whether I should structure my db table's in a different way?
export async function getServerSideProps( context ) {
const { series } = context.query;
...
return {
props: {
...
}
};
}
Thanks for any help in advance!
Please ensure you have foreign keys set up, and then you can use Supabase to query foreign table examples (SQL join).
There needs to be more data to give an exact answer, but here are the relevant docs.
Supabase get a single record
Supabase select - not super obvious, but you need to click the button Query foreign tables
Supabase filters
I also included logs and a try/catch so you can see your exact errors and where your code is failing.
const Page = (props) => {
console.log(props)// logged to browser's console
return <>Your page<>;
}
export async function getServerSideProps( context ) {
try {
const { series } = context.query;
console.log("series", series); // ensure series is present and check if is an object
const { data, error } = await supabase.from('series')
.select(`
id,
title,
book (
title // you can also use `*` check out select all docs
author (
name
)
)
`)
.eq('id', series)
.limit(1)
console.log("error", error);
console.log("data", data);
return {
props: {
series: data
}
}
} catch (e) {
console.log(e);
}
}
export default Page;
Note: getServerSideProps logs will show up in your server's console (where you run npm dev) - not the browser's console. You should remove the console logs once you figure out what's happening.

AWS DynamoDB Scan Operation ScanFilter Not Working

I am running below dynamo DB scan query in AWS
const dynamoDb = require('aws-sdk/clients/dynamodb.js');
const dynmoDBClient = new dynamoDb.DocumentClient({ region: "REGION"});
let params = {
"TableName":"Users",
"ScanFilter":{
"name":{
"AttributeValueList":[
{
"S":""
}
],
"ComparisonOperator":"GT"
}
},
"Select":"ALL_ATTRIBUTES"
}
let result = null;
result = await dynmoDBClient.scan(params).promise();
When I run the query , I get below error -
ERROR occurred while querying data from DB :
{"message":"One or more parameter values were invalid:
ComparisonOperator GT is not valid for M AttributeValue type"}
As per table definition , name attribute is of type S (string) and not M (map)
But I am still getting this error.
Can anybody please help here as I am not getting what is the issue here ?
AWS maintains sample code of core DynamoDB operations in various languages. Here's their sample for Scan in Node.js:
https://github.com/aws-samples/aws-dynamodb-examples/blob/master/DynamoDB-SDK-Examples/node.js/WorkingWithScans/scan-parallel-segments.js
ScanFilter is legacy so don't go there.
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.ScanFilter.html

Obtaining data from Firebase and creating an object in Flutter, Dart

I would like to create an Object using data from my Firebase database. I get the data correctly, but I can't create that Objet in the way im trying. I have no idea why it doesn't work, this is my first time using Dart.
Here is my code
MaterialQR selectFromFirebase(String document) {
MaterialQR res = MaterialQR(exercises: [], image: '', name: '', id: '');
FirebaseFirestore.instance.collection('MaterialQR')
.doc(document).get()
.then((value) => res = new MaterialQR(
exercises: value['exercises'],
image: value['image'],
name: value['name'],
id: value['id']));
return res;
}
The objective is return an "empty" Object if the document in my database doesn't exist or return a correct Object if the document exists. When I print(value['id']) inside .then(), I got a correct id, but it doesn't work when I create the new Object.
This is because data is loaded from Firestore (and pretty much any modern cloud API) asynchronously, because it may take some time before it's available. Instead of blocking your code (and the user) during this time, your main code actually continues to execute. Then when the data is available, your then block executes.
This is easiest to see if you place some logging in the code, run it, and check its output.
print('Before starting to read from the database');
FirebaseFirestore.instance.collection('MaterialQR')
.doc(document).get()
.then((value) => {
print('got data from the database');
});
print('After starting to read from the database');
The output of this is:
Before starting to read from the database
After starting to read from the database
Got data from the database
This is probably not what you expected, but it explains perfectly why you don't get a result from selectFromFirebase: the return res runs before res is ever set by your then block.
There is no way to prevent this asynchronous nature of the call. Instead you'll have to accept that calling cloud APIs is asynchronous, and return a Future from the method and mark is as async:
Future<MaterialQR> selectFromFirebase(String document) async {
That also means you can use await in there, so the entire function then becomes:
Future<MaterialQR> selectFromFirebase(String document) async {
try {
var value = await FirebaseFirestore.instance.collection('MaterialQR')
.doc(document).get();
return MaterialQR(
exercises: value['exercises'],
image: value['image'],
name: value['name'],
id: value['id']);
}
catch {
return MaterialQR(exercises: [], image: '', name: '', id: '');
}
}
See also:
The Flutter documentation on asynchronous operations and futures
The Flutter codelab on Asynchronous programming: futures, async, await.

Firebase query download the whole database. Why?

I try to download and show only specific data from the Realtime Database. I have the following code:
getUserPlatformIos() {
this.dataRef = this.afDatabase.list('data/users', ref => ref.orderByChild('meta/platform').equalTo('ios'));
this.data = this.dataRef.snapshotChanges().map(changes => {
return changes.map(c => ({ key: c.payload.key, ...c.payload.val() }));
});
return this.data;
}
My firebase database structure
Firebase rules
Why firebase does download the whole database if I query before? This causes very long loading times and a lot of downloaded data....
Indexes need to be defined at the place where you the query. Since you run the query on data/users, that's where you need to define your index:
"users": {
".indexOn": "meta/platform"
}
This defines an index on users, which has the value of the meta/platform property of each user.
Note that the log output of your app should be showing an error message with precisely this information. I highly recommend checking log output whenever something doesn't work the way you expect it to work.

How do to log a Error Callback in SQLite?

I am trying to connect to a database using the code below:
import SQLite from 'react-native-sqlite-storage'
var db = SQLite.openDatabase({name : "banco.db", createFromLocation : 1}, this.successCB(), this.errorCB());
errorCB() {
this.setState({message: "I NEED SHOW THE ERROR HERE"});
}
successCB() {
this.setState({message: "SQL executed fine"});
}
How to show the error on the errorCB function?
This is in the documentation example. The error callback will get passed an argument containing the error. You are also not providing the correct value to openDatabase. You should be passing in functions, not trying to call the function.
Copy pasting the relevant parts from the documentation with comments to explain:
// Your error callback function that should take an argument that will contain your error.
errorCB(err) {
console.log("SQL Error: " + err);
// Here you can use err in your setState call.
}
openCB() {
console.log("Database OPENED");
}
// openDatabase should be passed in the functions; openCB and errorCB in this example.
var db = SQLite.openDatabase("test.db", "1.0", "Test Database", 200000, openCB, errorCB);
// What you're doing is incorrect as it's akin to doing this which is wrong.
// var db = SQLite.openDatabase("test.db", "1.0", "Test Database", 200000, openCB(), errorCB());
This is really more of a basic JavaScript question where you need to be able to read the documentation and understand how to use a given API. If you're having trouble with this, I suggest reading up about Higher-Order Functions as it's fundamental to JavaScript.
Edit: To be very direct and answer the comments; this is what your code should look like:
import SQLite from 'react-native-sqlite-storage'
var db = SQLite.openDatabase({name : "banco.db", createFromLocation : 1}, this.successCB, this.errorCB);
// Making the assumption that these are in a class,
// otherwise add the const keyword before them.
// Convert these to arrow functions instead
// so they can more easily be passed as variables.
errorCB = (err) => {
this.setState({message: err});
}
successCB = () => {
this.setState({message: "SQL executed fine"});
}
Given your comments, I'll be very direct here. If you don't understand how functions, Higher-Order Functions, and variables/values work in JavaScript, you are going to have a very difficult time with React Native. Especially so if you are unfamiliar with ES6 syntax. Go through the book in that link or one of the many other great resources for learning the fundamentals of JavaScript before tackling React Native.
I used to open SQLite using following statement
database = SQLite.openDatabase({name: 'my.db', location: 'default'}, (db) => {
db.transaction( tx => {
tx.executeSql(`CREATE TABLE IF NOT EXISTS tableName (columnNames)`);
}, error => {
this.setState({message: error});
});
}, error => {
this.setState({message: error});
});
Hope this will help!

Resources