4

This is a continuation** of my quest to switch from regular DynamoDB tables to DynamoDB2 ones with Global Secondary Indices.

So I created my table as shown here and then added the following two elements:

table.put_item(data={'firstKey': 'key01', 'message': '{"firstKey":"key01", "comments": "mess 1 w/o secondKey"}'})
table.put_item(data={'firstKey': 'key02', 'secondKey':'skey01', 'message': '{"firstKey":"key02", "parentId":"skey01", "comments": "mess 2 w/ secondKey"}'})

What I want to do now is retrieve items by either their (i) unique firstKey values or (ii) unique secondKey values. The 1st one is easy:

res1 = table.get_item(firstKey='key01')
res1['message']

I can't figure out how to do the 2nd one. This does not work:

res2 = table.get_item(secondKey='skey01')

producing The provided key element does not match the schema. OK that's expected. When I do this:

res2 = table.query(secondKey='skey01',index='secondKeyIndex')

I get You must specify more than one key to filter on.

So how do I get it to work? Note that when I have the value of secondKey of an item, I do NOT know its corresponding firstKey.

===== UPDATE: Here are a couple of other things that I've tried:

This

res2 = table.query(secondKey__eq='skey01',index='secondKeyIndex')

produced

boto.dynamodb2.exceptions.QueryError: You must specify more than one key to filter on.

In the block below, the query statement did not produce any errors

res2 = table.query(secondKey='skey01',secondKey__eq='skey01',index='secondKeyIndex')
for r in res2:
    print res2['secondKey']

but the print gave me

boto.dynamodb2.exceptions.UnknownFilterTypeError: Operator 'secondKey' from 'secondKey' is not recognized.
Community
  • 1
  • 1
I Z
  • 5,719
  • 19
  • 53
  • 100

3 Answers3

5

It is possible using LSI/GSI.

See the boto tutorial here (search for LSI, and you will get the example). DynamoDB2 — boto v2.25.0 : http://boto.readthedocs.org/en/latest/ref/dynamodb2.html

Adding a full working example (tried with dynamo local: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Tools.DynamoDBLocal.html)

conn = DynamoDBConnection(
    host='localhost',
    port=8000,
    aws_access_key_id='DEVDB', #anything will do
    aws_secret_access_key='DEVDB', #anything will do
    is_secure=False)
tables = conn.list_tables()
print "Before Creation:", tables

table_name = 'myTable'
if table_name not in tables['TableNames']:
    Table.create(table_name
        , schema=[HashKey('firstKey')]
        , throughput={'read': 5, 'write': 2}
        , global_indexes=[
            GlobalAllIndex('secondKeyIndex', parts=[HashKey('secondKey')], throughput={'read': 5, 'write': 3})]
        , connection=conn
    )
    #print_table_details(conn, table_name)
table = Table(table_name, connection=conn)
item = Item(table, data={
    'firstKey': str(uuid.uuid4()),
    'secondKey': 'DUMMY-second'
})
item.save()
results = table.query(secondKey__eq='DUMMY-second', index='secondKeyIndex')
for res in results:
    print res['firstKey'], res['secondKey']

The result of execution is:

91d4d056-1da3-42c6-801e-5b8e9c42a93f DUMMY-second
15c17b09-4975-419a-b603-427e4c765f03 DUMMY-second
dd947b7d-935e-458f-84d3-ed6cd4f32f5a DUMMY-second

Also adding the exact packages (Due to Dynamo1/2 - there is chance of mistake):

from boto.dynamodb2.fields import HashKey, RangeKey, GlobalAllIndex
from boto.dynamodb2.layer1 import DynamoDBConnection
from boto.dynamodb2.table import Table
from boto.dynamodb2.items import Item
Sony Kadavan
  • 3,982
  • 2
  • 19
  • 26
  • Well, I read and reread this page a couple of times over the course of a couple of days trying to get this to work. I know that it can be done since I did it through the AWS console, but now I need to figure out how to do it programmatically using `boto`. Could you please show me the exact query syntax for my example above? Thanks BTW, if I need to modify the way I create the table to make this work, that's fine too. I just need to be able to retrieve items either by `firstKey` or by `secondKey`. – I Z Feb 14 '14 at 19:04
  • OK Here you go: I have edited the answer above with a full working example. I just now tried and ensured this works with Dynamo DB Local. One common problem which people face is having an older version of Dynamo Local. Ensure that you download the latest and try. I now tried with dynamodb_local_2013-12-12 – Sony Kadavan Feb 15 '14 at 12:18
1

For all those looking for a newer version when using query_2: check out https://github.com/boto/boto/issues/2708

philmaweb
  • 514
  • 7
  • 13
0

Query arguments are formatted differently. I haven't tried it, but I believe the syntax should be:

res2 = table.query(secondKey__eq='skey01',index='secondKeyIndex')
Jharrod LaFon
  • 545
  • 4
  • 6