data is not showing in Dynamodb table - node.js

i am working on lex chatbot and want to store user data in dynamodb.
here is my databaseManager.js file code
'use strict';
const { v1: uuidv1 } = require('uuid');
const AWS = require('aws-sdk');
const dynamo = new AWS.DynamoDB.DocumentClient();
module.exports.saveBookingToDatabase = async function(Arrival_city, Departure_city, Flight_type, Phone_number){
console.log('saveBookingToDatabase');
const item = {};
item.bookingId = uuidv1();
item.arrivalCity = Arrival_city;
item.departureCity = Departure_city;
item.classType = Flight_type;
item.phone = Phone_number;
const params = {
TableName: 'air_stallion',
Item: item
};
try {
let result = await dynamo.put(params)
console.log(`Saving ticket ${JSON.stringify(item)}`);
return item;
} catch(e) {
throw (e)
}
}
Table has been created but data is now showing in table

The values should not be empty, give some default values to prevent null or empty values.
For Example:
const item = {};
item.bookingId = uuidv1();
item.arrivalCity = Arrival_city || "Arr";
item.departureCity = Departure_city || "Dept";
item.classType = Flight_type || "Type";
item.phone = Phone_number || "Phone";
If the values are okay, then try with
let result = await dynamo.put(params).promise()

Related

Firebase Function onCreate add to new collection works, but update does not

I have this onCreate Trigger, I am using it to aggregate and add record or update record. First it takes minutes to add the record and then the update never runs just keeps adding, not sure why my query is not bringing back a record to update.
Any suggestion would be great.
exports.updateTotals = functions.runWith({tinmeoutSeconds: 540})
.firestore.document("user/{userID}/CompletedTasks/{messageId}")
.onCreate(async (snap, context) => {
const mycompleted = snap.data();
const myuserid = context.params.userID;
console.log("USER: "+myuserid);
const mygroup = mycompleted.groupRef;
const myuser = mycompleted.userRef;
const newPoints = mycompleted.pointsEarned;
console.log("POINTS: "+newPoints);
const data = {
groupRef: mygroup,
userRef: myuser,
pointsTotal: newPoints,
};
const mytotalsref = db.collection("TaskPointsTotals")
.where("groupRef", "==", mygroup)
.where("userRef", "==", myuser);
const o = {};
await mytotalsref.get().then(async function(thisDoc) {
console.log("NEW POINTS: "+thisDoc.pointsTotal);
const newTotalPoints = thisDoc.pointsTotal + newPoints;
console.log("NEW TOTAL: "+newTotalPoints);
if (thisDoc.exists) {
console.log("MYDOC: "+thisDoc.id);
o.pointsTotal = newTotalPoints;
await mytotalsref.update(o);
} else {
console.log("ADDING DOCUMENT");
await db.collection("TaskPointsTotals").doc().set(data);
}
});
});
You are experiencing this behavior because while querying for updates you are getting more than 1 document and you are using thisDoc.exists on more than one document. If you have used typescript this could have been catched while writing the code.
So for the update query, if you are confident that only unique documents exist with those filters then here’s the updated code that I have recreated using in my environment.
functions/index.ts :
exports.updateTotals = functions.runWith({timeoutSeconds: 540})
.firestore.document("user/{userId}/CompletedTasks/{messageId}")
.onCreate(async (snap, context) => {
const mycompleted = snap.data();
const myuserid = context.params.userID;
console.log("USER: "+myuserid);
const mygroup = mycompleted.groupRef;
const myuser = mycompleted.userRef;
const newPoints = mycompleted.pointsEarned;
console.log("POINTS: "+newPoints);
const data = {
groupRef: mygroup,
userRef: myuser,
pointsTotal: newPoints,
};
const mytotalsref = admin.firestore()
.collection("TaskPointsTotals")
.where("groupRef", "==", mygroup)
.where("userRef", "==", myuser);
await mytotalsref.get().then(async function(thisDoc) {
if (!thisDoc.empty) { // check if the snapshot is empty or not
const doc = thisDoc.docs[0];
if(doc.exists){
const newTotalPoints = doc.data()?.pointsTotal + newPoints;
const id = doc.id;
await db.collection("TaskPointsTotals").doc(id).update({pointsTotal: newTotalPoints});
}
} else {
await db.collection("TaskPointsTotals").doc().set(data);
}
});
});
For more information about QuerySnapshot methods check this docs

Google Cloud Functions Add values to a map in firestore

This is my code to add values to a map in firestore. At the moment the map gets overwritten everytime
exports.addTrainingtoList = functions.firestore
.document('/users/{uid}/trainings/{trainings}')
.onCreate((change, context) => {
const doc = admin.firestore().collection('users').doc(context.params.uid).collection('user').doc('trainings');
const trainingsID = change.data().trainingsID;
const trainingsName = change.data().training;
const trainingsTimestamp = change.data().timestamp;
doc.update({
Trainings: {
...doc.Trainings,
[trainingsID]: {
'trainingsName': trainingsName,
'trainingsDate': trainingsTimestamp,
},
},
})
});
This is my updated code after Franks answer:
exports.addTrainingtoList = functions.firestore
.document('/users/{uid}/trainings/{trainings}')
.onCreate((change, context) => {
const doc = admin.firestore().collection('users').doc(context.params.uid).collection('user').doc('trainings');
const trainingsID = change.data().trainingsID;
const trainingsName = change.data().training;
const trainingsTimestamp = change.data().timestamp;
const nameField = trainingsID + ".trainingsName";
const timestampField = trainingsID + ".trainingsDate";
doc.update({
Trainings: {
...doc.Trainings,
[nameField]: trainingsName,
[timestampField]: trainingsTimestamp,
},
})
});
Currently the map is overwritten.
Here u can see what I get:
Here u can see what I want to have.
Thanks in advance.
To add nested fields in an object use dot notation like this:
const nameField = trainingsID + ".trainingsName";
const timestampField = trainingsID + ".trainingsDate";
doc.update({
Trainings: {
...doc.Trainings,
[nameField]: trainingsName,
[timestampField]: trainingsTimestamp,
},
})
Since you updated your question to show what you want to get, that can be accomplished with:
const trainingsID = change.data().trainingsID + Date.now();
And then your original code to update the document.
Finally with Franks help I found a solution for my problem.
exports.addTrainingtoList = functions.firestore
.document('/users/{uid}/trainings/{trainings}')
.onCreate((change, context) => {
const doc = admin.firestore().collection('users').doc(context.params.uid).collection('user').doc('trainings');
const trainingsID = change.data().trainingsID;
const trainingsName = change.data().training;
const trainingsTimestamp = change.data().timestamp;
const nameField = `trainings.${trainingsID}.trainingsName`;
const dateField = `trainings.${trainingsID}.trainingsDate`;
doc.update({
[nameField]: trainingsName,
[dateField]: trainingsTimestamp,
})
});
This is the result:
If you finally want to delete values out of the map you can use:
exports.delTrainingtoList = functions.firestore
.document('/users/{uid}/trainings/{trainings}')
.onDelete((change, context) => {
const doc = admin.firestore().collection('users').doc(context.params.uid).collection('user').doc('trainings');
const trainingsID = change.data().trainingsID;
const trainingsName = change.data().training;
const trainingsTimestamp = change.data().timestamp;
const trainingsField = `trainings.${trainingsID}`;
doc.update({
[trainingsField]: FieldValue.delete(),
})
});

Cloud function query with typescript

I am trying to query a firestore field (dropdown) 'Title'. I am using following code to get the total number of Title for a given user but i want to apply filter and get count only when Title == Game. Please help. How can i modify this function to set counter only when this condition is met.
Currently it is getting me number of title.
import * as admin from 'firebase-admin'
import * as functions from 'firebase-functions'
admin.initializeApp()
export const updateCharts =
functions.firestore.document('users/{UserId}/count/{uid}')
.onWrite(async(change, _) => await updateStats(change))
async function updateStats (change:
functions.Change<functions.firestore.DocumentSnapshot>){
const chartRating = change.after.ref.parent
let Title = 0
const docRefs = await chartRating.listDocuments()
for (const docRef of docRefs) {
const snapshot = await docRef.get()
const data = snapshot.data()
if (data !== undefined) {
Title++
}
}
const restaurantRef = chartRating.parent!
console.log('{restaurantRef.path} now has ${Title}')
await restaurantRef.update({
Title: Title,
})
}
Replace this
let Title = 0
const docRefs = await chartRating.listDocuments()
for (const docRef of docRefs) {
const snapshot = await docRef.get()
const data = snapshot.data()
if (data !== undefined) {
Title++
}
}
with
let title = (await chartRating.where('Title', '==', 'Game').get()).size;
replace the where statement with the condition you need.

Can I use #google-cloud/logging Node.js library to getEntries filtering by date?

I've got this code to getEntries from my project's cloud-logging.
import { Logging } from "#google-cloud/logging";
const PROJECT_ID = "XXXXX";
const logging = new Logging({ projectId: PROJECT_ID });
const getAdminLogEntries = async () => {
const result = await logging.getEntries({
filter: `logName="projects/XXXXX/logs/my-custom-log-name"`,
});
const entryList = result[0];
for (const entry of entryList) {
console.log(`entry.metadata: ${JSON.stringify(entry.metadata)}`);
console.log(`entry.data: ${JSON.stringify(entry.data)}`);
console.log(`---`);
}
};
getAdminLogEntries();
But I'm only getting 6 results (the oldest one is from yesterday). And I guess it's because the query is not going too far back in time. Can it filter it by date? Ex: from 2021-01-01 to 2021-01-31?
Here is what I've found out.
Reference:
https://cloud.google.com/logging/docs/view/advanced-queries
https://cloud.google.com/logging/docs/reference/libraries#list_log_entries
I was able to filter by date with the following code:
import { Logging } from "#google-cloud/logging";
const PROJECT_ID = "XXXX";
const logging = new Logging({ projectId: PROJECT_ID });
const filterItems = [
`logName="projects/XXXXX/logs/admin-logs"`,
`timestamp >= "2021-02-01T00:00:00Z"`,
`timestamp < "2021-03-01T00:00:00Z"`,
`severity="WARNING"`,
];
// JOINING FILTERS WITH "AND" OPERATOR
const filters = filterItems.join(" AND ");
const getAdminLogEntries = async () => {
const result = await logging.getEntries({
filter: filters,
});
const entryList = result[0];
for (const entry of entryList) {
console.log(`entry.metadata.severity: ${JSON.stringify(entry.metadata.severity)}`);
console.log(`entry.metadata.timestamp: ${JSON.stringify(entry.metadata.timestamp)}`);
console.log(`entry.data.message: ${JSON.stringify(entry.data.message)}`);
console.log(`---`);
}
};
getAdminLogEntries();

Query onto a dynamoDb table

I am trying to get all the records of a database that meet a filter that I already defined. The problem with this is that I am having to repeat it N times depending on the number of organizations. Is there a way to make it iterate for each of the organizations?
I tried putting the organization_code in an array but it fails saying that the schema is not correct. Please help
const AWS = require('aws-sdk')
AWS.config.update({ region: 'us-east-2' })
const dDBClient = new AWS.DynamoDB.DocumentClient();
const async = require('async')
let scanComplete = false
let beginDate = "2020-12-16 00:00:00.000"
let endDate = "2020-12-23 00:00:00.000"
const organization_code = "CLPIT01DB" < - HERE ARE JUST 1 ORG, NEED 6 of them!
const params = {
ExpressionAttributeValues: {
':organization_code': organization_code,
':BeginDate': beginDate,
':EndDate': endDate
},
KeyConditionExpression: 'organization_code = :organization_code',
ProjectionExpression: `booking_id,booking_payment_ids,booking_pnr,company_address,company_city,company_comuna,company_girototal_amount_clp,total_amount_exe,total_amount_vat,vat`,
FilterExpression: 'payment_createdutc >= :BeginDate and payment_createdutc < :EndDate',
TableName: 'TemporaryPayments'
}
restOfTheCode
TableConfiguration
Thank you very much!
You can try this :
const AWS = require('aws-sdk')
AWS.config.update({ region: 'us-east-2' })
const dDBClient = new AWS.DynamoDB.DocumentClient();
let beginDate = "2020-12-16 00:00:00.000"
let endDate = "2020-12-23 00:00:00.000"
let arrayData = []; // init list of query data
// Initiate the params
let params = {
ExpressionAttributeValues: {
':BeginDate': beginDate,
':EndDate': endDate
},
KeyConditionExpression: 'organization_code = :organization_code',
ProjectionExpression: `booking_id,booking_payment_ids,booking_pnr,company_address,company_city,company_comuna,company_girototal_amount_clp,total_amount_exe,total_amount_vat,vat`,
FilterExpression: 'payment_createdutc >= :BeginDate and payment_createdutc < :EndDate',
TableName: 'TemporaryPayments'
}
async function db_query(org_code) {
params.ExpressionAttributeValues = {
...params.ExpressionAttributeValues,
{
':organization_code': org_code
}
}
let res = await dDBClient.query(params).promise();
arrayData = [
...arrayData,
res.Items
]
if (res.LastEvaluatedKey) {
params.ExclusiveStartKey = res.LastEvaluatedKey;
return db_query(org_code);
}
console.log(org_code+" data length : "+arrayData.length)
arrayData = [];
}
db_query("CLPIT01DB")
You can iterate the organization queries by doing this :
const org_codes = ["CLPIT01DB", "xxxxxxxxx", etc];
let org_queries = [];
org_codes.forEach(org => {
org_queries.push(db_query(org));
})
Promise.all(org_queries)

Resources