I am using node js to get data from dynamoDB. However at the moment I am retrieving the data with the UserId. I want to retrieve the data using the secondary index that I have created, which is dateId. My dynamoDB table consists of userId, Exercises, Sets, Reps and dateId. How can I achieve that?
I already tried to add the Index-name under the table name with the dateId value but it's not working.
My dbHelper.js looks like this.
dbHelper.prototype.getExercises = (userID) => {
return new Promise((resolve, reject) => {
const params = {
TableName: tableName,
KeyConditionExpression: "#userID = :user_id",
ExpressionAttributeNames: {"#userID": "userId"},
ExpressionAttributeValues: {":user_id": userID }
}
docClient.query(params, (err, data) => {
if (err) {
console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
return reject(JSON.stringify(err, null, 2))
}
console.log("GetItem succeeded:", JSON.stringify(data, null, 2));
resolve(data.Items)
})
});
}
My index.js looks like this
const GetExercisesIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'GetExercisesIntent';
},
async handle(handlerInput) {
const {responseBuilder } = handlerInput;
const userID = handlerInput.requestEnvelope.context.System.user.userId;
return dbHelper.getExercises(userID)
.then((data) => {
var speechText = 'Your exercises of the day are '
if (data.length == 0) {
speechText = "You do not have any favourite exercises yet, add exercise by
saving add moviename "
} else {
speechText += data.map(e => e.Exercise).join(", ")
}
return responseBuilder
.speak(speechText)
.reprompt(GENERAL_REPROMPT)
.getResponse();
})
.catch((err) => {
const speechText = "we cannot get your exercise right now. Try again!"
return responseBuilder
.speak(speechText)
.getResponse();
})
}
}
I think your function should look more like this example, based on combining AWS's documentation with your original code.
I think you'll want to supply the partition key for the Index (which I'm assuming is dateId) rather than the table's partition key.
The ProjectionExpression seems to let us specify a list of attributes to return, and I gather that you want just the Exercises attribute for each item matching the specified dateId.
dbHelper.prototype.getExercises = (dateID) => {
return new Promise((resolve, reject) => {
const
tableName = NameOfDynamoDbTable, // Must be the actual table name
indexName = NameOfDynamoDbIndex, // Must be the actual index name on that table
params = {
"TableName": tableName,
"IndexName": indexName,
"KeyConditionExpression": "#dateID = :date_id",
"ExpressionAttributeNames": {"#dateID": "dateId"},
"ExpressionAttributeValues": {":date_id": dateID },
"ProjectionExpression": "Exercises",
"ScanIndexForward": true
};
docClient.query(params, (err, data) => {
if (err) {
console.error("Can't read item. Error JSON:", JSON.stringify(err, null, 2));
return reject(JSON.stringify(err, null, 2));
}
console.log("GetItem succeeded:", JSON.stringify(data, null, 2));
resolve(data.Items)
});
});
};
Related
Ihave some issues trying to find a index of an expecific product in a mongo database.
const cart = await this.model.findOne({ user: { $eq: user } });
if (cart) {
const itemFound = cart.products.findIndex(
(item) => item._id === new ObjectId(obj._id)
);
I'm sending the id from the frontend as a string and I transform it with the new ObjectId, the issue is it gives me -1, when I console log the item._id and new ObjectId(obj._id). Are the same but I dont know why it gives me -1.
this is the whole fuction I want to do:
async editCart(obj, user) {
try {
const cart = await this.model.findOne({ user: { $eq: user } });
if (cart) {
const itemFound = cart.products.findIndex(
(item) => item._id === new ObjectId(obj._id)
);
if (itemFound !== -1) {
let product = cart.products[itemFound];
product.count += obj.count;
const saved = await cart.save();
return saved;
} else {
cart.products.push(obj);
const saved = await cart.save();
return saved;
}
} else {
const newCart = new this.model({
products: obj,
user: user,
});
const saved = await newCart.save();
return saved;
}
} catch (error) {
logger.error(`Error to edit cart ${error}`);
throw new Error(error);
}
}
If you find another way to do it I will be really greatfull
You can use .toString() when you want to compare to ObjectId values:
const itemFound = cart.products.findIndex(
(item) => item._id.toString() === obj._id.toString()
);
hi i wonder why i cannot retrieve an objectId from this json object even i can printout the stringify on console.
I can retrieve all other column with no problem but not objectId. It happen to all table in my back4app Parse server.
i need the objectId in order to update certain column in my program
below is my code
1)
const parseQuery = new Parse.Query("User");
parseQuery.equalTo("username", "Azha");
let queryResult = await parseQuery
.find()
.then((results) => {
results.forEach((prod) => {
//if i change below to prod.get("objectId") error undefined appear
console.log("Product ID Available : " + prod.get("username"));
});
})
.catch((error) => {
console.log(error);
});
const parseQuery = new Parse.Query("User");
parseQuery.equalTo("username", "Azha");
try {
let todos = await parseQuery.find();
if (todos.length > 0) {
//if i change below to todos[0].get("objectId") error undefined appear
console.log("yes Approval : " + todos[0].get("companyname"));
} else {
console.log("No Approval");
}
console.log("- value is : " + JSON.stringify(todos));
console.log("----------------------");
} catch (error) {
Alert.alert("Error!", error.message);
}
below is the json printout
[{"sessionToken":"r:d9166aa9d7143463c46725d095b53946","username":"Azha","createdAt":"2021-09-21T15:27:01.088Z","updatedAt":"2021-10-10T13:01:27.126Z","companyname":"XXX","fullname":"XXX","email":"azha#abc.com.my","emailVerified":true,"accesslevel":"Maintenence","companydivision":"Maintenence","position":"Technician","phonenumber":"999","userteam":"B","useremail":"azha#abc.com.my","ACL":{"*":{"read":true},"IuBGmCtxyu":{"read":true,"write":true}},"objectId":"IuBGmCtxyu"}]
Yes i just found my solution. Using object1 below:
const parseQuery = new Parse.Query("User");
parseQuery.equalTo("username", "Azha");
try {
let todos = await parseQuery.find();
var object1 = JSON.parse(JSON.stringify(todos));
console.log("2- value is : " + object1[0].objectId);
} catch (error) {
Alert.alert("Error!", error.message);
}
I am new to the parse platform and i'm trying to insert 81000 rows of data in to the Parse DB, here the code
const uri = "/the.json"
const res = await axios.get(uri)
const dataresult = Object.keys(res.data)
if (dataresult.length > 0) {
res.data.forEach(function (datakp) {
var kp = new Parse.Object("theClass");
kp.save(datakp)
.then((res) => {
console.log('oke ' + res.id)
}),
(error) => {
console.log('err : '+ error.message)
}
})
}
There is no error in console log, and no data is saved in Parse DB, but if I only insert 1000 rows, it will save to the database.
EG:
if (dataresult.length > 0) {
res.data.forEach(function (datakp, index) {
if (index < 1000) {
var kp = new Parse.Object("theClass");
kp.save(datakp)
.then((res) => {
console.log('oke ' + res.id)
}),
(error) => {
console.log('err : '+ error.message)
}
})
}
}
Thank You
UPDATE
I fix this case based on answer #davi-macĂȘdo
here a complete code
const uri = "/the.json"
const res = await axios.get(uri)
const dataresult = Object.keys(res.data)
const objs = [];
const theKP = Parse.Object.extend("theClass")
if (dataresult.length > 0) {
res.data.forEach(function (datakp) {
var thekp = new theKP()
thekp.set(datakp)
objs.push(thekp);
})
}
Parse.Object.saveAll(objs)
.then((res) => {
console.log('oke updated ' + dataresult.length)
}),
(error) => {
console.log('err : '+ error.message)
}
The most efficient way is using Parse.Object.saveAll function. Something like this:
const uri = "/the.json"
const res = await axios.get(uri)
const dataresult = Object.keys(res.data)
const objs = [];
if (dataresult.length > 0) {
res.data.forEach(function (datakp) {
objs.push(new Parse.Object("theClass", datakp));
})
}
Parse.Object.saveAll(objs)
.then((res) => {
console.log('oke ' + res.id)
}),
(error) => {
console.log('err : '+ error.message)
}
Anyways, since you have no error and no data currently being saved, you might be kitting some memory limit. So that's something you also need to be aware about.
You're probably hitting rate limits, I can't imagine saving 81,000 records in one shot is normal behaviour for many applications.
I looked through the documentation and couldn't find anything that might mention a save limit, however sending 1000 requests would trigger most rate limit protection
I am trying to update quantity and price in cart.json.
addProduct(id) {
// Fetch the previous cart
fs.readFile(p, (err, fileContent) => {
let cart = [];
if (!err) {
cart = JSON.parse(fileContent);
}
// Analyze the cart => Find existing product
const existingProduct = cart.find((prod) => prod.id === id);
const existingProductIndex = cart.findIndex((prod) => prod.id === id);
if (existingProduct) {
cart[existingProductIndex].quantity = (parseFloat(cart[existingProductIndex].quantity) + 1).toString();
cart[existingProductIndex].price = (parseFloat(this.price) * parseFloat(cart[existingProductIndex].quantity)).toString();
} else {
// Add new product
cart.push(this);
}
fs.writeFile(p, JSON.stringify(cart, null, 2), (err) => {
console.log(err);
});
});
}
in cart.json file
[
{
"id": "ee195a4a-4870-4067-af50-c53c1d8f9594",
"title": "Love",
"imageUrl": "...",
"price": "39.98",
"description": "Love the way you lie",
"quantity": "2"
}
]
This is the code I wrote in cartModel.js and it working fine as I expected. But I don't think it's a good code.
Can you guys give me more beautiful code solution?
Actually, the way to add changes in the JSON file is a reading file, adding the changes, and writing a file. In your code, you can add some optimizations like this
addProduct(id) {
// Fetch the previous cart
fs.readFile(p, (err, fileContent) => {
if (err) throw new Error(err.message);
const cart = JSON.parse(fileContent);
// Analyze the cart => Find existing product index
const existingProductIndex = cart.findIndex((prod) => prod.id === id);
if (existingProductIndex >= 0) {
const existingProduct = cart[existingProductIndex];
existingProduct.quantity = (
parseFloat(existingProduct.quantity) + 1
).toString();
existingProduct.price = (
parseFloat(this.price) * parseFloat(existingProduct.quantity)
).toFixed(2);
} else {
// Add new product
cart.push(this);
}
fs.writeFile(p, JSON.stringify(cart, null, 2), (err) => {
if (err) throw new Error(err.message);
});
});
}
You don't need to find a product twice. findIndex will return an index of the product if it exists (for example 0, 1, 34 ....), or -1 if it does not. Also, I suggest using the toFixed function, because the number can be like 12.123232523 so it will be shown as 12.12 if you are using toFixed(2). Also, toFixed converting the number to a string, so you don't need to use toString() for the price.
I want to update a globally declared variable after sqlite query,
but I cant get it to work,
I have read that it might be related to asynchronous functions but I have no idea how to implement callbacks and stuff in this example,
can you guys help please. Here is the code:
const sqlite3 = require('sqlite3').verbose();
const dbPath = './src/db/db.sqlite3';
let db = new sqlite3.Database(dbPath, (err) => {
if (err) {
console.error(err.message);
}
console.log('Connected to database.');
});
let number = null;
let rowsExist = null;
db.get("select count(*) from PRICE", [], (err, row) => {
if (err) {
console.error(err.message)
}
else {
rowsExist = Object.values(row)[0];
console.log(rowExist) //this works but outside the function it doesnt get updated
}
});
// here rowExist remains the same after query
if (rowsExist === null) {
number = 1
}
else {
db.get("SELECT number FROM PRICE ORDER BY number DESC LIMIT 1", [], (err, row) => {
if (err) {
console.error(err.message)
}
else {
number = Object.values(row)[0] + 1
}
})
};