Creating a dynamodb table using Lambda function (python) - error - aws-lambda

I have defined 3 attributes in that table definition. agentId, agentName, agentRole. I want to create KeySchema on agentId (partitionkey) , agentRole (range key).
In my understanding the table can have 10 attributes. All those 10 attributes don't have to be part of the KeySchema. Because Keyschema is used to identify unique records. Right?
It throws the following error:
Response
{
"errorMessage": "An error occurred (ValidationException) when calling the
CreateTable operation: One or more parameter values were invalid: Number of attributes in
KeySchema does not exactly match number of attributes defined in AttributeDefinitions",
"errorType": "ClientError",
"requestId": "d8d07c59-f36c-4989-9ac2-6ada9d8f6521",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 8, in lambda_handler\n
response = client.create_table(\n",
" File \"/var/runtime/botocore/client.py\", line 391, in _api_call\n return
self._make_api_call(operation_name, kwargs)\n",
" File \"/var/runtime/botocore/client.py\", line 719, in _make_api_call\n
raise error_class(parsed_response, operation_name)\n"
]
}
import json
import boto3
client = boto3.client("dynamodb")
def lambda_handler(event, context):
response = client.create_table(
AttributeDefinitions=[
{
'AttributeName': 'agentId',
'AttributeType': 'N'
},
{
'AttributeName': 'agentRole',
'AttributeType': 'S'
},
{
'AttributeName': 'agentName',
'AttributeType': 'S'
}
],
TableName='CallCenterCallsTable,
KeySchema=[
{
'AttributeName': 'agentId',
'KeyType': 'HASH'
},
{
'AttributeName': 'agentRole',
'KeyType': 'RANGE'
}
],
BillingMode='PROVISIONED',
ProvisionedThroughput={
'ReadCapacityUnits': 1,
'WriteCapacityUnits': 1
}
)
print(response)

Remove agentName from the Attribute definitions.
See the documentation for Attribute Definitions:
Represents an attribute for describing the key schema for the table and indexes.
You aren't using agentName in the key schema or indexes, so it shouldn't be included in the table definition. DynamoDB is schemaless. You only need to define the hash key and sort key at creation time. DynamoDB doesn't care about any other attributes you may want to insert into your table.

Related

get_item in Lambda to read one item from dynamodb table having issues

I have a simple table with agentId (PK) and agentRole(SK). I am trying read one item from that table. Using boto3 client
I am getting syntax error on print statement.
import json
import boto3
client = boto3.client('dynamodb')
def lambda_handler(event, context):
response = client.get_item(
TableName='USBCallCenterTable',
Key={
'agentId': {
'N': str(1)
},
'agentRole':{
'S': 'Manager'
}
}
)
print(response)
"errorMessage": "name 'response' is not defined",
"errorType": "NameError",
"requestId": "",
Print is not an argument of get_item. Try to put the print outside get_item. I think it should solve the problem.

Returning a Float in Graphene after querying DB

I am using some example code to return a list of fields and all is working for my Data Models. However I want to take an input, query the db, do a calculation and return a single number back. Everything works, bar getting the output to the end user.
class Query(graphene.ObjectType):
growth = graphene.Float(id=graphene.String())
def resolve_growth(self, info, id):
records = list(Model.objects.filter(id=id).order_by('date'))
## do calculation
return calculation
I get the following message in GraphiQL
{
"errors": [
{
"message": "Field \"growth\" of type \"Float\" must not have a sub selection.",
"locations": [
{
"line": 1,
"column": 32
}
]
}
]
}
I am making the following query on the client side using graphiQL:
{growth(id: "AAN") }
but this gets morphed into by the front end:
{growth(id: "AAN") {
id
} }
In the end I solved this by returning an Object.

How to add a json in a nested array of a mongodb document using Spring?

Document stored in mongodb:
{
"CNF_SERVICE_ID":"1",
"SERVICE_CATEGORY":"COMMON_SERVICE",
"SERVICES":[{
"SERVICE_NAME":"Authentication Service",
"VERSIONS":[{
"VERSION_NAME":"AuthenticationServiceV6_3",
"VERSION_NUMBER":"2",
"VERSION_NOTES":"test",
"RELEASE_DATE":"21-02-2020",
"OBSOLETE_DATE":"21-02-2020",
"STATUS":"Y",
"GROUPS":[{
"GROUP_NAME":"TEST GROUP",
"CREATED_DATE":"",
"NODE_NAMES":[
""
],
"CUSTOMERS":[{
"CUSTOMER_CONFIG_ID":"4",
"ACTIVATION_DATE":"21-02-2020",
"DEACTIVATION_DATE":"21-02-2020",
"STATUS":"Y"
}]
}]
}]
}
]
}
Now, I need to add another customer json to the array "CUSTOMERS" inside "GROUPS" in the same document above. The customer json would be like this:
{
"CUSTOMER_CONFIG_ID":"10",
"ACTIVATION_DATE":"16-03-2020",
"DEACTIVATION_DATE":"16-03-2021",
"STATUS":"Y"
}
I tried this:
Update update = new Update().push("SERVICES.$.VERSIONS.GROUPS.CUSTOMERS",customerdto);
mongoOperations.update(query, update, Myclass.class, "mycollection");
But, I am getting the exception: org.springframework.data.mongodb.UncategorizedMongoDbException: Command failed with error 28 (PathNotViable): 'Cannot create field 'GROUPS' in element
[ EDIT ADD ]
I was able to update it using the filtered positional operator. Below is the query I used:
update(
{ "SERVICE_CATEGORY":"COMMON_SERVICE", "SERVICES.SERVICE_NAME":"Authentication Service", "SERVICES.VERSIONS.VERSION_NAME":"AuthenticationServiceV6_3"},
{ $push:{"SERVICES.$[].VERSIONS.$[].GROUPS.$[].CUSTOMERS": { "CUSTOMER_CONFIG_ID":"6", "ACTIVATION_DATE":"31-03-2020", "STATUS":"Y" } } }
);
Actually, this query updated all the fields irrespective of the filter conditions. So. I tried this but I am facing syntax exception. Please help.
update(
{"SERVICE_CATEGORY":"COMMON_SERVICE"},
{"SERVICES.SERVICE_NAME":"Authentication Service"},
{"SERVICES.VERSIONS.VERSION_NAME":"AuthenticationServiceV6_3"}
{
$push:{"SERVICES.$[service].VERSIONS.$[version].GROUPS.$[group].CUSTOMERS":{
"CUSTOMER_CONFIG_ID":"6",
"ACTIVATION_DATE":"31-03-2020",
"STATUS":"Y"
}
}
},
{
multi: true,
arrayFilters: [ { $and:[{ "version.VERSION_NAME": "AuthenticationServiceV6_3"},{"service.SERVICE_NAME":"Authentication Service"},{"group.GROUP_NAME":"TEST GROUP"}]} ]
}
);
Update: April 1,2020
The code I tried:
validationquery.addCriteria(Criteria.where("SERVICE_CATEGORY").is(servicedto.getService_category()).and("SERVICES.SERVICE_NAME").is(servicedetail.getService_name()).and("SERVICES.VERSIONS.VERSION_NAME").is(version.getVersion_name()));
Update update=new Update().push("SERVICES.$[s].VERSIONS.$[v].GROUPS.$[].CUSTOMERS", customer).filterArray(Criteria.where("SERVICE_CATEGORY").is(servicedto.getService_category()).and("s.SERVICE_NAME").is(servicedetail.getService_name()).and("v.VERSION_NAME").is(version.getVersion_name()));
mongoOperations.updateMulti(validationquery, update, ServiceRegistrationDTO.class, collection, key,env);
The below exception is thrown:
ERROR com.sample.amt.mongoTemplate.MongoOperations - Exception in count(query, collectionName,key,env) :: org.springframework.dao.DataIntegrityViolationException: Error parsing array filter :: caused by :: Expected a single top-level field name, found 'SERVICE_CATEGORY' and 's'; nested exception is com.mongodb.MongoWriteException: Error parsing array filter :: caused by :: Expected a single top-level field name, found 'SERVICE_CATEGORY' and 's'
This update query adds the JSON to the nested array, "SERVICES.VERSIONS.GROUPS.CUSTOMERS", based upon the specified filter conditions. Note that your filter conditions direct the update operation to the specific array (of the nested arrays).
// JSON document to be added to the CUSTOMERS array
new_cust = {
"CUSTOMER_CONFIG_ID": "6",
"ACTIVATION_DATE": "31-03-2020",
"STATUS": "Y"
}
db.collection.update(
{
"SERVICE_CATEGORY": "COMMON_SERVICE",
"SERVICES.SERVICE_NAME": "Authentication Service",
"SERVICES.VERSIONS.VERSION_NAME": "AuthenticationServiceV6_3"
},
{
$push: { "SERVICES.$[s].VERSIONS.$[v].GROUPS.$[g].CUSTOMERS": new_cust }
},
{
multi: true,
arrayFilters: [
{ "s.SERVICE_NAME": "Authentication Service" },
{ "v.VERSION_NAME": "AuthenticationServiceV6_3" },
{ "g.GROUP_NAME": "TEST GROUP" }
]
}
);
Few things to note when updating documents with nested arrays of more than one level nesting.
Use the all positional operator $[] and the filtered positional
operator $[<identifier>], and not the $ positional operator.
With filtered positional operator specify the array filter conditions
using the arrayFilters parameter. Note that this will direct your update to target the specific nested array.
For the filtered positional operator $[<identifier>], the
identifier must begin with a lowercase letter and contain only
alphanumeric characters.
References:
Array Update
Operators
db.collection.update() with arrayFilters
Thanks to #prasad_ for providing the query. I was able to eventually convert the query successfully to code with Spring data MongoTemplate's updateMulti method. I have posted the code below:
Query validationquery = new Query();
validationquery.addCriteria(Criteria.where("SERVICE_CATEGORY").is(servicedto.getService_category()).and("SERVICES.SERVICE_NAME").is(servicedetail.getService_name()).and("SERVICES.VERSIONS.VERSION_NAME").is(version.getVersion_name()));
Update update=new Update().push("SERVICES.$[s].VERSIONS.$[v].GROUPS.$[].CUSTOMERS", customer).filterArray(Criteria.where("s.SERVICE_NAME").is(servicedetail.getService_name())).filterArray(Criteria.where("v.VERSION_NAME").is(version.getVersion_name()));
mongoOperations.updateMulti(validationquery, update, ServiceRegistrationDTO.class, collection, key,env);
mongoTemplateobj.updateMulti(validationquery, update, ServiceRegistrationDTO.class, collection, key,env);

How can I create a relationship between `json` column and a `int` (id) column in Hasura + Postgres?

I have 2 tables users and post
Table users has columns id and post, column contains an array of the form [1, 2, 3, 4, 5] - where 1, 2, 3, 4, 5 is id in table post
In the table posts the following columns id and text
Table users:
https://i.stack.imgur.com/ywdS7.png
Table posts:
https://i.stack.imgur.com/IBdpb.png
in hasura made an array relation
https://i.stack.imgur.com/311sd.png
Next I made the following request
{
users_test {
postz {
id
}
}
}
I would like to receive such data in response:
postz: [
   {
     text: 'qwe'
   },
   {
     text: 'sdf'
   }
]
But with such a request, I get a trace. error:
{
"errors": [
{
"extensions": {
"internal": {
"statement": "SELECT coalesce(json_agg(\"root\" ), '[]' ) AS \"root\" FROM (SELECT row_to_json((SELECT \"_5_e\" FROM (SELECT \"_4_root.ar.root.postz\".\"postz\" AS \"postz\" ) AS \"_5_e\" ) ) AS \"root\" FROM (SELECT * FROM \"public\".\"users_test\" WHERE ('true') ) AS \"_0_root.base\" LEFT OUTER JOIN LATERAL (SELECT coalesce(json_agg(\"postz\" ), '[]' ) AS \"postz\" FROM (SELECT row_to_json((SELECT \"_2_e\" FROM (SELECT \"_1_root.ar.root.postz.base\".\"id\" AS \"id\" ) AS \"_2_e\" ) ) AS \"postz\" FROM (SELECT * FROM \"public\".\"posts\" WHERE ((\"_0_root.base\".\"post\") = (\"id\")) ) AS \"_1_root.ar.root.postz.base\" ) AS \"_3_root.ar.root.postz\" ) AS \"_4_root.ar.root.postz\" ON ('true') ) AS \"_6_root\" ",
"prepared": true,
"error": {
"exec_status": "FatalError",
"hint": "No operator matches the given name and argument type(s). You might need to add explicit type casts.",
"message": "operator does not exist: json = integer",
"status_code": "42883",
"description": null
},
"arguments": [
"(Oid 114,Just (\"{\\\"x-hasura-role\\\":\\\"admin\\\"}\",Binary))"
]
},
"path": "$",
"code": "unexpected"
},
"message": "postgres query error"
}
]
}
What am I doing wrong and how can I fix it?
A few suggestions:
There are some typos in your query, as far as I can tell. Try:
{
users {
id
posts {
text
}
}
}
You don't need the post column on the users table. You just need a user_id column on the posts table, and a foreign key constraint from the posts table to the users table using the user_id and id columns of the tables respectively. Check out the docs here:
https://docs.hasura.io/1.0/graphql/manual/schema/relationships/create.html#step-3-create-an-array-relationship
https://docs.hasura.io/1.0/graphql/manual/schema/relationships/database-modelling/one-to-many.html
If you have to have the post array column for some reason, you can use computed fields to create a "relationship" between a json array and another table’s id.
https://docs.hasura.io/1.0/graphql/manual/schema/computed-fields.html#table-computed-fields
Your function would:
Take in the json array column
Extract the id's
Return select * from table where id in id's
Example:
https://jsonb-relationships-hasura.herokuapp.com/console/api-explorer
Computed field definition at: https://jsonb-relationships-hasura.herokuapp.com/console/data/schema/public/tables/authors/modify
Run these queries:
# Get list of articles for each author
query {
authors {
id
name
articles
}
}
# Get actual articles for each author
query {
authors {
id
name
owned_articles {
id
title
}
}
}

I can only query with primary keys in GraphQL on Appync?

This problem is boggling my mind.
I'm trying to query an RDS table with a non-primary key inside a graphql query.
Here is the example of two of my queries in appsync
query getloc{
getLocationByCounty(County: "County"){
LocationsID
State
County
}
}
query getLocations{
getLocation(LocationsID: 1){
LocationsID
State
County
}
}
The second query here works, and returns exactly the county with that LocationID.
The first returns the error message: "Cannot return null for non-nullable type: 'Int' within parent 'Locations' (/getLocationByCounty/LocationsID)"
If I change the schema for locations and make LocationsID non-nullable the error goes away, but it
returns null.
{
"data": {
"getLocationByCounty": {
"State": null
}
}
}
My request resolver for the getLocationsByCounty is:
"version": "2018-05-29",
"statements": ["select * from Locations where County = '$ctx.args.County'"]
Here is the response resolver:
## Raise a GraphQL field error in case of a datasource invocation error
#if($ctx.error)
$utils.error($ctx.error.message, $ctx.error.type)
#end
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0])
Is this just not allowed in graphQL or is am I doing wrong???
It's worth noting that if I just do this query:
select * from Locations where County = 'County'
in mySQL, it works exactly as intended.

Resources