Index: third_party/gsutil/boto/docs/source/dynamodb_tut.rst |
diff --git a/third_party/gsutil/boto/docs/source/dynamodb_tut.rst b/third_party/gsutil/boto/docs/source/dynamodb_tut.rst |
new file mode 100644 |
index 0000000000000000000000000000000000000000..07f060836df95a074b4590841179c47118eaf7dd |
--- /dev/null |
+++ b/third_party/gsutil/boto/docs/source/dynamodb_tut.rst |
@@ -0,0 +1,339 @@ |
+.. dynamodb_tut: |
+ |
+============================================ |
+An Introduction to boto's DynamoDB interface |
+============================================ |
+ |
+This tutorial focuses on the boto interface to AWS' DynamoDB_. This tutorial |
+assumes that you have boto already downloaded and installed. |
+ |
+.. _DynamoDB: http://aws.amazon.com/dynamodb/ |
+ |
+ |
+Creating a Connection |
+--------------------- |
+ |
+The first step in accessing DynamoDB is to create a connection to the service. |
+To do so, the most straight forward way is the following:: |
+ |
+ >>> import boto |
+ >>> conn = boto.connect_dynamodb( |
+ aws_access_key_id='<YOUR_AWS_KEY_ID>', |
+ aws_secret_access_key='<YOUR_AWS_SECRET_KEY>') |
+ >>> conn |
+ <boto.dynamodb.layer2.Layer2 object at 0x3fb3090> |
+ |
+Bear in mind that if you have your credentials in boto config in your home |
+directory, the two keyword arguments in the call above are not needed. More |
+details on configuration can be found in :doc:`boto_config_tut`. |
+ |
+The :py:func:`boto.connect_dynamodb` functions returns a |
+:py:class:`boto.dynamodb.layer2.Layer2` instance, which is a high-level API |
+for working with DynamoDB. Layer2 is a set of abstractions that sit atop |
+the lower level :py:class:`boto.dynamodb.layer1.Layer1` API, which closely |
+mirrors the Amazon DynamoDB API. For the purpose of this tutorial, we'll |
+just be covering Layer2. |
+ |
+ |
+Listing Tables |
+-------------- |
+ |
+Now that we have a DynamoDB connection object, we can then query for a list of |
+existing tables in that region:: |
+ |
+ >>> conn.list_tables() |
+ ['test-table', 'another-table'] |
+ |
+ |
+Creating Tables |
+--------------- |
+ |
+DynamoDB tables are created with the |
+:py:meth:`Layer2.create_table <boto.dynamodb.layer2.Layer2.create_table>` |
+method. While DynamoDB's items (a rough equivalent to a relational DB's row) |
+don't have a fixed schema, you do need to create a schema for the table's |
+hash key element, and the optional range key element. This is explained in |
+greater detail in DynamoDB's `Data Model`_ documentation. |
+ |
+We'll start by defining a schema that has a hash key and a range key that |
+are both keys:: |
+ |
+ >>> message_table_schema = conn.create_schema( |
+ hash_key_name='forum_name', |
+ hash_key_proto_value=str, |
+ range_key_name='subject', |
+ range_key_proto_value=str |
+ ) |
+ |
+The next few things to determine are table name and read/write throughput. We'll |
+defer explaining throughput to the DynamoDB's `Provisioned Throughput`_ docs. |
+ |
+We're now ready to create the table:: |
+ |
+ >>> table = conn.create_table( |
+ name='messages', |
+ schema=message_table_schema, |
+ read_units=10, |
+ write_units=10 |
+ ) |
+ >>> table |
+ Table(messages) |
+ |
+This returns a :py:class:`boto.dynamodb.table.Table` instance, which provides |
+simple ways to create (put), update, and delete items. |
+ |
+ |
+Getting a Table |
+--------------- |
+ |
+To retrieve an existing table, use |
+:py:meth:`Layer2.get_table <boto.dynamodb.layer2.Layer2.get_table>`:: |
+ |
+ >>> conn.list_tables() |
+ ['test-table', 'another-table', 'messages'] |
+ >>> table = conn.get_table('messages') |
+ >>> table |
+ Table(messages) |
+ |
+:py:meth:`Layer2.get_table <boto.dynamodb.layer2.Layer2.get_table>`, like |
+:py:meth:`Layer2.create_table <boto.dynamodb.layer2.Layer2.create_table>`, |
+returns a :py:class:`boto.dynamodb.table.Table` instance. |
+ |
+Keep in mind that :py:meth:`Layer2.get_table <boto.dynamodb.layer2.Layer2.get_table>` |
+will make an API call to retrieve various attributes of the table including the |
+creation time, the read and write capacity, and the table schema. If you |
+already know the schema, you can save an API call and create a |
+:py:class:`boto.dynamodb.table.Table` object without making any calls to |
+Amazon DynamoDB:: |
+ |
+ >>> table = conn.table_from_schema( |
+ name='messages', |
+ schema=message_table_schema) |
+ |
+If you do this, the following fields will have ``None`` values: |
+ |
+ * create_time |
+ * status |
+ * read_units |
+ * write_units |
+ |
+In addition, the ``item_count`` and ``size_bytes`` will be 0. |
+If you create a table object directly from a schema object and |
+decide later that you need to retrieve any of these additional |
+attributes, you can use the |
+:py:meth:`Table.refresh <boto.dynamodb.table.Table.refresh>` method:: |
+ |
+ >>> from boto.dynamodb.schema import Schema |
+ >>> table = conn.table_from_schema( |
+ name='messages', |
+ schema=Schema.create(hash_key=('forum_name', 'S'), |
+ range_key=('subject', 'S'))) |
+ >>> print table.write_units |
+ None |
+ >>> # Now we decide we need to know the write_units: |
+ >>> table.refresh() |
+ >>> print table.write_units |
+ 10 |
+ |
+ |
+The recommended best practice is to retrieve a table object once and |
+use that object for the duration of your application. So, for example, |
+instead of this:: |
+ |
+ class Application(object): |
+ def __init__(self, layer2): |
+ self._layer2 = layer2 |
+ |
+ def retrieve_item(self, table_name, key): |
+ return self._layer2.get_table(table_name).get_item(key) |
+ |
+You can do something like this instead:: |
+ |
+ class Application(object): |
+ def __init__(self, layer2): |
+ self._layer2 = layer2 |
+ self._tables_by_name = {} |
+ |
+ def retrieve_item(self, table_name, key): |
+ table = self._tables_by_name.get(table_name) |
+ if table is None: |
+ table = self._layer2.get_table(table_name) |
+ self._tables_by_name[table_name] = table |
+ return table.get_item(key) |
+ |
+ |
+Describing Tables |
+----------------- |
+ |
+To get a complete description of a table, use |
+:py:meth:`Layer2.describe_table <boto.dynamodb.layer2.Layer2.describe_table>`:: |
+ |
+ >>> conn.list_tables() |
+ ['test-table', 'another-table', 'messages'] |
+ >>> conn.describe_table('messages') |
+ { |
+ 'Table': { |
+ 'CreationDateTime': 1327117581.624, |
+ 'ItemCount': 0, |
+ 'KeySchema': { |
+ 'HashKeyElement': { |
+ 'AttributeName': 'forum_name', |
+ 'AttributeType': 'S' |
+ }, |
+ 'RangeKeyElement': { |
+ 'AttributeName': 'subject', |
+ 'AttributeType': 'S' |
+ } |
+ }, |
+ 'ProvisionedThroughput': { |
+ 'ReadCapacityUnits': 10, |
+ 'WriteCapacityUnits': 10 |
+ }, |
+ 'TableName': 'messages', |
+ 'TableSizeBytes': 0, |
+ 'TableStatus': 'ACTIVE' |
+ } |
+ } |
+ |
+ |
+Adding Items |
+------------ |
+ |
+Continuing on with our previously created ``messages`` table, adding an:: |
+ |
+ >>> table = conn.get_table('messages') |
+ >>> item_data = { |
+ 'Body': 'http://url_to_lolcat.gif', |
+ 'SentBy': 'User A', |
+ 'ReceivedTime': '12/9/2011 11:36:03 PM', |
+ } |
+ >>> item = table.new_item( |
+ # Our hash key is 'forum' |
+ hash_key='LOLCat Forum', |
+ # Our range key is 'subject' |
+ range_key='Check this out!', |
+ # This has the |
+ attrs=item_data |
+ ) |
+ |
+The |
+:py:meth:`Table.new_item <boto.dynamodb.table.Table.new_item>` method creates |
+a new :py:class:`boto.dynamodb.item.Item` instance with your specified |
+hash key, range key, and attributes already set. |
+:py:class:`Item <boto.dynamodb.item.Item>` is a :py:class:`dict` sub-class, |
+meaning you can edit your data as such:: |
+ |
+ item['a_new_key'] = 'testing' |
+ del item['a_new_key'] |
+ |
+After you are happy with the contents of the item, use |
+:py:meth:`Item.put <boto.dynamodb.item.Item.put>` to commit it to DynamoDB:: |
+ |
+ >>> item.put() |
+ |
+ |
+Retrieving Items |
+---------------- |
+ |
+Now, let's check if it got added correctly. Since DynamoDB works under an |
+'eventual consistency' mode, we need to specify that we wish a consistent read, |
+as follows:: |
+ |
+ >>> table = conn.get_table('messages') |
+ >>> item = table.get_item( |
+ # Your hash key was 'forum_name' |
+ hash_key='LOLCat Forum', |
+ # Your range key was 'subject' |
+ range_key='Check this out!' |
+ ) |
+ >>> item |
+ { |
+ # Note that this was your hash key attribute (forum_name) |
+ 'forum_name': 'LOLCat Forum', |
+ # This is your range key attribute (subject) |
+ 'subject': 'Check this out!' |
+ 'Body': 'http://url_to_lolcat.gif', |
+ 'ReceivedTime': '12/9/2011 11:36:03 PM', |
+ 'SentBy': 'User A', |
+ } |
+ |
+ |
+Updating Items |
+-------------- |
+ |
+To update an item's attributes, simply retrieve it, modify the value, then |
+:py:meth:`Item.put <boto.dynamodb.item.Item.put>` it again:: |
+ |
+ >>> table = conn.get_table('messages') |
+ >>> item = table.get_item( |
+ hash_key='LOLCat Forum', |
+ range_key='Check this out!' |
+ ) |
+ >>> item['SentBy'] = 'User B' |
+ >>> item.put() |
+ |
+Working with Decimals |
+--------------------- |
+ |
+To avoid the loss of precision, you can stipulate that the |
+``decimal.Decimal`` type be used for numeric values:: |
+ |
+ >>> import decimal |
+ >>> conn.use_decimals() |
+ >>> table = conn.get_table('messages') |
+ >>> item = table.new_item( |
+ hash_key='LOLCat Forum', |
+ range_key='Check this out!' |
+ ) |
+ >>> item['decimal_type'] = decimal.Decimal('1.12345678912345') |
+ >>> item.put() |
+ >>> print table.get_item('LOLCat Forum', 'Check this out!') |
+ {u'forum_name': 'LOLCat Forum', u'decimal_type': Decimal('1.12345678912345'), |
+ u'subject': 'Check this out!'} |
+ |
+You can enable the usage of ``decimal.Decimal`` by using either the ``use_decimals`` |
+method, or by passing in the |
+:py:class:`Dynamizer <boto.dynamodb.types.Dynamizer>` class for |
+the ``dynamizer`` param:: |
+ |
+ >>> from boto.dynamodb.types import Dynamizer |
+ >>> conn = boto.connect_dynamodb(dynamizer=Dynamizer) |
+ |
+This mechanism can also be used if you want to customize the encoding/decoding |
+process of DynamoDB types. |
+ |
+ |
+Deleting Items |
+-------------- |
+ |
+To delete items, use the |
+:py:meth:`Item.delete <boto.dynamodb.item.Item.delete>` method:: |
+ |
+ >>> table = conn.get_table('messages') |
+ >>> item = table.get_item( |
+ hash_key='LOLCat Forum', |
+ range_key='Check this out!' |
+ ) |
+ >>> item.delete() |
+ |
+ |
+Deleting Tables |
+--------------- |
+ |
+.. WARNING:: |
+ Deleting a table will also **permanently** delete all of its contents without prompt. Use carefully. |
+ |
+There are two easy ways to delete a table. Through your top-level |
+:py:class:`Layer2 <boto.dynamodb.layer2.Layer2>` object:: |
+ |
+ >>> conn.delete_table(table) |
+ |
+Or by getting the table, then using |
+:py:meth:`Table.delete <boto.dynamodb.table.Table.delete>`:: |
+ |
+ >>> table = conn.get_table('messages') |
+ >>> table.delete() |
+ |
+ |
+.. _Data Model: http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/DataModel.html |
+.. _Provisioned Throughput: http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/ProvisionedThroughputIntro.html |