Update multiple fields at once with QLDB Node.js driver - node.js

I'm trying to implement an API endpoint that handles PATCH or PUT requests, updating the relevant QLDB document with the request payload. I'm trying the following, but it doesn't seem to work:
await driver.executeLambda(async (txn) => {
await txn.execute(
`UPDATE People AS p BY p_id SET ? WHERE p_id = ?`,
requestPayload,
documentId,
);
});
The error I get is:
BadRequestException: Parser Error: at line 1, column 32: Invalid path component, expecting either an IDENTIFIER or STAR, got: QUESTION_MARK with value:
1; Expected identifier for simple path
(I have confirmed that the QLDB statement UPDATE People AS p BY p_id SET p.name = 'John Doe' WHERE p_id = '<document_id>', run in the QLDB web console, does in fact work as desired. I've also confirmed that the values of my variables are as I'd expect -- the first is an object and the second is a string.)
Is this kind of updating not supported by the QLDB Node.js driver?

It looks like your query is missing the field name in the parameterization. It should be SET p.name = ?:
UPDATE People AS p BY p_id SET p.name = ? WHERE p.p_id = ?

Related

How to bind array to IN condition with Node postgres

I'm struggling to figure out of to bind an array to an IN query in node pg library.
const env = 'foo';
const sourceTypes = ['one', 'two'];
const resp = await pool.query(
`SELECT source_id, target_id FROM records
WHERE target_env = $1
AND source_type IN ($2)`,
[env, sourceTypes],
);
I've tried several variations and they either error out or don't return any data.
I can make the query when I just use when I manually bind to generate something like this:
SELECT source_id, target_id FROM records
WHERE target_env = 'foo'
AND source_type IN ('one', 'two')
PS: If can provide suggestion on how to actually see the SQL request that PG is generating, that would be extremely helpful!
You can't bind an array to multiple elements of a list in one go. But you can use an array instead of a list by changing in ($2) to =ANY($2)
You can see what queries are getting sent by setting log_statement=all and then viewing the PostgreSQL log file.

Azure CosmosDB/Nodejs - Entity with the specified id does not exist in the system

I am trying to delete and update records in cosmosDB using my graphql/nodejs code and getting error - "Entity with the specified id does not exist in the system". Here is my code
deleteRecord: async (root, id) => {
const { resource: result } = await container.item(id.id, key).delete();
console.log(`Deleted item with id: ${id}`);
},
Somehow below code is not able to find record, even "container.item(id.id, key).read()" doesn't work.
await container.item(id.id, key)
But if I try to find record using query spec it works
await container.items.query('SELECT * from c where c.id = "'+id+'"' ).fetchNext()
FYI- I am able to fetch all records and create new item, so Connection to DB and reading/writing is not an issue.
What else can it be? Any pointer related to this will be helpful.
Thanks in advance.
It seems you pass the wrong key to item(id,key). According to the Note of this documentation:
In both the "update" and "delete" methods, the item has to be selected
from the database by calling container.item(). The two parameters
passed in are the id of the item and the item's partition key. In this
case, the parition key is the value of the "category" field.
So you need to pass the value of your partition key, not your partition key path.
For example, if you have document like below, and your partition key is '/category', you need to use this code await container.item("xxxxxx", "movie").
{
"id":"xxxxxx",
"category":"movie"
}

How to pass date as an input to SQL Server query in node

I am using node-mssql and my function goes like this:
const getPoliciesDue = async (userId, toDate) => {
const db = await sql.connect(config) // const sql = require('mssql'), config = {config for my DB}
const request = db.request()
.input('userId', sql.VarChar, userId) // userId is a string
.input('toDate', sql.Date, toDate) // toDate is a javascript Date() object
const result = await request.query(
'SELECT policyNumber, holderId, ... FROM Policies WHERE Policies.userId = #userId AND Policies.toDate <= #toDate'
)
return result.recordset
}
I want to get all the policies which are expiring before a certain date belonging to a certain user.
But when I run this exact query, I get the error
Must declare the scalar variable #userId
I removed #userId from the WHERE clause and put '#toDate' (quotes around the variable). Now I get an error
Conversion failed when converting date and/or time from character string
The documentation says input() accepts the Date() object. I have tried passing date object as well as a string in YYYY-MM-DD format, but with no avail. Passing a string in YYYY-MM-DD format works for an INSERT query, but not for a SELECT query. How am I supposed to run my query?
Note I can't run the query in a single line, like
db.request().input().query()
because there is another input which will later go in conditionally.
Okay, a huge oversight on my part and sincere apologies to those who tried to find an answer. I found out that I was running the query() method on the wrong object. I was running the query method on db object whereas I should have run it on the request object. The code works perfectly after calling the method on the right object.

Updating specific MongoDB document based on ID passed in from pug-based express route

I'm attempting to update a single row of a table within a pug page. The rows of this table are populated from MongoDB. The cells of these table rows are populated using document data e.g. doc.name, while the actual table row contains the document's ID e.g. doc._id.
tr(id = doc._id)
form.hidden(method = "patch", action = "../update" + doc._id)
td button.btn(type = "submit") Update
td
input(name = "name", value = "doc.name")
td
input(name = "age", value = "doc.age")
The route for this operation is shown below:
router.patch("../update/:id", Controller.update)
The controller's update function is:
exports.update = (req, res, next) => {
const id = req.params.id;
const operations = {};
for(const task of req.body){
operations[task.propName] = task.value;
}
Feature.update({_id: id}, {$set: operations})
.exec()
.then(
res.status(200)
)
.catch(
res.status(500)
)
}
I'm able to enter and submit the change, then pass the URL back through an Express route ../update/:id so that the request equals GET ../update/testID123?name=testName&age=42 404. I understand that this means the ID can't be found, but I'm perplexed as to why not? It was my understanding that the last section of the URL was represented as req.params and anything after ? was the req.body?
However, when I conduct the identical request using a defined PATCH request via Postman, I receive a different error mentioning that req.body is not iterable, but I don't understand how to force differentiation between the auto-selected GET request and the desired PATCH request. It's worth noting that I've already followed the path to the "not iterable" error as outlaid in this post, so I don't think this is the real problem.
It's the end of the day and my brain has turned to mush, so apologies for missing out any key details, and thanks for reading.
Found the answer thanks to advice given in this post. I was accessing aspects of an object that didn't exist, in a manner that wasn't suitable for iteration as outlaid in the linked post. I was wrong in thinking that the req.body not iterable error was a red herring, so I re-implemented the task of Object.keys(req.body) loop and instead of appending [task.propName] = task.value to the updateOperations array, I had to implement [task] = req.body[task].

"Missing required key 'Key' in params" in Get operation of Dynamo dB

I am writing Lambda function in node.js to getitems from dynamodB. Table is employee where emo_Id is the Partition key. Below is the code snippet I am writing:
var table = "Employee_Test";
var emp_Id=event.emp_Id;
var emp_Name=event.emp_Name;
var params = {
TableName: table,
KeyConditionExpression: "#eId = :Id",
ExpressionAttributeNames:{
"#eId": "emp_Id"
},
ExpressionAttributeValues: {
":Id":emp_Id
}}
The error I am getting is :
"message": "Missing required key 'Key' in params",
"code": "MissingRequiredParameter",
I know the resolution of the error is to add:
Key:{
"emp_Id": emp_Id,
} to the code. But If I have to query the employees who have joined after a particular date then I cannot provide emp_Id as a parameter.
In the AWS release notes I have found that we can disable parameter validation,
https://aws.amazon.com/releasenotes/6967335344676381 I tried this but this is also not working.
Can somebody please help?
Thanks
Shweta
I was hit with a same error when querying the secondary indexes. Turns out that I was using the wrong API. Confused between getItem and Query.
I ran into this when I first started with DynamoDb. Such an annoying error. Turns out I had accidentally used the .get method, from a previous working getById example, instead of the .query method.
In short, you may just need to change this ...
const response = await db.get(query).promise();
... to this ...
const response = await db.query(query).promise();
Add a Global Secondary Index to your table to enable lookups by start date. First, change your item creation code (PutItem) to add an attribute representing the month and year an employee joined, like joinYearMonth=201612. Second, scan your table to find items that do not already have this attribute and add it. Third, create a Global Secondary Index with a partition key of joinYearMonth and a sort key of joinTimestamp. This way, you can issue query requests on the GSI for the years and months you require to find those that joined.

Resources