How to return the Primary Key of the newly inserted row using asyncpg? - asyncpg

I wanted to do something like this:
async with app.pg_pool.acquire() as pg:
uid = await pg.execute('INSERT INTO users (created, keyed, key, email) '
'VALUES ($1, $2, $3, $4) RETURNING id',
time, time, key, rj['email'])['id']
However Connection.execute doesn't seem to return anything other than the status:
https://magicstack.github.io/asyncpg/current/api/index.html?highlight=returning#asyncpg.connection.Connection.execute
The question could be otherwise phrased as: How do I get back the response of the RETURNING statement when using asyncpg?

Simply use Connection.fetchval() instead of execute().

The Connection.execute will return the status of the INSERT. If you need the Record, Records or Value use one of the following instead of Connection.execute :
Connection.fetchval - returns only the value of one field specified. Returns null if no fields are specified.
Connection.fetch - will return an array of dict. Each dict will have the list of fields specified after the RETURNING statement.
Connection.fetchrow - will return a dict with the list of fields specified after the RETURNING statement

Related

Get all collection result if null value appears in match filter in mongoose

Really don't know how to describe my problem. I tried my best. I have a collection and I want anyone to search through multiple parameters. I used the $match filter for this. here is my code.
db.product.aggregate([{$match:{lastStatus:req.query.status,name:req.query.name}}])
This is working fine. but I am taking the match values from the user via API and there is a chance that the user didn't pass these values, in that case, I return the products based on the applied match. suppose the user only passes the name, then the result comes on the basis of the name, not on lastStatus. right now this query does not work if any of the provided values is empty or undefined.
what can be the solutions
You can check the condition if any of the field has value then set the value in the match variable.
let match = {};
// MATCH STATUS
if (req.query.status) match["lastStatus"] = req.query.status;
// MATCH NAME
if (req.query.name && req.query.name.trim() != "") match["name"] = req.query.name.trim();
db.product.aggregate([{ $match: match }]);

Trying to check if value is in sqlite3 with Python

I am trying to check if a value is in SQLite with python to then either update the table if the value exists or create a new value if it is not. I have tried to create a cursor to check rows, append the rows to a list with loop, check if value exists, check the count of the rows... I seems to get hung up on the if statement when trying to access the value initialized from the query. Here is the code:
checkT = db.execute("SELECT COUNT(*) FROM trans WHERE stock=:stock AND id=:user_id", stock=request.form.get("symbol"), user_id=session["user_id"])
if checkT > 0:
print("there")
else:
print("not there")
How can I fix this? Thank you!
From the CS50 Library for Python doc for execute
Returns
for SELECTs, a list of dict objects, each of which represents a row in the result set; for INSERTs, the primary key of a newly inserted row (or None if none); for UPDATEs, the number of rows updated; for DELETEs, the number of rows deleted; for CREATEs, True on success; on error, a RuntimeError is raised
checkT is a list with one element, which is a dict with one key/value pair.
This checkT[0]['COUNT(*)'] will give the number returned from the sql. Counting the rows would not be appropriate in this case because this query will always return one row.
One hint: column names in a SELECT can be aliased, given a different name, like so:
SELECT COUNT(*) as count from....... It would just be typing convenience, because then the key in the returned dict will be count instead of COUNT(*).
Remember: in the flask run terminal there is a traceback with gives more details information on the error received (assuming "hung up" means a 500 Internal Server Error).

UPSERT syntax error linked to UPDATE in PostgreSQL (python)

I'm still learning PostgreSQL. During my testing, I have only been using INSERT statement in either psycopg2 and now asyncpg. I now have the need to UPDATE data in my test database, instead of replacing all of it.
I'm currently trying to do a simple replacement test in a testing table, before I move to development table with more data.
I want to replace any $1 name that is in CONFLICT with a name that is already in the table users. I'm trying the query code, which is passed to the DB via asyncpg. I keep getting a syntax errors, so I'm a little lost on how to correct these errors.
What is the proper syntax for this query?
'''INSERT INTO users(name, dob)
VALUES($1, $2)
ON CONFLICT (name)
DO
UPDATE "users"
SET name = 'TEST'
WHERE name = excluded.name '''
UPDATE:
I'm getting this error message when using asyncpg:
asyncpg.exceptions.PostgresSyntaxError: syntax error at or near ""users""
I'm getting this error message when using psycopg2:
psycopg2.ProgrammingError: syntax error at or near ""users""
This is the asyncpg code that I have been using to do the INSERTs:
async def insert_new_records(self, sql_command, data):
print (sql_command)
async with asyncpg.create_pool(**DB_CONN_INFO, command_timeout=60) as pool:
async with pool.acquire() as conn:
try:
stmt = await conn.prepare(sql_command)
async with conn.transaction():
for value in data:
async for item in stmt.cursor(*value):
pass
finally:
await pool.release(conn)
test_sql_command = '''
INSERT INTO users(name, dob)
VALUES($1, $2)
ON CONFLICT (name)
DO
UPDATE "users"
SET name = 'TEST'
WHERE name = excluded.name '''
# The name 'HELLO WORLD' exists in the table, but the other name does not.
params = [('HELLO WORLD', datetime.date(1984, 3, 1)),
('WORLD HELLO', datetime.date(1984, 3, 1))]
loop = asyncio.get_event_loop()
loop.run_until_complete(db.insert_new_records(test_sql_command, params))
You need single quotes around the value for name: SET name='TEST'
The double quotes are for table or column names. In your case, you could just remove the double quotes around users.
After edit:
You should really try your SQL commands in the database console, this has nothing to do with python nor async. It's pure postgresql syntax.
So, the second issue in your query is that you shouldn't specify "users" after UPDATE. It's implied that you're updating the same table. So just DO UPDATE SET... is good.
Then, you'll get column reference "name" is ambiguous. You should write DO UPDATE SET name='TEST'. You already are updating the row where name=excluded.name. I am not 100% clear on what you're trying to do. So if you insert a row once, it's inserted as usual. If you insert it a second time, the name is replaced with 'TEST'. The excluded keyword allows you to access the attempted insert values. So for example, if you wanted to update the last_access column when trying to insert an existing name, you would write ON CONFLICT (name) DO UPDATE last_access=excluded.last_access.
you can test
replace :
'''INSERT INTO users(name, dob)
VALUES($1, $2)
ON CONFLICT (name)
DO
UPDATE "users"
SET name = 'TEST'
WHERE name = excluded.name '''
by :
"""INSERT INTO users(name, dob)
VALUES($1, $2)
ON CONFLICT (name)
DO
UPDATE
SET name = 'TEST'
WHERE name = excluded.name """

Getting index of the resultset

Is there a way to get the index of the results within an aql query?
Something like
FOR user IN Users sort user.age DESC RETURN {id:user._id, order:{index?}}
If you want to enumerate the result set and store these numbers in an attribute order, then this is possible with the following AQL query:
LET sorted_ids = (
FOR user IN Users
SORT user.age DESC
RETURN user._key
)
FOR i IN 0..LENGTH(sorted_ids)-1
UPDATE sorted_ids[i] WITH { order: i+1 } IN Users
RETURN NEW
A subquery is used to sort users by age and return an array of document keys. Then a loop over a numeric range from the first to the last index of the that array is used to iterate over its elements, which gives you the desired order value (minus 1) as variable i. The current array element is a document key, which is used to update the user document with an order attribute.
Above query can be useful for a one-off computation of an order attribute. If your data changes a lot, then it will quickly become stale however, and you may want to move this to the client-side.
For a related discussion see AQL: Counter / enumerator
If I understand your question correctly - and feel free to correct me, this is what you're looking for:
FOR user IN Users
SORT user.age DESC
RETURN {
id: user._id,
order: user._key
}
The _key is the primary key in ArangoDB.
If however, you're looking for example data entered (in chronological order) then you will have to have to set the key on your inserts and/or create a date / time object and filter using that.
Edit:
Upon doing some research, I believe this link might be of use to you for AI the keys: https://www.arangodb.com/2013/03/auto-increment-values-in-arangodb/

Dynamodb querying for list count

I have a dynamodb table which has following columns,
id,name,events, deadline
events is a list which contain number of events.
I want to scan/query for all the rows with following items as the result,
id, name, number of events.
I tried following way but didn't receive any value for number of events. Can someone show me where am I wrong.
var params = {
TableName: 'table_name',
ExpressionAttributeNames: {"#name": "name",
"#even": "events.length"
},
ProjectionExpression: 'id, #name, #even'
}
You cannot achieve what you want in this way. The entries in "ExpressionAttributeNames" are not evaluated as expressions.
The definition of "#even": "events.length" in "ExpressionAttributeNames" does not evaluate the expression event.length and assign it to the variable "#even". Instead it specifies "#even" as referring to a column named "events.length" or a table where "events" is an object that has a "length" attribute. Since your table has neither, you get nothing back.
From the DynamoDB documentation:
In an expression, a dot (".") is interpreted as a separator character in a document path. However, DynamoDB also allows you to use a dot character as part of an attribute name.
To achieve what you want, you will have to return the "events" column and calculate the length outside of the query, or define a new "eventsLength" column and populate and maintain that value yourself if you are concerned about returning "events" in each query.

Resources