I am using AWS Dynamo DB and am facing an issue.
I have a table which has multiple columns (e.g. firstname, lastname and others). The primary key is an integer.
My requirement is that user can send in one or more search condition and I have fetch data based on this.
e.g. say a Table t1 which has columns Id, firstname, lastname
I am unable to search when user sends in only one search condition.
Below is code:
Table table = dynamoDB.getTable("t1");
Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":firstname", "aa");
expressionAttributeValues.put(":lastname", "bb");
ItemCollection<ScanOutcome> items = table.scan
("(firstname = :firstname) AND " +
"(lastname = :lastname)", // FilterExpression
null, // ProjectionExpression
null, // No ExpressionAttributeNames
expressionAttributeValues);
When I send both firstname and lastname as input then the above code works fine.
However if I send in only firstname then the code fails as the lastname input is not being sent.
One crude way to solve this if I make the FilterExpression programatically. I want to know if dynamodb query has inbuilt support for such scenario.
I searched a lot but could not find anything useful.
Related
I have a dynamodb table on which a GSI is defined with a partition key and sort key.
Let's say the parition key is name and sort key is ssn for the GSI.
I have to fetch based upon a name and ssn, below is the query I am using and it works fine.
table.query(IndexName='lookup-by-name',KeyConditionExpression=Key('name').eq(name)\
& Key('ssn').eq(ssn))
Now, I have to query based upon a name and a list of ssns.
For Example
ssns=['ssn1','ss2','ss3',ssn4']
name='Alex'
query all records which has name as 'Alex' and whose ssn is present in ssns list.
How do I implement something like this ?
While DynamoDB native SDK cannot provide the functionality to do this, you can achieve it using PartiQL which provides a SQL like interface for interacting with DynamoDB.
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-gettingstarted.html
import boto3
client = boto3.client('dynamodb', region_name="eu-west-1")
name = 'Alex'
ssns = ['ssn1','ssn2','ssn3','ssn4']
response = client.execute_statement(
Statement = "Select * from \"MyTableTest\".\"lookup-by-name\" where \"name\" = '%s' AND \"ssn\" IN %s" % (name, ssns)
)
print(response['Items'])
It would also require you to use the lower level Client instead of the Table level resource which you are using above.
You would have to do multiple queries.
Ended up using just the name as keycondition and then filter out the ssn in python code.
Below worked for me as the number of records was not a lot.
response=table.query(IndexName='lookup-by-name',KeyConditionExpression=Key('name').eq(name)
ssns=['ssn1','ss2','ss3',ssn4']
data= response['Items']
data=list(filter(lambda record: record['ssn'] in ssns,data))
return data
I've recently started learning DynamoDB and created a table 'Communication' with the following attributes (along with the DynamoDB type):
Primary Key Communication ID (randomly generated seq # or UUID): String
Sort Key User ID: String
Attributes/Columns:
Communication_Mode: String
Communication_Channel: String
Communication_Preference: String (possible values Y/N)
DateTime: Number
Use case: User can choose not to be communicated (Communication_Preference: N) and after a month user may opt for it (Communication_Preference: Y); meaning for the same User ID there can be more than 1 record as PartitionKey is randomly generated number
If I have to query above table and retrieve last inserted record for a specific userid do I need to create Global Secondary Index on DateTime.
Can someone correct me if my understanding is wrong or propose me the best option to meet above requirement. Thanks!
I've a table "City" with more than 100k records.
The field "name" contains strings like "Roma", "La Valletta".
I receive a file with the city name, all in upper case as in "ROMA".
I need to get the id of the record that contains "Roma" when I search for "ROMA".
In SQL, I must do something like:
select id from city where upper(name) = upper(%name%)
How can I do this in kettle?
Note: if the city is not found, I use an Insert/update field to create it, so I must avoid duplicates generated by case-sensitive names.
You can make use of the String Operations steps in Pentaho Kettle. Set the Lower/Upper option to Y
Pass the city (name) from the City table to the String operations steps which will do the Upper case of your data stream i.e. city name. Join/lookup with the received file and get the required id.
More on String Operations step in pentaho wiki.
You can use a 'Database join' step. Here you can write the sql:
select id from city where upper(name) = upper(?)
and specify the city field name from the text file as parameter. With 'Number of rows to return' and 'Outer join?' you can control the join behaviour.
This solution doesn't work well with a large number of rows, as it will execute one query per row. In those cases Rishu's solution is better.
This is how I did:
First "Modified JavaScript value" step for create a query:
var queryDest="select coalesce( (select id as idcity from city where upper(name) = upper('"+replace(mycity,"'","\'\'")+"') and upper(cap) = upper('"+mycap+"') ), 0) as idcitydest";
Then I use this string as a query in a Dynamic SQL row.
After that,
IF idcitydest == 0 then
insert new city;
else
use the found record
This system make a query for file's row but it use few memory cache
Without saving SHA1 digest string in table directly. Is it possible to format the column in select statement ?
For example (Hope you know what i mean):
#item = Item.where(Digest::SHA1.hexdigest id.to_s:'356a192b7913b04c54574d18c28d46e6395428ab')
No, not the way you want it. The hexdigest method you're using won't be available at the database level. You could use database-specific functions though.
For example:
Item.where("LOWER(name) = ?", entered_name.downcase)
The LOWER() function will be available to the database so it can pass the name column to it.
For your case, I can suggest two solutions:
Obviously, store the encrypted field in the table. And then match.
key = '356a192b7913b04c54574d18c28d46e6395428ab'
Item.where(encrypted_id: key)
Iterate over all column values (ID, in your case) and find the one that matches:
all_item_ids = Item.pluck("CAST(id AS TEXT)")
item_id = all_item_ids.find{ |val| Digest::SHA1.hexdigest(val) == key }
Then you could use Item.find(item_id) to get the item or Item.where(id: item_id) to get an ActiveRecord::Relation object.
Hi all i have the following code:
tx = session.beginTransaction();
Query query = session.createQuery("UPDATE com.nisid.entities.Payment set amount=:amount,paymentMethod=:method,paymentExpire=:expireDate"
+ "Where paymentId=:payid,actionId=:actionid");
query.setParameter("amount", amount);
query.setParameter("method", method);
query.setParameter("expireDate", expireDate);
query.setParameter("payid", projectId);
query.setParameter("actionid", actionId);
int resutl=query.executeUpdate();
Trying to do an update using HQL but i am getting error: galArgumentException: node to traverse cannot be null!
my table in the DB is called Payment and it has A COMPOSITE KEY ( projectId,actionId)
Could you please help me further???
The concept is that i have a JSP page which retrieves and displayes the results from DB retrieving info from Project Table, Payment Table and Action Table. Project has many to many relationship with Action and i am using Payment Table as the intermetiary table which holds the 2 FK of the other table.
You missed space before where, and replace , to and after where.
Query query = session.createQuery("UPDATE com.nisid.entities.Payment set amount=:amount,paymentMethod=:method,paymentExpire=:expireDate"
+ " Where paymentId=:payid and actionId=:actionid");