Resource not found querying dynamodb - javascript

I am trying to access a DynamoDb table, but I keep getting a "Resource not found" error.
The table is defined as follows, note that the table is Active and the Region is Paris (eu-west-3)
The code I am using:
export class EncuestaComponent implements OnInit {
[...]
client: DynamoDBClient = new DynamoDBClient({
region : 'eu-west-3',
credentials: {
accessKeyId: '[REDACTED]',
secretAccessKey: '[REDACTED]'
}
});
[...]
onDbClick() {
const commandParams = {};
const input: BatchExecuteStatementInput = {
Statements: [
{Statement: "SELECT opciones FROM encuesta.encuesta WHERE id = 'user.1'"}
],
}
const command = new BatchExecuteStatementCommand(input);
this.client.send(command).
then(data => console.log(data.Responses![0].Error)).
catch(error => {console.log("Error"); console.log(error)});
}
And, in the console, it shows that the then method has been executed, but the message printed is {Code: 'ResourceNotFound', Message: 'Requested resource not found'}
What am I doing wrong?

In PartiQL for DynamoDB, when you do select * from something.else means that you want it to query an index named else on table named something. Either you need to do one of the following:
escape the .
surround the table name with quotes
create a new table with a different name
I am not in front of my computer or i would figure out which it is for you, but this is where I'd start.

Here is something that might be causing the problem.
Can you confirm that
the accessKey that you are using have permission to read from the DynamoDB table?
that the accessKey has not expired and can be used?
Here are a few things that can help you test out the functionality try adding the key in ~/.aws/credentials and running this command.
aws dynamodb scan --table-name encuesta.encuesta
and confirm that it is indeed showing up the table content and not getting an access denied error.

Related

How can I use DEFAULT values via knex insert?

My goal is to dynamically insert data into a table via knex.
Code looks like this:
const knexService = require("../knexService.js")
async function insertObjectToKnex() {
const insertObject = {
id: "DEFAULT",
someKey: "someValue"
};
await knexService.db("table").insert(inserObject);
}
On DEFAULT the next free id should be used as database id - table is configured and it works with raw sql. With knex.js I get the following error:
invalid input syntax for type integer: "DEFAULT"
Using the useNullAsDefault: true, config is not possible, because the id is not nullable.
How can I trigger the default value in knex - I did not find anything in the documentation or with google, that could at least give a hint to this issue!
While it is not mentioned in the documentation of knex.js one should simply not add fields with a DEFAULT assignement to a query. This will set the default value to the row column.

Cant use arrayRemove in Firestore. Function DocumentReference.update() called with invalid data

Cant see the problem in my code when trying to delete elements in array with "arrayRemove".
This is my code:
const getRef = firebase.firestore().collection('customers').doc('andreas');
const response = await getRef.get();
console.log(response.data()); // answer { bookings: [ '123booking', '456booking' ] }
// then i'm trying to delete the element with value 123booking:
let deleteRef = firebase.firestore().collection('customers').doc('andreas');
const removeRes = await deleteRef.update({
bookings: admin.firestore.FieldValue.arrayRemove('123booking')
});
This is my error message:
Error [FirebaseError]: Function DocumentReference.update() called with invalid data. Unsupported field value: a custom object (found in field bookings in document customers/andreas)
Apparently you are mixing up the use of the JS SDK and of the Admin SDK:
On one hand, you do
const getRef = firebase.firestore().collection('customers').doc('andreas'); // JS SDK
and on the other hand, you do
bookings: admin.firestore.FieldValue.arrayRemove('123booking') // Admin SDK
If you are actually using the Admin SDK (refer to the question tags), you should do
const getRef = admin.firestore().collection('customers').doc('andreas');
On the other hand, if you are not using the Admin SDK, i.e. this code is executed in a web app, change the following line from
bookings: admin.firestore.FieldValue.arrayRemove('123booking')
to
bookings: firebase.firestore.FieldValue.arrayRemove('123booking')

How to use Knex with Transactions to save into SQLITE3

Hey everyone i have the following code that retrieves data from cloud, then i need to save it to a database. I did it using Knex to make a seed file, and also using a regular function, but i need to do it using transactions with Knex.
Here is what i did :
function addPatient(){
return knex.transaction((t) => {
return knex('patients').insert({
uid: patient.uid,
first_name: patient.first_name,
last_name: patient.last_name,
birth_date: patient.birth_date,
code: patient.code,
birthsex: patient.birthsex,
})
}).then(t.commit)
.catch(function(e) {
t.rollback();
throw e;
})
}
Although sometimes i replaced the json by a variable object that gets all the data.
And i imported knex as following :
const knex = require(path.join(__dirname, 'knexfile.js'));
What intrigues me is i get this error :
knex.transaction is not a function, can anyone please hint or help or point to me where i am wrong ?
Thank you

TypeORM AfterSave() triggers after creation but when queried, it returns NULL

I have an Entity called Trip. The structure is:
What I want is whenever a new trip is created, the room column should be populated with ${tripId}_${someRandomStringHere}. So for example, I just created a new trip using this body:
The response should be:
The newly created trip has the id of 15. So, the response has the room valued at 15_4gupvdo0ea408c25ia0qsbh because again: ${tripId}_${someRandomStringHere}.
This is working as expected whenever I POST the request and create the trip. BUT whenever I query all the trips created, the room property of each trip objects shows null!
Look at the /api/trips:
room property is NULL. So what the heck I dont understand what is happening.
My Trip Entity code is:
import { PrimaryGeneratedColumn, Column, CreateDateColumn,
UpdateDateColumn, Entity, Unique, ManyToOne, AfterInsert, JoinColumn, getConnection } from 'typeorm'
import { DriverEntity } from 'src/driver/driver.entity';
#Entity('trips')
export class TripEntity {
#PrimaryGeneratedColumn()
id: number
#Column()
destination: string
#Column('decimal')
destination_lat: number
#Column('decimal')
destination_long: number
#Column()
maxPassenger: number
#Column()
totalPassenger: number
#Column({ nullable: true })
room: string
#CreateDateColumn()
created_at: Date
#UpdateDateColumn()
updated_at: Date
// --------->HERE: The after insert
#AfterInsert()
async createSocketRoom(): Promise<void> {
const randomString = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
this.room = `${this.id}_${randomString}`
}
// Trip belongs to driver
// Adds driver_id to trips table
#ManyToOne(type => DriverEntity, driver => driver.trips)
#JoinColumn({ name: 'driver_id' })
driver: DriverEntity
}
My Trip Service Code is:
async create(data: CreateTripDTO) {
const { driver_id } = data
const driver = await this.driverRepository.findOne({ where: { id: driver_id } })
const trip = await this.tripRepository.create(data)
trip.driver = driver
await this.tripRepository.save(trip)
return trip
}
I dont think I need to include the Trip Controller code but anyway..
I don't know why it is happening because I have my User Entity with #BeforeUpdate and works fine...
After reading alot of similar github issues, watched youtube tutorials [Hi Ben Awad! :D], I found a somewhat fix.. by using Subscribers
Actually, I don't know what is the difference of the Listener/Subscriber. Maybe I am doing the wrong usage. Can someone enlighten me please? For example the difference of AfterSave of Entity Listener vs AfterSave of Entity Subscriber. When/Best case to use? something like that. Anyway back with the "fix..."
I created a Trip Subscriber:
import { EventSubscriber, EntitySubscriberInterface, InsertEvent } from "typeorm";
import { TripEntity } from "src/trip/trip.entity";
#EventSubscriber()
export class TripSubsriber implements EntitySubscriberInterface<TripEntity> {
// Denotes that this subscriber only listens to Trip Entity
listenTo() {
return TripEntity
}
// Called after entity insertion
async afterInsert(event: InsertEvent<any>) {
console.log(`AFTER ENTITY INSERTED: `, event.entity);
const randomString = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
// query the trip with given event.entity
const trip = await event.manager.getRepository(TripEntity).findOne(event.entity.id)
// populate the room with desired format
trip.room = `${trip.id}_${randomString}`
// save it!
await event.manager.getRepository(TripEntity).save(trip)
}
}
At first it is not working but after digging for hours again, I need to add a subscriber property with the value of the path of my subscribers at the ormconfig.json for it to work!
e.g: "subscribers": [
"src/subscriber/*.ts"
]
Again, the Trip Subscriber code seems spaghetti to me because I already have the event.entity object but I do not know how to update it without the need of querying and updating it using event.manager.getRepository(). Please can someone fix this code for me? the proper way of doing it?
NOW, It is working!
the request body:
the /api/trips res:
My questions are:
Why whenever I use that method methoud subscriber, it is not working. Is it not the proper way to do it? The why is it in the docs? Or for other use case?
Do I really have to use subscriber for it to achieve? Thats so many steps.
I came from Rails. So having to create files/subscribers just to do it somewhat tiring. Unlike ActiveRecord's after_save callback it is very easy..
PS. I'm new to nest-js and typeorm
#AfterInsert method will just modify your JS object after inserting into DB is done. So thats reason why is your code not working. You have to use #BeforeInsert decorator. BeforeInsert will modify your JS entity/object before inserting/saving into DB.
What it looks like is happening with your AfterInsert is that you are creating the random room string just fine, but you are not saving the value to the database, only using the return of the id so that you can create the string. What you could do in your AfterInsert is run the save() function from the EntityManager or RepositoryManger once more and commit the value to the database, similar to what you have happening in you Subscriber. I haven't dived too deep into the Subscriber/Listener vs Before-/AfterInsert decorators, so I can't give a deeper answer to your questions.
If you'd rather not make two commits to the database, you can always do a query for the most recent id and increment it by 1 (thus, matching what the new objects id should be) with something like
const maxId = await this.tripRepository.findOne({select: ['id'], order: {id: "DESC"} });
const trip = await this.tripRepository.create(data);
const randomString = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
this.room = `${maxId + 1}_${randomString}`
trip.driver = driver
await this.tripRepository.save(trip)
It's a little clunky to look at, but it doesn't require two writes to the database (though you'll definitely need to ensure that after creation room and trip have the same id).
Your last option would be to create a Trigger in your database that does the same thing as your JavaScript code.
You just use "this.save()" after all in createSocketRoom() function
https://i.stack.imgur.com/oUY8n.png my query after use that!!!

AWS : How to specify dynamodb arn in javascript SDK

So I'm trying to put records into a DynamoDB table from an AWS lambda function. I've set up the role for the lambda function to have access for the lambda function. However, in all the example code from the dynamo documentation below has no reference to an identifier/arn. Is one not needed, and instead the specific dynamoDB instance to use is inferred from the IAM role that the lambda function uses?
Essentially, my question is how can all the code do is call new AWS.DynamoDB(...) and 'automatically' know the right database to access/modify?
Example code:
var table = new AWS.DynamoDB({apiVersion: '2012-08-10', params: {TableName: 'MY_TABLE'}});
var key = 'UNIQUE_KEY_ID';
// Write the item to the table
var itemParams = {
Item: {
id: {S: key},
data: {S: 'data'}
}
};
table.putItem(itemParams, function() {
// Read the item from the table
table.getItem({Key: {id: {S: key}}}, function(err, data) {
console.log(data.Item); // print the item data
});
});
Table name and region is all you should need to specify.
Is one not needed, and instead the specific dynamoDB instance to use
is inferred from the IAM role that the lambda function uses?
The AWS SDK configuration provides the account and region. Those pieces of information, coupled with the table name, are everything it needs to connect to your table. In this case I believe the IAM role provides the account information, and you have specified the table name. You might also need to specify the region depending on if the table is in the default region or not.

Categories

Resources