~ubuntu-branches/ubuntu/trusty/python-boto/trusty

« back to all changes in this revision

Viewing changes to docs/build/html/dynamodb2_tut.html

  • Committer: Package Import Robot
  • Author(s): Eric Evans
  • Date: 2013-12-27 15:09:08 UTC
  • mfrom: (1.1.14) (14.1.4 experimental)
  • Revision ID: package-import@ubuntu.com-20131227150908-qlm32tt1lej259nd
Tags: 2.20.1-2
Run unit tests with autopkgtest.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
3
 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
 
 
5
 
 
6
 
<html xmlns="http://www.w3.org/1999/xhtml">
7
 
  <head>
8
 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
9
 
    
10
 
    <title>An Introduction to boto’s DynamoDB v2 interface &mdash; boto v2.16.0</title>
11
 
    
12
 
    <link rel="stylesheet" href="_static/boto.css" type="text/css" />
13
 
    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
14
 
    
15
 
    <script type="text/javascript">
16
 
      var DOCUMENTATION_OPTIONS = {
17
 
        URL_ROOT:    '',
18
 
        VERSION:     'HEAD',
19
 
        COLLAPSE_INDEX: false,
20
 
        FILE_SUFFIX: '.html',
21
 
        HAS_SOURCE:  true
22
 
      };
23
 
    </script>
24
 
    <script type="text/javascript" src="_static/jquery.js"></script>
25
 
    <script type="text/javascript" src="_static/underscore.js"></script>
26
 
    <script type="text/javascript" src="_static/doctools.js"></script>
27
 
    <link rel="top" title="boto v2.16.0" href="index.html" />
28
 
    <link rel="next" title="Migrating from DynamoDB v1 to DynamoDB v2" href="migrations/dynamodb_v1_to_v2.html" />
29
 
    <link rel="prev" title="An Introduction to boto’s Support interface" href="support_tut.html" /> 
30
 
  </head>
31
 
  <body>
32
 
    <div class="related">
33
 
      <h3>Navigation</h3>
34
 
      <ul>
35
 
        <li class="right" style="margin-right: 10px">
36
 
          <a href="genindex.html" title="General Index"
37
 
             accesskey="I">index</a></li>
38
 
        <li class="right" >
39
 
          <a href="py-modindex.html" title="Python Module Index"
40
 
             >modules</a> |</li>
41
 
        <li class="right" >
42
 
          <a href="migrations/dynamodb_v1_to_v2.html" title="Migrating from DynamoDB v1 to DynamoDB v2"
43
 
             accesskey="N">next</a> |</li>
44
 
        <li class="right" >
45
 
          <a href="support_tut.html" title="An Introduction to boto’s Support interface"
46
 
             accesskey="P">previous</a> |</li>
47
 
        <li><a href="index.html">boto v2.16.0</a> &raquo;</li> 
48
 
      </ul>
49
 
    </div>  
50
 
 
51
 
    <div class="document">
52
 
      <div class="documentwrapper">
53
 
        <div class="bodywrapper">
54
 
          <div class="body">
55
 
            
56
 
  <div class="section" id="an-introduction-to-boto-s-dynamodb-v2-interface">
57
 
<span id="dynamodb2-tut"></span><h1>An Introduction to boto&#8217;s DynamoDB v2 interface<a class="headerlink" href="#an-introduction-to-boto-s-dynamodb-v2-interface" title="Permalink to this headline">¶</a></h1>
58
 
<p>This tutorial focuses on the boto interface to AWS&#8217; <a class="reference external" href="http://aws.amazon.com/dynamodb/">DynamoDB</a> v2. This tutorial
59
 
assumes that you have boto already downloaded and installed.</p>
60
 
<div class="admonition warning">
61
 
<p class="first admonition-title">Warning</p>
62
 
<p class="last">This tutorial covers the <strong>SECOND</strong> major release of DynamoDB (including
63
 
local secondary index support). The documentation for the original
64
 
version of DynamoDB (&amp; boto&#8217;s support for it) is at
65
 
<a class="reference internal" href="dynamodb_tut.html"><em>DynamoDB v1</em></a>.</p>
66
 
</div>
67
 
<p>The v2 DynamoDB API has both a high-level &amp; low-level component. The low-level
68
 
API (contained primarily within <tt class="docutils literal"><span class="pre">boto.dynamodb2.layer1</span></tt>) provides an
69
 
interface that rough matches exactly what is provided by the API. It supports
70
 
all options available to the service.</p>
71
 
<p>The high-level API attempts to make interacting with the service more natural
72
 
from Python. It supports most of the featureset.</p>
73
 
<div class="section" id="the-high-level-api">
74
 
<h2>The High-Level API<a class="headerlink" href="#the-high-level-api" title="Permalink to this headline">¶</a></h2>
75
 
<p>Most of the interaction centers around a single object, the <tt class="docutils literal"><span class="pre">Table</span></tt>. Tables
76
 
act as a way to effectively namespace your records. If you&#8217;re familiar with
77
 
database tables from an RDBMS, tables will feel somewhat familiar.</p>
78
 
<div class="section" id="creating-a-new-table">
79
 
<h3>Creating a New Table<a class="headerlink" href="#creating-a-new-table" title="Permalink to this headline">¶</a></h3>
80
 
<p>To create a new table, you need to call <tt class="docutils literal"><span class="pre">Table.create</span></tt> &amp; specify (at a
81
 
minimum) both the table&#8217;s name as well as the key schema for the table.</p>
82
 
<p>Since both the key schema and local secondary indexes can not be
83
 
modified after the table is created, you&#8217;ll need to plan ahead of time how you
84
 
think the table will be used. Both the keys &amp; indexes are also used for
85
 
querying, so you&#8217;ll want to represent the data you&#8217;ll need when querying
86
 
there as well.</p>
87
 
<p>For the schema, you can either have a single <tt class="docutils literal"><span class="pre">HashKey</span></tt> or a combined
88
 
<tt class="docutils literal"><span class="pre">HashKey+RangeKey</span></tt>. The <tt class="docutils literal"><span class="pre">HashKey</span></tt> by itself should be thought of as a
89
 
unique identifier (for instance, like a username or UUID). It is typically
90
 
looked up as an exact value.
91
 
A <tt class="docutils literal"><span class="pre">HashKey+RangeKey</span></tt> combination is slightly different, in that the
92
 
<tt class="docutils literal"><span class="pre">HashKey</span></tt> acts like a namespace/prefix &amp; the <tt class="docutils literal"><span class="pre">RangeKey</span></tt> acts as a value
93
 
that can be referred to by a sorted range of values.</p>
94
 
<p>For the local secondary indexes, you can choose from an <tt class="docutils literal"><span class="pre">AllIndex</span></tt>, a
95
 
<tt class="docutils literal"><span class="pre">KeysOnlyIndex</span></tt> or a <tt class="docutils literal"><span class="pre">IncludeIndex</span></tt> field. Each builds an index of values
96
 
that can be queried on. The <tt class="docutils literal"><span class="pre">AllIndex</span></tt> duplicates all values onto the index
97
 
(to prevent additional reads to fetch the data). The <tt class="docutils literal"><span class="pre">KeysOnlyIndex</span></tt>
98
 
duplicates only the keys from the schema onto the index. The <tt class="docutils literal"><span class="pre">IncludeIndex</span></tt>
99
 
lets you specify a list of fieldnames to duplicate over.</p>
100
 
<p>Simple example:</p>
101
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.fields</span> <span class="kn">import</span> <span class="n">HashKey</span>
102
 
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.table</span> <span class="kn">import</span> <span class="n">Table</span>
103
 
 
104
 
<span class="go"># Uses your ``aws_access_key_id`` &amp; ``aws_secret_access_key`` from either a</span>
105
 
<span class="go"># config file or environment variable &amp; the default region.</span>
106
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="s">&#39;users&#39;</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="p">[</span>
107
 
<span class="gp">... </span>    <span class="n">HashKey</span><span class="p">(</span><span class="s">&#39;username&#39;</span><span class="p">),</span>
108
 
<span class="gp">... </span><span class="p">])</span>
109
 
</pre></div>
110
 
</div>
111
 
<p>A full example:</p>
112
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">boto.dynamodb2</span>
113
 
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.fields</span> <span class="kn">import</span> <span class="n">HashKey</span><span class="p">,</span> <span class="n">RangeKey</span><span class="p">,</span> <span class="n">KeysOnlyIndex</span><span class="p">,</span> <span class="n">AllIndex</span>
114
 
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.table</span> <span class="kn">import</span> <span class="n">Table</span>
115
 
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.types</span> <span class="kn">import</span> <span class="n">NUMBER</span>
116
 
 
117
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="s">&#39;users&#39;</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="p">[</span>
118
 
<span class="gp">... </span>    <span class="n">HashKey</span><span class="p">(</span><span class="s">&#39;account_type&#39;</span><span class="p">,</span> <span class="n">data_type</span><span class="o">=</span><span class="n">NUMBER</span><span class="p">),</span>
119
 
<span class="gp">... </span>    <span class="n">RangeKey</span><span class="p">(</span><span class="s">&#39;last_name&#39;</span><span class="p">),</span>
120
 
<span class="gp">... </span><span class="p">],</span> <span class="n">throughput</span><span class="o">=</span><span class="p">{</span>
121
 
<span class="gp">... </span>    <span class="s">&#39;read&#39;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
122
 
<span class="gp">... </span>    <span class="s">&#39;write&#39;</span><span class="p">:</span> <span class="mi">15</span><span class="p">,</span>
123
 
<span class="gp">... </span><span class="p">},</span> <span class="n">indexes</span><span class="o">=</span><span class="p">[</span>
124
 
<span class="gp">... </span>    <span class="n">AllIndex</span><span class="p">(</span><span class="s">&#39;EverythingIndex&#39;</span><span class="p">,</span> <span class="n">parts</span><span class="o">=</span><span class="p">[</span>
125
 
<span class="gp">... </span>        <span class="n">HashKey</span><span class="p">(</span><span class="s">&#39;account_type&#39;</span><span class="p">,</span> <span class="n">data_type</span><span class="o">=</span><span class="n">NUMBER</span><span class="p">),</span>
126
 
<span class="gp">... </span>    <span class="p">])</span>
127
 
<span class="gp">... </span><span class="p">],</span>
128
 
<span class="gp">... </span><span class="c"># If you need to specify custom parameters like keys or region info...</span>
129
 
<span class="gp">... </span><span class="n">connection</span><span class="o">=</span> <span class="n">boto</span><span class="o">.</span><span class="n">dynamodb2</span><span class="o">.</span><span class="n">connect_to_region</span><span class="p">(</span><span class="s">&#39;us-east-1&#39;</span><span class="p">))</span>
130
 
</pre></div>
131
 
</div>
132
 
</div>
133
 
<div class="section" id="using-an-existing-table">
134
 
<h3>Using an Existing Table<a class="headerlink" href="#using-an-existing-table" title="Permalink to this headline">¶</a></h3>
135
 
<p>Once a table has been created, using it is relatively simple. You can either
136
 
specify just the <tt class="docutils literal"><span class="pre">table_name</span></tt> (allowing the object to lazily do an additional
137
 
call to get details about itself if needed) or provide the <tt class="docutils literal"><span class="pre">schema/indexes</span></tt>
138
 
again (same as what was used with <tt class="docutils literal"><span class="pre">Table.create</span></tt>) to avoid extra overhead.</p>
139
 
<p>Lazy example:</p>
140
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.table</span> <span class="kn">import</span> <span class="n">Table</span>
141
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;users&#39;</span><span class="p">)</span>
142
 
</pre></div>
143
 
</div>
144
 
<p>Efficient example:</p>
145
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.fields</span> <span class="kn">import</span> <span class="n">HashKey</span><span class="p">,</span> <span class="n">RangeKey</span><span class="p">,</span> <span class="n">AllIndex</span>
146
 
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.table</span> <span class="kn">import</span> <span class="n">Table</span>
147
 
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.types</span> <span class="kn">import</span> <span class="n">NUMBER</span>
148
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;users&#39;</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="p">[</span>
149
 
<span class="gp">... </span>    <span class="n">HashKey</span><span class="p">(</span><span class="s">&#39;account_type&#39;</span><span class="p">,</span> <span class="n">data_type</span><span class="o">=</span><span class="n">NUMBER</span><span class="p">),</span>
150
 
<span class="gp">... </span>    <span class="n">RangeKey</span><span class="p">(</span><span class="s">&#39;last_name&#39;</span><span class="p">),</span>
151
 
<span class="gp">... </span><span class="p">],</span> <span class="n">indexes</span><span class="o">=</span><span class="p">[</span>
152
 
<span class="gp">... </span>    <span class="n">AllIndex</span><span class="p">(</span><span class="s">&#39;EverythingIndex&#39;</span><span class="p">,</span> <span class="n">parts</span><span class="o">=</span><span class="p">[</span>
153
 
<span class="gp">... </span>        <span class="n">HashKey</span><span class="p">(</span><span class="s">&#39;account_type&#39;</span><span class="p">,</span> <span class="n">data_type</span><span class="o">=</span><span class="n">NUMBER</span><span class="p">),</span>
154
 
<span class="gp">... </span>    <span class="p">])</span>
155
 
<span class="gp">... </span><span class="p">])</span>
156
 
</pre></div>
157
 
</div>
158
 
</div>
159
 
<div class="section" id="creating-a-new-item">
160
 
<h3>Creating a New Item<a class="headerlink" href="#creating-a-new-item" title="Permalink to this headline">¶</a></h3>
161
 
<p>Once you have a <tt class="docutils literal"><span class="pre">Table</span></tt> instance, you can add new items to the table. There
162
 
are two ways to do this.</p>
163
 
<p>The first is to use the <tt class="docutils literal"><span class="pre">Table.put_item</span></tt> method. Simply hand it a dictionary
164
 
of data &amp; it will create the item on the server side. This dictionary should
165
 
be relatively flat (as you can nest in other dictionaries) &amp; <strong>must</strong> contain
166
 
the keys used in the <tt class="docutils literal"><span class="pre">schema</span></tt>.</p>
167
 
<p>Example:</p>
168
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.table</span> <span class="kn">import</span> <span class="n">Table</span>
169
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;users&#39;</span><span class="p">)</span>
170
 
 
171
 
<span class="go"># Create the new user.</span>
172
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">users</span><span class="o">.</span><span class="n">put_item</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="p">{</span>
173
 
<span class="gp">... </span>    <span class="s">&#39;username&#39;</span><span class="p">:</span> <span class="s">&#39;johndoe&#39;</span><span class="p">,</span>
174
 
<span class="gp">... </span>    <span class="s">&#39;first_name&#39;</span><span class="p">:</span> <span class="s">&#39;John&#39;</span><span class="p">,</span>
175
 
<span class="gp">... </span>    <span class="s">&#39;last_name&#39;</span><span class="p">:</span> <span class="s">&#39;Doe&#39;</span><span class="p">,</span>
176
 
<span class="gp">... </span><span class="p">})</span>
177
 
<span class="go">True</span>
178
 
</pre></div>
179
 
</div>
180
 
<p>The alternative is to manually construct an <tt class="docutils literal"><span class="pre">Item</span></tt> instance &amp; tell it to
181
 
<tt class="docutils literal"><span class="pre">save</span></tt> itself. This is useful if the object will be around for awhile &amp; you
182
 
don&#8217;t want to re-fetch it.</p>
183
 
<p>Example:</p>
184
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.items</span> <span class="kn">import</span> <span class="n">Item</span>
185
 
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.table</span> <span class="kn">import</span> <span class="n">Table</span>
186
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;users&#39;</span><span class="p">)</span>
187
 
 
188
 
<span class="go"># WARNING - This doens&#39;t save it yet!</span>
189
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span> <span class="o">=</span> <span class="n">Item</span><span class="p">(</span><span class="n">users</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="p">{</span>
190
 
<span class="gp">... </span>    <span class="s">&#39;username&#39;</span><span class="p">:</span> <span class="s">&#39;johndoe&#39;</span><span class="p">,</span>
191
 
<span class="gp">... </span>    <span class="s">&#39;first_name&#39;</span><span class="p">:</span> <span class="s">&#39;John&#39;</span><span class="p">,</span>
192
 
<span class="gp">... </span>    <span class="s">&#39;last_name&#39;</span><span class="p">:</span> <span class="s">&#39;Doe&#39;</span><span class="p">,</span>
193
 
<span class="gp">... </span><span class="p">})</span>
194
 
<span class="go"># The data now gets persisted to the server.</span>
195
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
196
 
<span class="go">True</span>
197
 
</pre></div>
198
 
</div>
199
 
</div>
200
 
<div class="section" id="getting-an-item-accessing-data">
201
 
<h3>Getting an Item &amp; Accessing Data<a class="headerlink" href="#getting-an-item-accessing-data" title="Permalink to this headline">¶</a></h3>
202
 
<p>With data now in DynamoDB, if you know the key of the item, you can fetch it
203
 
back out. Specify the key value(s) as kwargs to <tt class="docutils literal"><span class="pre">Table.get_item</span></tt>.</p>
204
 
<p>Example:</p>
205
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.table</span> <span class="kn">import</span> <span class="n">Table</span>
206
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;users&#39;</span><span class="p">)</span>
207
 
 
208
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">get_item</span><span class="p">(</span><span class="n">username</span><span class="o">=</span><span class="s">&#39;johndoe&#39;</span><span class="p">)</span>
209
 
</pre></div>
210
 
</div>
211
 
<p>Once you have an <tt class="docutils literal"><span class="pre">Item</span></tt> instance, it presents a dictionary-like interface to
212
 
the data.:</p>
213
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">get_item</span><span class="p">(</span><span class="n">username</span><span class="o">=</span><span class="s">&#39;johndoe&#39;</span><span class="p">)</span>
214
 
 
215
 
<span class="go"># Read a field out.</span>
216
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span><span class="p">[</span><span class="s">&#39;first_name&#39;</span><span class="p">]</span>
217
 
<span class="go">&#39;John&#39;</span>
218
 
 
219
 
<span class="go"># Change a field (DOESN&#39;T SAVE YET!).</span>
220
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span><span class="p">[</span><span class="s">&#39;first_name&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;Johann&#39;</span>
221
 
 
222
 
<span class="go"># Delete data from it (DOESN&#39;T SAVE YET!).</span>
223
 
<span class="gp">&gt;&gt;&gt; </span><span class="k">del</span> <span class="n">johndoe</span><span class="p">[</span><span class="s">&#39;last_name&#39;</span><span class="p">]</span>
224
 
</pre></div>
225
 
</div>
226
 
</div>
227
 
<div class="section" id="updating-an-item">
228
 
<h3>Updating an Item<a class="headerlink" href="#updating-an-item" title="Permalink to this headline">¶</a></h3>
229
 
<p>Just creating new items or changing only the in-memory version of the <tt class="docutils literal"><span class="pre">Item</span></tt>
230
 
isn&#8217;t particularly effective. To persist the changes to DynamoDB, you have
231
 
three choices.</p>
232
 
<p>The first is sending all the data with the expectation nothing has changed
233
 
since you read the data. DynamoDB will verify the data is in the original state
234
 
and, if so, will all of the item&#8217;s data. If that expectation fails, the call
235
 
will fail:</p>
236
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">get_item</span><span class="p">(</span><span class="n">username</span><span class="o">=</span><span class="s">&#39;johndoe&#39;</span><span class="p">)</span>
237
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span><span class="p">[</span><span class="s">&#39;first_name&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;Johann&#39;</span>
238
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span><span class="p">[</span><span class="s">&#39;whatever&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;man, that&#39;s just like your opinion&quot;</span>
239
 
<span class="gp">&gt;&gt;&gt; </span><span class="k">del</span> <span class="n">johndoe</span><span class="p">[</span><span class="s">&#39;last_name&#39;</span><span class="p">]</span>
240
 
 
241
 
<span class="go"># Affects all fields, even the ones not changed locally.</span>
242
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
243
 
<span class="go">True</span>
244
 
</pre></div>
245
 
</div>
246
 
<p>The second is a full overwrite. If you can be confident your version of the
247
 
data is the most correct, you can force an overwrite of the data.:</p>
248
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">get_item</span><span class="p">(</span><span class="n">username</span><span class="o">=</span><span class="s">&#39;johndoe&#39;</span><span class="p">)</span>
249
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span><span class="p">[</span><span class="s">&#39;first_name&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;Johann&#39;</span>
250
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span><span class="p">[</span><span class="s">&#39;whatever&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;man, that&#39;s just like your opinion&quot;</span>
251
 
<span class="gp">&gt;&gt;&gt; </span><span class="k">del</span> <span class="n">johndoe</span><span class="p">[</span><span class="s">&#39;last_name&#39;</span><span class="p">]</span>
252
 
 
253
 
<span class="go"># Specify ``overwrite=True`` to fully replace the data.</span>
254
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">overwrite</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
255
 
<span class="go">True</span>
256
 
</pre></div>
257
 
</div>
258
 
<p>The last is a partial update. If you&#8217;ve only modified certain fields, you
259
 
can send a partial update that only writes those fields, allowing other
260
 
(potentially changed) fields to go untouched.:</p>
261
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">get_item</span><span class="p">(</span><span class="n">username</span><span class="o">=</span><span class="s">&#39;johndoe&#39;</span><span class="p">)</span>
262
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span><span class="p">[</span><span class="s">&#39;first_name&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;Johann&#39;</span>
263
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span><span class="p">[</span><span class="s">&#39;whatever&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;man, that&#39;s just like your opinion&quot;</span>
264
 
<span class="gp">&gt;&gt;&gt; </span><span class="k">del</span> <span class="n">johndoe</span><span class="p">[</span><span class="s">&#39;last_name&#39;</span><span class="p">]</span>
265
 
 
266
 
<span class="go"># Partial update, only sending/affecting the</span>
267
 
<span class="go"># ``first_name/whatever/last_name`` fields.</span>
268
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span><span class="o">.</span><span class="n">partial_save</span><span class="p">()</span>
269
 
<span class="go">True</span>
270
 
</pre></div>
271
 
</div>
272
 
</div>
273
 
<div class="section" id="deleting-an-item">
274
 
<h3>Deleting an Item<a class="headerlink" href="#deleting-an-item" title="Permalink to this headline">¶</a></h3>
275
 
<p>You can also delete items from the table. You have two choices, depending on
276
 
what data you have present.</p>
277
 
<p>If you already have an <tt class="docutils literal"><span class="pre">Item</span></tt> instance, the easiest approach is just to call
278
 
<tt class="docutils literal"><span class="pre">Item.delete</span></tt>.:</p>
279
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">johndoe</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
280
 
<span class="go">True</span>
281
 
</pre></div>
282
 
</div>
283
 
<p>If you don&#8217;t have an <tt class="docutils literal"><span class="pre">Item</span></tt> instance &amp; you don&#8217;t want to incur the
284
 
<tt class="docutils literal"><span class="pre">Table.get_item</span></tt> call to get it, you can call <tt class="docutils literal"><span class="pre">Table.delete_item</span></tt> method.:</p>
285
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.table</span> <span class="kn">import</span> <span class="n">Table</span>
286
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;users&#39;</span><span class="p">)</span>
287
 
 
288
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">users</span><span class="o">.</span><span class="n">delete_item</span><span class="p">(</span><span class="n">username</span><span class="o">=</span><span class="s">&#39;johndoe&#39;</span><span class="p">)</span>
289
 
<span class="go">True</span>
290
 
</pre></div>
291
 
</div>
292
 
</div>
293
 
<div class="section" id="batch-writing">
294
 
<h3>Batch Writing<a class="headerlink" href="#batch-writing" title="Permalink to this headline">¶</a></h3>
295
 
<p>If you&#8217;re loading a lot of data at a time, making use of batch writing can
296
 
both speed up the process &amp; reduce the number of write requests made to the
297
 
service.</p>
298
 
<p>Batch writing involves wrapping the calls you want batched in a context manager.
299
 
The context manager immitates the <tt class="docutils literal"><span class="pre">Table.put_item</span></tt> &amp; <tt class="docutils literal"><span class="pre">Table.delete_item</span></tt>
300
 
APIs. Getting &amp; using the context manager looks like:</p>
301
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.table</span> <span class="kn">import</span> <span class="n">Table</span>
302
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;users&#39;</span><span class="p">)</span>
303
 
 
304
 
<span class="gp">&gt;&gt;&gt; </span><span class="k">with</span> <span class="n">users</span><span class="o">.</span><span class="n">batch_write</span><span class="p">()</span> <span class="k">as</span> <span class="n">batch</span><span class="p">:</span>
305
 
<span class="gp">... </span>    <span class="n">batch</span><span class="o">.</span><span class="n">put_item</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="p">{</span>
306
 
<span class="gp">... </span>        <span class="s">&#39;username&#39;</span><span class="p">:</span> <span class="s">&#39;anotherdoe&#39;</span><span class="p">,</span>
307
 
<span class="gp">... </span>        <span class="s">&#39;first_name&#39;</span><span class="p">:</span> <span class="s">&#39;Another&#39;</span><span class="p">,</span>
308
 
<span class="gp">... </span>        <span class="s">&#39;last_name&#39;</span><span class="p">:</span> <span class="s">&#39;Doe&#39;</span><span class="p">,</span>
309
 
<span class="gp">... </span>        <span class="s">&#39;date_joined&#39;</span><span class="p">:</span> <span class="nb">int</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()),</span>
310
 
<span class="gp">... </span>    <span class="p">})</span>
311
 
<span class="gp">... </span>    <span class="n">batch</span><span class="o">.</span><span class="n">put_item</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="p">{</span>
312
 
<span class="gp">... </span>        <span class="s">&#39;username&#39;</span><span class="p">:</span> <span class="s">&#39;alice&#39;</span><span class="p">,</span>
313
 
<span class="gp">... </span>        <span class="s">&#39;first_name&#39;</span><span class="p">:</span> <span class="s">&#39;Alice&#39;</span><span class="p">,</span>
314
 
<span class="gp">... </span>        <span class="s">&#39;date_joined&#39;</span><span class="p">:</span> <span class="nb">int</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()),</span>
315
 
<span class="gp">... </span>    <span class="p">})</span>
316
 
<span class="gp">... </span>    <span class="n">batch</span><span class="o">.</span><span class="n">delete_item</span><span class="p">(</span><span class="n">username</span><span class="o">=</span><span class="n">jane</span><span class="s">&#39;)</span>
317
 
</pre></div>
318
 
</div>
319
 
<p>However, there are some limitations on what you can do within the context
320
 
manager.</p>
321
 
<ul class="simple">
322
 
<li>It can&#8217;t read data at all or do batch any other operations.</li>
323
 
<li>You can&#8217;t put &amp; delete the same data within a batch request.</li>
324
 
</ul>
325
 
<div class="admonition note">
326
 
<p class="first admonition-title">Note</p>
327
 
<p class="last">Additionally, the context manager can only batch 25 items at a time for a
328
 
request (this is a DynamoDB limitation). It is handled for you so you can
329
 
keep writing additional items, but you should be aware that 100 <tt class="docutils literal"><span class="pre">put_item</span></tt>
330
 
calls is 4 batch requests, not 1.</p>
331
 
</div>
332
 
</div>
333
 
<div class="section" id="querying">
334
 
<h3>Querying<a class="headerlink" href="#querying" title="Permalink to this headline">¶</a></h3>
335
 
<p>Manually fetching out each item by itself isn&#8217;t tenable for large datasets.
336
 
To cope with fetching many records, you can either perform a standard query,
337
 
query via a local secondary index or scan the entire table.</p>
338
 
<p>A standard query typically gets run against a hash+range key combination.
339
 
Filter parameters are passed as kwargs &amp; use a <tt class="docutils literal"><span class="pre">__</span></tt> to separate the fieldname
340
 
from the operator being used to filter the value.</p>
341
 
<p>In terms of querying, our original schema is less than optimal. For the
342
 
following examples, we&#8217;ll be using the following table setup:</p>
343
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="s">&#39;users&#39;</span><span class="p">,</span> <span class="n">schema</span><span class="o">=</span><span class="p">[</span>
344
 
<span class="gp">... </span>    <span class="n">HashKey</span><span class="p">(</span><span class="s">&#39;account_type&#39;</span><span class="p">),</span>
345
 
<span class="gp">... </span>    <span class="n">RangeKey</span><span class="p">(</span><span class="s">&#39;last_name&#39;</span><span class="p">),</span>
346
 
<span class="gp">... </span><span class="p">],</span> <span class="n">indexes</span><span class="o">=</span><span class="p">[</span>
347
 
<span class="gp">... </span>    <span class="n">AllIndex</span><span class="p">(</span><span class="s">&#39;DateJoinedIndex&#39;</span><span class="p">,</span> <span class="n">parts</span><span class="o">=</span><span class="p">[</span>
348
 
<span class="gp">... </span>        <span class="n">HashKey</span><span class="p">(</span><span class="s">&#39;account_type&#39;</span><span class="p">),</span>
349
 
<span class="gp">... </span>        <span class="n">RangeKey</span><span class="p">(</span><span class="s">&#39;date_joined&#39;</span><span class="p">,</span> <span class="n">data_type</span><span class="o">=</span><span class="n">NUMBER</span><span class="p">),</span>
350
 
<span class="gp">... </span>    <span class="p">]),</span>
351
 
<span class="gp">... </span><span class="p">])</span>
352
 
</pre></div>
353
 
</div>
354
 
<p>When executing the query, you get an iterable back that contains your results.
355
 
These results may be spread over multiple requests as DynamoDB paginates them.
356
 
This is done transparently, but you should be aware it may take more than one
357
 
request.</p>
358
 
<p>To run a query for last names starting with the letter &#8220;D&#8221;:</p>
359
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">names_with_d</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">query</span><span class="p">(</span>
360
 
<span class="gp">... </span>    <span class="n">account_type__eq</span><span class="o">=</span><span class="s">&#39;standard_user&#39;</span><span class="p">,</span>
361
 
<span class="gp">... </span>    <span class="n">last_name__beginswith</span><span class="o">=</span><span class="s">&#39;D&#39;</span>
362
 
<span class="gp">... </span><span class="p">)</span>
363
 
 
364
 
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">user</span> <span class="ow">in</span> <span class="n">names_with_d</span><span class="p">:</span>
365
 
<span class="gp">... </span>    <span class="k">print</span> <span class="n">user</span><span class="p">[</span><span class="s">&#39;first_name&#39;</span><span class="p">]</span>
366
 
<span class="go">&#39;Bob&#39;</span>
367
 
<span class="go">&#39;Jane&#39;</span>
368
 
<span class="go">&#39;John&#39;</span>
369
 
</pre></div>
370
 
</div>
371
 
<p>You can also reverse results (<tt class="docutils literal"><span class="pre">reverse=True</span></tt>) as well as limiting them
372
 
(<tt class="docutils literal"><span class="pre">limit=2</span></tt>):</p>
373
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">rev_with_d</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">query</span><span class="p">(</span>
374
 
<span class="gp">... </span>    <span class="n">account_type__eq</span><span class="o">=</span><span class="s">&#39;standard_user&#39;</span><span class="p">,</span>
375
 
<span class="gp">... </span>    <span class="n">last_name__beginswith</span><span class="o">=</span><span class="s">&#39;D&#39;</span><span class="p">,</span>
376
 
<span class="gp">... </span>    <span class="n">reverse</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
377
 
<span class="gp">... </span>    <span class="n">limit</span><span class="o">=</span><span class="mi">2</span>
378
 
<span class="gp">... </span><span class="p">)</span>
379
 
 
380
 
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">user</span> <span class="ow">in</span> <span class="n">rev_with_d</span><span class="p">:</span>
381
 
<span class="gp">... </span>    <span class="k">print</span> <span class="n">user</span><span class="p">[</span><span class="s">&#39;first_name&#39;</span><span class="p">]</span>
382
 
<span class="go">&#39;John&#39;</span>
383
 
<span class="go">&#39;Jane&#39;</span>
384
 
</pre></div>
385
 
</div>
386
 
<p>You can also run queries against the local secondary indexes. Simply provide
387
 
the index name (<tt class="docutils literal"><span class="pre">index='FirstNameIndex'</span></tt>) &amp; filter parameters against its
388
 
fields:</p>
389
 
<div class="highlight-python"><pre># Users within the last hour.
390
 
&gt;&gt;&gt; recent = users.query(
391
 
...     account_type__eq='standard_user',
392
 
...     date_joined__gte=time.time() - (60 * 60),
393
 
...     index='DateJoinedIndex'
394
 
... )
395
 
 
396
 
&gt;&gt;&gt; for user in recent:
397
 
...     print user['first_name']
398
 
'Alice'
399
 
'Jane'</pre>
400
 
</div>
401
 
<p>Finally, if you need to query on data that&#8217;s not in either a key or in an
402
 
index, you can run a <tt class="docutils literal"><span class="pre">Table.scan</span></tt> across the whole table, which accepts a
403
 
similar but expanded set of filters. If you&#8217;re familiar with the Map/Reduce
404
 
concept, this is akin to what DynamoDB does.</p>
405
 
<div class="admonition warning">
406
 
<p class="first admonition-title">Warning</p>
407
 
<p class="last">Scans are consistent &amp; run over the entire table, so relatively speaking,
408
 
they&#8217;re more expensive than plain queries or queries against an LSI.</p>
409
 
</div>
410
 
<p>An example scan of all records in the table looks like:</p>
411
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">all_users</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">scan</span><span class="p">()</span>
412
 
</pre></div>
413
 
</div>
414
 
<p>Filtering a scan looks like:</p>
415
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">owners_with_emails</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">scan</span><span class="p">(</span>
416
 
<span class="gp">... </span>    <span class="n">is_owner__eq</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
417
 
<span class="gp">... </span>    <span class="n">email__null</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span>
418
 
<span class="gp">... </span><span class="p">)</span>
419
 
 
420
 
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">user</span> <span class="ow">in</span> <span class="n">recent</span><span class="p">:</span>
421
 
<span class="gp">... </span>    <span class="k">print</span> <span class="n">user</span><span class="p">[</span><span class="s">&#39;first_name&#39;</span><span class="p">]</span>
422
 
<span class="go">&#39;George&#39;</span>
423
 
<span class="go">&#39;John&#39;</span>
424
 
</pre></div>
425
 
</div>
426
 
</div>
427
 
<div class="section" id="parallel-scan">
428
 
<h3>Parallel Scan<a class="headerlink" href="#parallel-scan" title="Permalink to this headline">¶</a></h3>
429
 
<p>DynamoDB also includes a feature called &#8220;Parallel Scan&#8221;, which allows you
430
 
to make use of <strong>extra</strong> read capacity to divide up your result set &amp; scan
431
 
an entire table faster.</p>
432
 
<p>This does require extra code on the user&#8217;s part &amp; you should ensure that
433
 
you need the speed boost, have enough data to justify it and have the extra
434
 
capacity to read it without impacting other queries/scans.</p>
435
 
<p>To run it, you should pick the <tt class="docutils literal"><span class="pre">total_segments</span></tt> to use, which is an integer
436
 
representing the number of temporary partitions you&#8217;d divide your table into.
437
 
You then need to spin up a thread/process for each one, giving each
438
 
thread/process a <tt class="docutils literal"><span class="pre">segment</span></tt>, which is a zero-based integer of the segment
439
 
you&#8217;d like to scan.</p>
440
 
<p>An example of using parallel scan to send out email to all users might look
441
 
something like:</p>
442
 
<div class="highlight-python"><div class="highlight"><pre><span class="c">#!/usr/bin/env python</span>
443
 
<span class="kn">import</span> <span class="nn">threading</span>
444
 
 
445
 
<span class="kn">import</span> <span class="nn">boto.ses</span>
446
 
<span class="kn">import</span> <span class="nn">boto.dynamodb2</span>
447
 
<span class="kn">from</span> <span class="nn">boto.dynamodb2.table</span> <span class="kn">import</span> <span class="n">Table</span>
448
 
 
449
 
 
450
 
<span class="n">AWS_ACCESS_KEY_ID</span> <span class="o">=</span> <span class="s">&#39;&lt;YOUR_AWS_KEY_ID&gt;&#39;</span>
451
 
<span class="n">AWS_SECRET_ACCESS_KEY</span> <span class="o">=</span> <span class="s">&#39;&lt;YOUR_AWS_SECRET_KEY&gt;&#39;</span>
452
 
<span class="n">APPROVED_EMAIL</span> <span class="o">=</span> <span class="s">&#39;some@address.com&#39;</span>
453
 
 
454
 
 
455
 
<span class="k">def</span> <span class="nf">send_email</span><span class="p">(</span><span class="n">email</span><span class="p">):</span>
456
 
    <span class="c"># Using Amazon&#39;s Simple Email Service, send an email to a given</span>
457
 
    <span class="c"># email address. You must already have an email you&#39;ve verified with</span>
458
 
    <span class="c"># AWS before this will work.</span>
459
 
    <span class="n">conn</span> <span class="o">=</span> <span class="n">boto</span><span class="o">.</span><span class="n">ses</span><span class="o">.</span><span class="n">connect_to_region</span><span class="p">(</span>
460
 
        <span class="s">&#39;us-east-1&#39;</span><span class="p">,</span>
461
 
        <span class="n">aws_access_key_id</span><span class="o">=</span><span class="n">AWS_ACCESS_KEY_ID</span><span class="p">,</span>
462
 
        <span class="n">aws_secret_access_key</span><span class="o">=</span><span class="n">AWS_SECRET_ACCESS_KEY</span>
463
 
    <span class="p">)</span>
464
 
    <span class="n">conn</span><span class="o">.</span><span class="n">send_email</span><span class="p">(</span>
465
 
        <span class="n">APPROVED_EMAIL</span><span class="p">,</span>
466
 
        <span class="s">&quot;[OurSite] New feature alert!&quot;</span><span class="p">,</span>
467
 
        <span class="s">&quot;We&#39;ve got some exciting news! We added a new feature to...&quot;</span><span class="p">,</span>
468
 
        <span class="p">[</span><span class="n">email</span><span class="p">]</span>
469
 
    <span class="p">)</span>
470
 
 
471
 
 
472
 
<span class="k">def</span> <span class="nf">process_segment</span><span class="p">(</span><span class="n">segment</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">total_segments</span><span class="o">=</span><span class="mi">10</span><span class="p">):</span>
473
 
    <span class="c"># This method/function is executed in each thread, each getting its</span>
474
 
    <span class="c"># own segment to process through.</span>
475
 
    <span class="n">conn</span> <span class="o">=</span> <span class="n">boto</span><span class="o">.</span><span class="n">dynamodb2</span><span class="o">.</span><span class="n">connect_to_region</span><span class="p">(</span>
476
 
        <span class="s">&#39;us-east-1&#39;</span><span class="p">,</span>
477
 
        <span class="n">aws_access_key_id</span><span class="o">=</span><span class="n">AWS_ACCESS_KEY_ID</span><span class="p">,</span>
478
 
        <span class="n">aws_secret_access_key</span><span class="o">=</span><span class="n">AWS_SECRET_ACCESS_KEY</span>
479
 
    <span class="p">)</span>
480
 
    <span class="n">table</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;users&#39;</span><span class="p">,</span> <span class="n">connection</span><span class="o">=</span><span class="n">conn</span><span class="p">)</span>
481
 
 
482
 
    <span class="c"># We pass in the segment &amp; total_segments to scan here.</span>
483
 
    <span class="k">for</span> <span class="n">user</span> <span class="ow">in</span> <span class="n">table</span><span class="o">.</span><span class="n">scan</span><span class="p">(</span><span class="n">segment</span><span class="o">=</span><span class="n">segment</span><span class="p">,</span> <span class="n">total_segments</span><span class="o">=</span><span class="n">total_segments</span><span class="p">):</span>
484
 
        <span class="n">send_email</span><span class="p">(</span><span class="n">user</span><span class="p">[</span><span class="s">&#39;email&#39;</span><span class="p">])</span>
485
 
 
486
 
 
487
 
<span class="k">def</span> <span class="nf">send_all_emails</span><span class="p">():</span>
488
 
    <span class="n">pool</span> <span class="o">=</span> <span class="p">[]</span>
489
 
    <span class="c"># We&#39;re choosing to divide the table in 3, then...</span>
490
 
    <span class="n">pool_size</span> <span class="o">=</span> <span class="mi">3</span>
491
 
 
492
 
    <span class="c"># ...spinning up a thread for each segment.</span>
493
 
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">pool_size</span><span class="p">):</span>
494
 
        <span class="n">worker</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span>
495
 
            <span class="n">target</span><span class="o">=</span><span class="n">process_segment</span><span class="p">,</span>
496
 
            <span class="n">kwargs</span><span class="o">=</span><span class="p">{</span>
497
 
                <span class="s">&#39;segment&#39;</span><span class="p">:</span> <span class="n">i</span><span class="p">,</span>
498
 
                <span class="s">&#39;total_segments&#39;</span><span class="p">:</span> <span class="n">pool_size</span><span class="p">,</span>
499
 
            <span class="p">}</span>
500
 
        <span class="p">)</span>
501
 
        <span class="n">pool</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">worker</span><span class="p">)</span>
502
 
        <span class="c"># We start them to let them start scanning &amp; consuming their</span>
503
 
        <span class="c"># assigned segment.</span>
504
 
        <span class="n">worker</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
505
 
 
506
 
    <span class="c"># Finally, we wait for each to finish.</span>
507
 
    <span class="k">for</span> <span class="n">thread</span> <span class="ow">in</span> <span class="n">pool</span><span class="p">:</span>
508
 
        <span class="n">thread</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
509
 
 
510
 
 
511
 
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
512
 
    <span class="n">send_all_emails</span><span class="p">()</span>
513
 
</pre></div>
514
 
</div>
515
 
</div>
516
 
<div class="section" id="batch-reading">
517
 
<h3>Batch Reading<a class="headerlink" href="#batch-reading" title="Permalink to this headline">¶</a></h3>
518
 
<p>Similar to batch writing, batch reading can also help reduce the number of
519
 
API requests necessary to access a large number of items. The
520
 
<tt class="docutils literal"><span class="pre">Table.batch_get</span></tt> method takes a list (or any sliceable collection) of keys
521
 
&amp; fetches all of them, presented as an iterator interface.</p>
522
 
<p>This is done lazily, so if you never iterate over the results, no requests are
523
 
executed. Additionally, if you only iterate over part of the set, the minumum
524
 
number of calls are made to fetch those results (typically max 100 per
525
 
response).</p>
526
 
<p>Example:</p>
527
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">boto.dynamodb2.table</span> <span class="kn">import</span> <span class="n">Table</span>
528
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;users&#39;</span><span class="p">)</span>
529
 
 
530
 
<span class="go"># No request yet.</span>
531
 
<span class="gp">&gt;&gt;&gt; </span><span class="n">many_users</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">batch_get</span><span class="p">(</span><span class="n">keys</span><span class="o">=</span><span class="p">[</span>
532
 
<span class="go">    {&#39;username&#39;: &#39;alice&#39;},</span>
533
 
<span class="go">    {&#39;username&#39;: &#39;bob&#39;},</span>
534
 
<span class="go">    {&#39;username&#39;: &#39;fred&#39;},</span>
535
 
<span class="go">    {&#39;username&#39;: &#39;jane&#39;},</span>
536
 
<span class="go">    {&#39;username&#39;: &#39;johndoe&#39;},</span>
537
 
<span class="go">])</span>
538
 
 
539
 
<span class="go"># Now the request is performed, requesting all five in one request.</span>
540
 
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">user</span> <span class="ow">in</span> <span class="n">many_users</span><span class="p">:</span>
541
 
<span class="gp">... </span>    <span class="k">print</span> <span class="n">user</span><span class="p">[</span><span class="s">&#39;first_name&#39;</span><span class="p">]</span>
542
 
<span class="go">&#39;Alice&#39;</span>
543
 
<span class="go">&#39;Bobby&#39;</span>
544
 
<span class="go">&#39;Fred&#39;</span>
545
 
<span class="go">&#39;Jane&#39;</span>
546
 
<span class="go">&#39;John&#39;</span>
547
 
</pre></div>
548
 
</div>
549
 
</div>
550
 
<div class="section" id="deleting-a-table">
551
 
<h3>Deleting a Table<a class="headerlink" href="#deleting-a-table" title="Permalink to this headline">¶</a></h3>
552
 
<p>Deleting a table is a simple exercise. When you no longer need a table, simply
553
 
run:</p>
554
 
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">users</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
555
 
</pre></div>
556
 
</div>
557
 
</div>
558
 
<div class="section" id="dynamodb-local">
559
 
<h3>DynamoDB Local<a class="headerlink" href="#dynamodb-local" title="Permalink to this headline">¶</a></h3>
560
 
<p><a class="reference external" href="http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Tools.html">Amazon DynamoDB Local</a> is a utility which can be used to mock DynamoDB
561
 
during development. Connecting to a running DynamoDB Local server is easy:</p>
562
 
<div class="highlight-python"><div class="highlight"><pre><span class="c">#!/usr/bin/env python</span>
563
 
<span class="kn">from</span> <span class="nn">boto.dynamodb2.layer1</span> <span class="kn">import</span> <span class="n">DynamoDBConnection</span>
564
 
 
565
 
 
566
 
<span class="c"># Connect to DynamoDB Local</span>
567
 
<span class="n">conn</span> <span class="o">=</span> <span class="n">DynamoDBConnection</span><span class="p">(</span>
568
 
    <span class="n">host</span><span class="o">=</span><span class="s">&#39;localhost&#39;</span><span class="p">,</span>
569
 
    <span class="n">port</span><span class="o">=</span><span class="mi">8000</span><span class="p">,</span>
570
 
    <span class="n">aws_secret_access_key</span><span class="o">=</span><span class="s">&#39;anything&#39;</span><span class="p">,</span>
571
 
    <span class="n">is_secure</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
572
 
 
573
 
<span class="c"># List all local tables</span>
574
 
<span class="n">tables</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">list_tables</span><span class="p">()</span>
575
 
</pre></div>
576
 
</div>
577
 
</div>
578
 
<div class="section" id="next-steps">
579
 
<h3>Next Steps<a class="headerlink" href="#next-steps" title="Permalink to this headline">¶</a></h3>
580
 
<p>You can find additional information about other calls &amp; parameter options
581
 
in the <a class="reference internal" href="ref/dynamodb2.html"><em>API docs</em></a>.</p>
582
 
</div>
583
 
</div>
584
 
</div>
585
 
 
586
 
 
587
 
          </div>
588
 
        </div>
589
 
      </div>
590
 
      <div class="sphinxsidebar">
591
 
        <div class="sphinxsidebarwrapper">
592
 
  <h3><a href="index.html">Table Of Contents</a></h3>
593
 
  <ul>
594
 
<li><a class="reference internal" href="#">An Introduction to boto&#8217;s DynamoDB v2 interface</a><ul>
595
 
<li><a class="reference internal" href="#the-high-level-api">The High-Level API</a><ul>
596
 
<li><a class="reference internal" href="#creating-a-new-table">Creating a New Table</a></li>
597
 
<li><a class="reference internal" href="#using-an-existing-table">Using an Existing Table</a></li>
598
 
<li><a class="reference internal" href="#creating-a-new-item">Creating a New Item</a></li>
599
 
<li><a class="reference internal" href="#getting-an-item-accessing-data">Getting an Item &amp; Accessing Data</a></li>
600
 
<li><a class="reference internal" href="#updating-an-item">Updating an Item</a></li>
601
 
<li><a class="reference internal" href="#deleting-an-item">Deleting an Item</a></li>
602
 
<li><a class="reference internal" href="#batch-writing">Batch Writing</a></li>
603
 
<li><a class="reference internal" href="#querying">Querying</a></li>
604
 
<li><a class="reference internal" href="#parallel-scan">Parallel Scan</a></li>
605
 
<li><a class="reference internal" href="#batch-reading">Batch Reading</a></li>
606
 
<li><a class="reference internal" href="#deleting-a-table">Deleting a Table</a></li>
607
 
<li><a class="reference internal" href="#dynamodb-local">DynamoDB Local</a></li>
608
 
<li><a class="reference internal" href="#next-steps">Next Steps</a></li>
609
 
</ul>
610
 
</li>
611
 
</ul>
612
 
</li>
613
 
</ul>
614
 
 
615
 
  <h4>Previous topic</h4>
616
 
  <p class="topless"><a href="support_tut.html"
617
 
                        title="previous chapter">An Introduction to boto&#8217;s Support interface</a></p>
618
 
  <h4>Next topic</h4>
619
 
  <p class="topless"><a href="migrations/dynamodb_v1_to_v2.html"
620
 
                        title="next chapter">Migrating from DynamoDB v1 to DynamoDB v2</a></p>
621
 
  <h3>This Page</h3>
622
 
  <ul class="this-page-menu">
623
 
    <li><a href="_sources/dynamodb2_tut.txt"
624
 
           rel="nofollow">Show Source</a></li>
625
 
  </ul>
626
 
<div id="searchbox" style="display: none">
627
 
  <h3>Quick search</h3>
628
 
    <form class="search" action="search.html" method="get">
629
 
      <input type="text" name="q" />
630
 
      <input type="submit" value="Go" />
631
 
      <input type="hidden" name="check_keywords" value="yes" />
632
 
      <input type="hidden" name="area" value="default" />
633
 
    </form>
634
 
    <p class="searchtip" style="font-size: 90%">
635
 
    Enter search terms or a module, class or function name.
636
 
    </p>
637
 
</div>
638
 
<script type="text/javascript">$('#searchbox').show(0);</script><div><a href="boto.pdf">PDF Version</a></div>
639
 
        </div>
640
 
      </div>
641
 
      <div class="clearer"></div>
642
 
    </div>
643
 
    <div class="related">
644
 
      <h3>Navigation</h3>
645
 
      <ul>
646
 
        <li class="right" style="margin-right: 10px">
647
 
          <a href="genindex.html" title="General Index"
648
 
             >index</a></li>
649
 
        <li class="right" >
650
 
          <a href="py-modindex.html" title="Python Module Index"
651
 
             >modules</a> |</li>
652
 
        <li class="right" >
653
 
          <a href="migrations/dynamodb_v1_to_v2.html" title="Migrating from DynamoDB v1 to DynamoDB v2"
654
 
             >next</a> |</li>
655
 
        <li class="right" >
656
 
          <a href="support_tut.html" title="An Introduction to boto’s Support interface"
657
 
             >previous</a> |</li>
658
 
        <li><a href="index.html">boto v2.16.0</a> &raquo;</li> 
659
 
      </ul>
660
 
    </div>
661
 
    <div class="footer">
662
 
        &copy; Copyright 2009,2010, Mitch Garnaat.
663
 
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
664
 
    </div>
665
 
  </body>
666
 
</html>
 
 
b'\\ No newline at end of file'