blob: 97955d5a494522de9c36c2fed277e4208d49495f [file] [log] [blame]
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Data Store Best Practices &mdash; Apache Usergrid 1.0 documentation</title>
<link rel="stylesheet" href="../_static/css/theme.css" type="text/css" />
<link rel="top" title="Apache Usergrid 1.0 documentation" href="../index.html"/>
<link rel="next" title="Collections" href="collections.html"/>
<link rel="prev" title="The Usergrid Data Store" href="data-store-dbms.html"/>
<script src="../_static/js/modernizr.min.js"></script>
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-nav-search">
<a href="../index.html" class="icon icon-home"> Apache Usergrid
</a>
<div class="version">
1.0
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<p class="caption"><span class="caption-text">Getting Started</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../introduction/overview.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="../introduction/usergrid-features.html">Usergrid Features</a></li>
<li class="toctree-l1"><a class="reference internal" href="../introduction/data-model.html">Usergrid Data model</a></li>
<li class="toctree-l1"><a class="reference internal" href="../introduction/async-vs-sync.html">Async vs. sync calls</a></li>
</ul>
<p class="caption"><span class="caption-text">Using Usergrid</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../using-usergrid/creating-account.html">Creating a Usergrid Account</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using-usergrid/creating-a-new-application.html">Creating a new application</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using-usergrid/using-a-sandbox-app.html">Using a Sandbox Application</a></li>
<li class="toctree-l1"><a class="reference internal" href="../using-usergrid/using-the-api.html">Using the API</a></li>
</ul>
<p class="caption"><span class="caption-text">Data Storage</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="data-store-dbms.html">The Usergrid Data Store</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="">Data Store Best Practices</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#put-your-data-in-as-you-ll-want-to-get-it-out">Put your data in as you&#8217;ll want to get it out</a></li>
<li class="toctree-l2"><a class="reference internal" href="#best-practice-denormalize-for-pre-computed-query-results">Best practice: Denormalize for pre-computed query results</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#getting-review-data-the-relational-way">Getting review data the relational way</a></li>
<li class="toctree-l3"><a class="reference internal" href="#using-a-denormalized-model-to-store-then-retrieve-data">Using a denormalized model to store (then retrieve) data</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="collections.html">Collections</a></li>
<li class="toctree-l1"><a class="reference internal" href="entities.html">Entities</a></li>
</ul>
<p class="caption"><span class="caption-text">Data Queries</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../data-queries/querying-your-data.html">Querying your data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../data-queries/query-parameters.html">Query parameters &amp; clauses</a></li>
<li class="toctree-l1"><a class="reference internal" href="../data-queries/operators-and-types.html">Query operators &amp; data types</a></li>
<li class="toctree-l1"><a class="reference internal" href="../data-queries/advanced-query-usage.html">Advanced query usage</a></li>
</ul>
<p class="caption"><span class="caption-text">Entity Connections</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../entity-connections/connecting-entities.html">Connecting entities</a></li>
<li class="toctree-l1"><a class="reference internal" href="../entity-connections/retrieving-entities.html">Retrieving connections</a></li>
<li class="toctree-l1"><a class="reference internal" href="../entity-connections/disconnecting-entities.html">Disconnecting entities</a></li>
</ul>
<p class="caption"><span class="caption-text">Push Notifications</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../push-notifications/overview.html">Push notifications overview</a></li>
<li class="toctree-l1"><a class="reference internal" href="../push-notifications/adding-push-support.html">Adding push notifications support</a></li>
<li class="toctree-l1"><a class="reference internal" href="../push-notifications/getting-started.html">Getting started with push notifications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../push-notifications/tutorial.html">Tutorial: Push notifications sample app</a></li>
<li class="toctree-l1"><a class="reference internal" href="../push-notifications/registering.html">Registering with a notification service</a></li>
<li class="toctree-l1"><a class="reference internal" href="../push-notifications/creating-notifiers.html">Creating notifiers</a></li>
<li class="toctree-l1"><a class="reference internal" href="../push-notifications/managing-users-and-devices.html">Managing users and devices</a></li>
<li class="toctree-l1"><a class="reference internal" href="../push-notifications/creating-and-managing-notifications.html">Creating and managing notifications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../push-notifications/troubleshooting.html">Troubleshooting</a></li>
</ul>
<p class="caption"><span class="caption-text">Security &amp; Authentication</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../security-and-auth/app-security.html">Security &amp; token authentication</a></li>
<li class="toctree-l1"><a class="reference internal" href="../security-and-auth/using-permissions.html">Using permissions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../security-and-auth/using-roles.html">Using roles</a></li>
<li class="toctree-l1"><a class="reference internal" href="../security-and-auth/authenticating-users-and-application-clients.html">Authenticating users &amp; app clients</a></li>
<li class="toctree-l1"><a class="reference internal" href="../security-and-auth/user-authentication-types.html">Authentication levels</a></li>
<li class="toctree-l1"><a class="reference internal" href="../security-and-auth/changing-token-time-live-ttl.html">Changing token expiration (time-to-live)</a></li>
<li class="toctree-l1"><a class="reference internal" href="../security-and-auth/authenticating-api-requests.html">Authenticating API requests</a></li>
<li class="toctree-l1"><a class="reference internal" href="../security-and-auth/revoking-tokens-logout.html">Revoking tokens (logout)</a></li>
<li class="toctree-l1"><a class="reference internal" href="../security-and-auth/facebook-sign.html">Facebook sign in</a></li>
<li class="toctree-l1"><a class="reference internal" href="../security-and-auth/securing-your-app.html">Security best practices</a></li>
</ul>
<p class="caption"><span class="caption-text">User Management &amp; Social Graph</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../user-management/user-management.html">User management &amp; social graph</a></li>
<li class="toctree-l1"><a class="reference internal" href="../user-management/working-user-data.html">Working with User Data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../user-management/group.html">Working with group data</a></li>
<li class="toctree-l1"><a class="reference internal" href="../user-management/activity.html">Activity</a></li>
<li class="toctree-l1"><a class="reference internal" href="../user-management/user-connections.html">Social Graph Connections</a></li>
<li class="toctree-l1"><a class="reference internal" href="../user-management/user-connections.html#creating-other-connections">Creating other connections</a></li>
<li class="toctree-l1"><a class="reference internal" href="../user-management/messagee-example.html">App Example - Messagee</a></li>
</ul>
<p class="caption"><span class="caption-text">Geo-location</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../geolocation/geolocation.html">Geolocating your Entities</a></li>
</ul>
<p class="caption"><span class="caption-text">Assets &amp; Files</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../assets-and-files/uploading-assets.html">Uploading assets</a></li>
<li class="toctree-l1"><a class="reference internal" href="../assets-and-files/retrieving-assets.html">Retrieving assets</a></li>
<li class="toctree-l1"><a class="reference internal" href="../assets-and-files/folders.html">Folders</a></li>
</ul>
<p class="caption"><span class="caption-text">Counters &amp; Events</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../counters-and-events/events-and-counters.html">Counters &amp; events</a></li>
<li class="toctree-l1"><a class="reference internal" href="../counters-and-events/creating-and-incrementing-counters.html">Creating &amp; incrementing counters</a></li>
<li class="toctree-l1"><a class="reference internal" href="../counters-and-events/creating-and-incrementing-counters.html#decrementing-resetting-counters">Decrementing/resetting counters</a></li>
<li class="toctree-l1"><a class="reference internal" href="../counters-and-events/creating-and-incrementing-counters.html#using-counters-hierarchically">Using counters hierarchically</a></li>
<li class="toctree-l1"><a class="reference internal" href="../counters-and-events/retrieving-counters.html">Retrieving counters</a></li>
</ul>
<p class="caption"><span class="caption-text">Organizations &amp; Applications</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../orgs-and-apps/managing.html">Organization &amp; application management</a></li>
<li class="toctree-l1"><a class="reference internal" href="../orgs-and-apps/organization.html">Organization</a></li>
<li class="toctree-l1"><a class="reference internal" href="../orgs-and-apps/application.html">Application</a></li>
<li class="toctree-l1"><a class="reference internal" href="../orgs-and-apps/admin-user.html">Admin user</a></li>
</ul>
<p class="caption"><span class="caption-text">API Reference</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../rest-endpoints/api-docs.html">Methods</a></li>
<li class="toctree-l1"><a class="reference internal" href="../rest-endpoints/api-docs.html#models">Models</a></li>
<li class="toctree-l1"><a class="reference internal" href="../rest-endpoints/api-docs.html#sub-types">Sub-Types</a></li>
</ul>
<p class="caption"><span class="caption-text">Client SDKs</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../sdks/tbd.html">COMING SOON...</a></li>
</ul>
<p class="caption"><span class="caption-text">Installing Usergrid</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../installation/deployment-guide.html">Usergrid 2.1.0 Deployment Guide</a></li>
</ul>
<p class="caption"><span class="caption-text">More about Usergrid</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../reference/presos-and-videos.html">Presentations &amp; Videos</a></li>
<li class="toctree-l1"><a class="reference internal" href="../reference/contribute-code.html">How to Contribute Code &amp; Docs</a></li>
</ul>
</div>
&nbsp;
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../index.html">Apache Usergrid</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="../index.html">Docs</a> &raquo;</li>
<li>Data Store Best Practices</li>
<li class="wy-breadcrumbs-aside">
<a href="../_sources/data-storage/optimizing-access.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="data-store-best-practices">
<h1>Data Store Best Practices<a class="headerlink" href="#data-store-best-practices" title="Permalink to this headline"></a></h1>
<p>The Usergrid data store is backed by Cassandra, an open source
distributed DBMS. Cassandra is specifically designed to support
applications that need flexibility and high scalability, particularly
web and mobile applications. To get the most out of your Usergrid
application, you should optimize your data access with this kind of
database in mind.</p>
<div class="section" id="put-your-data-in-as-you-ll-want-to-get-it-out">
<h2>Put your data in as you&#8217;ll want to get it out<a class="headerlink" href="#put-your-data-in-as-you-ll-want-to-get-it-out" title="Permalink to this headline"></a></h2>
<p>The best practices described here are all related to the theme of
putting your data in the way you’ll want to get it out. You’ll model
your data with your likely read requests in mind rather than by modeling
around the structure of the data itself (as you might with a relational
database). In many cases, you can avoid using queries that are
inefficient for this kind of database.</p>
<p>You can use the following techniques to optimize data store access:</p>
<ul class="simple">
<li><strong>Denormalize and duplicate</strong>. By creating a data model that
strategically denormalizes and duplicates data, you can avoid costly
queries. In other words, you model the data so that all of the data
for a given request is all in one place rather than scattered in a
way that a query must account for.</li>
<li><strong>Create direct paths to the data you’ll want</strong>. You can optimize
your app’s performance by connecting entities your code retrieves
most often. With connections, you can avoid some queries that might
add complexity and reduce performance.</li>
</ul>
</div>
<div class="section" id="best-practice-denormalize-for-pre-computed-query-results">
<h2>Best practice: Denormalize for pre-computed query results<a class="headerlink" href="#best-practice-denormalize-for-pre-computed-query-results" title="Permalink to this headline"></a></h2>
<p>If you’re familiar with designing relational databases, you’re probably
used to normalizing the structure of your data as much as possible. When
normalizing an RDBMS data model, you minimize redundancy by ensuring
that a column from one table is duplicated only once in any other table,
and only when necessary to create primary/secondary key relationships.
You then retrieve data that spans tables by joining them with an SQL
query.</p>
<p>In contrast, with the Usergrid data store you’ll get better performance
by strategically denormalizing and duplicating data. When you
denormalize, you combine data from what might (in a relational model)
have been separate tables. When duplicating, you intentionally maintain
copies of certain entity properties across multiple entities. By
denormalizing and duplicating, you can collect the results of requests
into a single entity rather than relying on a query.</p>
<p>Part of designing your data model should include identifying the queries
your client will make. Then in your data model design, you capture the
results of those queries in advance by writing that data into entities
of one collection you can read from later.</p>
<div class="section" id="getting-review-data-the-relational-way">
<h3>Getting review data the relational way<a class="headerlink" href="#getting-review-data-the-relational-way" title="Permalink to this headline"></a></h3>
<p>For example, take a closer look at the relational case through a product
database. Imagine you want to present a list of all reviews for a
product. When a user chooses a review from the list, you’ll show them a
view that includes the review’s title, body, and rating; the product it
describes; and who wrote the review. That way, your user will be able to
click through to more information about the product or reviewing user.</p>
<p>In a relational database, you’d likely have separate tables for the
review-specific information and a rating; for the product; and for the
user. Your reviews table would include secondary keys with which to join
reviews to the users and products tables. Maybe something like this:</p>
<img alt="../_images/reviews.png" src="../_images/reviews.png" />
<p>To get the data you need, your query might look like the SQL query
below. By getting UUIDs for the user and product into your client code,
you’re able to give the user a way to get user and product information
from the review.</p>
<div class="highlight-python"><div class="highlight"><pre>SELECT review.title, review.body, review.rating, review.uuid,
user.name, user.uuid, product.name, product.uuid
FROM reviews
INNER JOIN users
ON users.uuid = reviews.authorId
INNER JOIN products
ON products.uuid = reviews.productId
WHERE reviews.uuid = &lt;uuid_for_selected_review&gt;
</pre></div>
</div>
<p>But due to Cassandra’s distributed, high-scale design, a join such as
this wouldn’t work. So in the Usergrid, you’d get the data by first
storing it all in one place.</p>
</div>
<div class="section" id="using-a-denormalized-model-to-store-then-retrieve-data">
<h3>Using a denormalized model to store (then retrieve) data<a class="headerlink" href="#using-a-denormalized-model-to-store-then-retrieve-data" title="Permalink to this headline"></a></h3>
<p>In the Usergrid, a more efficient way to get the same result would start
by including related user and product data with the review data. This
would give you a single place to get all the data you&#8217;ll show.</p>
<p>The following shows how that model might look as entities in the
Usergrid. (The users and products entities are included here to remind
you that they exist, but they aren’t actually used in this
denormalization example.)</p>
<img alt="../_images/reviews2.png" src="../_images/reviews2.png" />
<p>This use case assumes that your user and product data are already in the
data store. In the following API request code, you’re just adding a new
review written by a user about a particular product. The JSON body is
your new review entity (the JSON here is non-entitized to make it
readable).</p>
<div class="highlight-python"><div class="highlight"><pre>POST https://api.usergrid.com/my_org/my_app/reviews -d {
&quot;title&quot; : &quot;Tempted to climb in myself.&quot;,
&quot;body&quot; : &quot;I mean, who doesn&#39;t love a bouncy castle? The kids love it!&quot;,
&quot;rating&quot; : 3,
&quot;authorName&quot; : &quot;Jennie&quot;,
&quot;authorUUID&quot; : &lt;author_uuid&gt;,
&quot;authorImage&quot; : &quot;http://&lt;path_to_image&gt;.png&quot;,
&quot;productUUID&quot; : &lt;product_uuid&gt;,
&quot;productImage&quot; : &quot;http://&lt;path_to_image&gt;.jpg&quot;,
&quot;productName&quot; : &quot;Magic Castle Bounce House Inflatable Bouncer&quot;
}
</pre></div>
</div>
<p>Notice that you’re adding user and product data (which your client code
would have at hand when the user posts the review) when you’re adding
the review-specific data.</p>
<p>Retrieving all the data from one place You’d get the review, including
the subset of product and user data you need right away, by making one
API call such as the following (note there’s no SQL-like query string
needed):</p>
<div class="highlight-python"><div class="highlight"><pre>GET http://api.usergrid.com/my_org/my_app/reviews/&lt;review_uuid&gt;
</pre></div>
</div>
<p>Your result might look like this. The highlighted lines show data you&#8217;d
present to the user.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">&quot;action&quot;</span> <span class="p">:</span> <span class="s">&quot;get&quot;</span><span class="p">,</span>
<span class="s">&quot;application&quot;</span> <span class="p">:</span> <span class="s">&quot;&lt;app_uuid&gt;&quot;</span><span class="p">,</span>
<span class="s">&quot;params&quot;</span> <span class="p">:</span> <span class="p">{</span> <span class="p">},</span>
<span class="s">&quot;path&quot;</span> <span class="p">:</span> <span class="s">&quot;/reviews&quot;</span><span class="p">,</span>
<span class="s">&quot;uri&quot;</span> <span class="p">:</span> <span class="s">&quot;https://api.usergrid.com/my_org/my_app/reviews&quot;</span><span class="p">,</span>
<span class="s">&quot;entities&quot;</span> <span class="p">:</span> <span class="p">[</span> <span class="p">{</span>
<span class="s">&quot;uuid&quot;</span> <span class="p">:</span> <span class="s">&quot;&lt;review_uuid&gt;&quot;</span><span class="p">,</span>
<span class="s">&quot;type&quot;</span> <span class="p">:</span> <span class="s">&quot;review&quot;</span><span class="p">,</span>
<span class="s">&quot;created&quot;</span> <span class="p">:</span> <span class="mi">1395410364673</span><span class="p">,</span>
<span class="s">&quot;modified&quot;</span> <span class="p">:</span> <span class="mi">1395410364673</span><span class="p">,</span>
<span class="s">&quot;authorName&quot;</span> <span class="p">:</span> <span class="s">&quot;Jennie&quot;</span><span class="p">,</span>
<span class="s">&quot;authorImage&quot;</span> <span class="p">:</span> <span class="s">&quot;&lt;path_to_image&gt;.png&quot;</span><span class="p">,</span>
<span class="s">&quot;authorUUID&quot;</span> <span class="p">:</span> <span class="s">&quot;&lt;author_uuid&gt;&quot;</span><span class="p">,</span>
<span class="s">&quot;body&quot;</span> <span class="p">:</span> <span class="s">&quot;I mean, who doesn&#39;t love a bouncy castle? The kids love it!&quot;</span><span class="p">,</span>
<span class="s">&quot;metadata&quot;</span> <span class="p">:</span> <span class="p">{</span>
<span class="s">&quot;path&quot;</span> <span class="p">:</span> <span class="s">&quot;/reviews/&lt;review_uuid&gt;&quot;</span>
<span class="p">},</span>
<span class="s">&quot;productImage&quot;</span> <span class="p">:</span> <span class="s">&quot;http://&lt;path_to_image&gt;.jpg&quot;</span><span class="p">,</span>
<span class="s">&quot;productName&quot;</span> <span class="p">:</span> <span class="s">&quot;Magic Castle Bounce House Inflatable Bouncer&quot;</span><span class="p">,</span>
<span class="s">&quot;productUUID&quot;</span> <span class="p">:</span> <span class="s">&quot;&lt;product_uuid&gt;&quot;</span><span class="p">,</span>
<span class="s">&quot;rating&quot;</span> <span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
<span class="s">&quot;title&quot;</span> <span class="p">:</span> <span class="s">&quot;Tempted to climb in myself.&quot;</span>
<span class="p">}</span> <span class="p">],</span>
<span class="s">&quot;timestamp&quot;</span> <span class="p">:</span> <span class="mi">1395764951934</span><span class="p">,</span>
<span class="s">&quot;duration&quot;</span> <span class="p">:</span> <span class="mi">16</span><span class="p">,</span>
<span class="s">&quot;organization&quot;</span> <span class="p">:</span> <span class="s">&quot;my_org&quot;</span><span class="p">,</span>
<span class="s">&quot;applicationName&quot;</span> <span class="p">:</span> <span class="s">&quot;my_app&quot;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This gives you, in one request, all the review information you’d planned
on presenting to your app’s users for a single view. Your client code
could retrieve the review entity in the result, along with the product
and user data, then present it all as a review.</p>
<p>Best practice: Connect entities to simplify scoped requests Another way
to streamline your requests is to connect entities by using the built-in
connections feature. In a sense, a connection can replace the WHERE
clause of a query you might have written.</p>
<p>Getting back to the review example, imagine you want to retrieve all of
the reviews written by a particular user. In the relational example, you
might have an SQL query such as this:</p>
<div class="highlight-python"><div class="highlight"><pre>SELECT * FROM reviews WHERE authorId = &lt;user_uuid&gt;;
</pre></div>
</div>
<p>Even in the Usergrid, you could use a similar syntax in a query string
appended to an API path. Working from the review entity model in the
preceding example, that might look like this (though yours would likely
entitize the spaces):</p>
<div class="highlight-python"><div class="highlight"><pre>GET http://api.usergrid.com/my_org/my_app/reviews?ql=select * where
authorUUID=&lt;user_uuid&gt;
</pre></div>
</div>
<p>But if this is an API call you’re going to be making often, there’s a
better way. Instead, create a connection between the review and the user
when your code creates the review. You can connect entities with a verb
that describes their relationship to one another.</p>
<p>The following creates Jennie’s review and at the same time connects her
as the person who “wrote” it. (For easier reading, this example contains
spaces you wouldn’t be able to include.)</p>
<div class="highlight-python"><div class="highlight"><pre>POST http://api.usergrid.com/my_org/my_app/users/jennie/wrote/reviews {
&quot;title&quot; : &quot;Tempted to climb in myself.&quot;,
&quot;body&quot; : &quot;I mean, who doesn&#39;t love a bouncy castle? The kids love it!&quot;,
&quot;rating&quot; : 3,
&quot;authorName&quot; : &quot;Jennie&quot;,
&quot;authorImage&quot; : &quot;http://&lt;path_to_image&gt;.png&quot;,
&quot;productName&quot; : &quot;Magic Castle Bounce House Inflatable Bouncer&quot;,
&quot;productImage&quot; : &quot;http://&lt;path_to_image&gt;.jpg&quot;
}
</pre></div>
</div>
<p>When reading the data, you’d retrieve all of the reviews Jennie has
written with a URL that’s nearly identical, minus the JSON:</p>
<div class="highlight-python"><div class="highlight"><pre>GET http://api.usergrid.com/my_org/my_app/users/jennie/wrote/reviews
</pre></div>
</div>
<p>Your request result would look something like the following. Here, the
entities array returned contains the reviews you connected with Jennie
(though there’s only one in this example). The connection-specific
metadata is highlighted.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">&quot;action&quot;</span> <span class="p">:</span> <span class="s">&quot;get&quot;</span><span class="p">,</span>
<span class="s">&quot;application&quot;</span> <span class="p">:</span> <span class="s">&quot;&lt;app_uuid&gt;&quot;</span><span class="p">,</span>
<span class="s">&quot;params&quot;</span> <span class="p">:</span> <span class="p">{</span> <span class="p">},</span>
<span class="s">&quot;path&quot;</span> <span class="p">:</span> <span class="s">&quot;/users/&lt;user_uuid&gt;/wrote&quot;</span><span class="p">,</span>
<span class="s">&quot;uri&quot;</span> <span class="p">:</span> <span class="s">&quot;https://api.usergrid.com/my_org/my_app/users/&lt;user_uuid&gt;/wrote&quot;</span><span class="p">,</span>
<span class="s">&quot;entities&quot;</span> <span class="p">:</span> <span class="p">[</span> <span class="p">{</span>
<span class="s">&quot;uuid&quot;</span> <span class="p">:</span> <span class="s">&quot;&lt;review_uuid&gt;&quot;</span><span class="p">,</span>
<span class="s">&quot;type&quot;</span> <span class="p">:</span> <span class="s">&quot;review&quot;</span><span class="p">,</span>
<span class="s">&quot;created&quot;</span> <span class="p">:</span> <span class="mi">1395410364673</span><span class="p">,</span>
<span class="s">&quot;modified&quot;</span> <span class="p">:</span> <span class="mi">1395410364673</span><span class="p">,</span>
<span class="s">&quot;authorName&quot;</span> <span class="p">:</span> <span class="s">&quot;Jennie&quot;</span><span class="p">,</span>
<span class="s">&quot;authorImage&quot;</span> <span class="p">:</span> <span class="s">&quot;http://&lt;path_to_image&gt;.png&quot;</span><span class="p">,</span>
<span class="s">&quot;authorUUID&quot;</span> <span class="p">:</span> <span class="s">&quot;&lt;user_uuid&gt;&quot;</span><span class="p">,</span>
<span class="s">&quot;body&quot;</span> <span class="p">:</span> <span class="s">&quot;I mean, who doesn&#39;t love a bouncy castle? Kids love it!&quot;</span><span class="p">,</span>
<span class="s">&quot;metadata&quot;</span> <span class="p">:</span> <span class="p">{</span>
<span class="s">&quot;connecting&quot;</span> <span class="p">:</span> <span class="p">{</span>
<span class="s">&quot;wrote&quot;</span> <span class="p">:</span> <span class="s">&quot;/users/&lt;user_uuid&gt;/wrote/&lt;review_uuid&gt;/connecting/wrote&quot;</span>
<span class="p">},</span>
<span class="s">&quot;path&quot;</span> <span class="p">:</span> <span class="s">&quot;/users/&lt;user_uuid&gt;/wrote/&lt;review_uuid&gt;&quot;</span><span class="p">,</span>
<span class="p">},</span>
<span class="s">&quot;productImage&quot;</span> <span class="p">:</span> <span class="s">&quot;http://&lt;path_to_image&gt;.jpg&quot;</span><span class="p">,</span>
<span class="s">&quot;productName&quot;</span> <span class="p">:</span> <span class="s">&quot;Magic Castle Bounce House Inflatable Bouncer&quot;</span><span class="p">,</span>
<span class="s">&quot;productUUID&quot;</span> <span class="p">:</span> <span class="s">&quot;&lt;product_uuid&gt;&quot;</span><span class="p">,</span>
<span class="s">&quot;rating&quot;</span> <span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
<span class="s">&quot;title&quot;</span> <span class="p">:</span> <span class="s">&quot;Tempted to climb in myself.&quot;</span>
<span class="p">}</span> <span class="p">],</span>
<span class="s">&quot;timestamp&quot;</span> <span class="p">:</span> <span class="mi">1395777037697</span><span class="p">,</span>
<span class="s">&quot;duration&quot;</span> <span class="p">:</span> <span class="mi">19</span><span class="p">,</span>
<span class="s">&quot;organization&quot;</span> <span class="p">:</span> <span class="s">&quot;my_org&quot;</span><span class="p">,</span>
<span class="s">&quot;applicationName&quot;</span> <span class="p">:</span> <span class="s">&quot;my_app&quot;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>To retrieve a particular review written by Jennie, you could use
something like the following:</p>
<div class="highlight-python"><div class="highlight"><pre>GET http://api.usergrid.com/my_org/my_app/users/jennie/wrote/reviews/&lt;review_uuid&gt;
</pre></div>
</div>
<p>You can create connections to set up relationships you can use to later
retrieve data quickly and with a simple syntax.</p>
<p>For example, when creating a connected entity (such as the review entity
here), you can at the same time create other connections to connect the
product to the new review, then connect the product to its reviewer
(paths are abbreviated in these examples):</p>
<div class="highlight-python"><div class="highlight"><pre>POST /users/jennie/wrote/reviews {&lt;review_entity_json&gt;}
POST /products/&lt;reviewed_product_uuid&gt;/reviewedIn/reviews/&lt;new_review_uuid&gt;
POST /products/&lt;reviewed_product_uuid&gt;/reviewedBy/users/jennie
</pre></div>
</div>
<p>Having created these connections for each review you post, in addition
to getting the review the user wrote, you could later also:</p>
<p>Get the reviews for a product:</p>
<div class="highlight-python"><div class="highlight"><pre>GET /products/&lt;reviewed_product_uuid&gt;/reviewedIn/reviews
Get the users who reviewed the product:
GET /products/&lt;reviewed_product_uuid&gt;/reviewedBy/users
</pre></div>
</div>
</div>
</div>
</div>
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
<a href="collections.html" class="btn btn-neutral float-right" title="Collections" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
<a href="data-store-dbms.html" class="btn btn-neutral" title="The Usergrid Data Store" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
</div>
<hr/>
<div role="contentinfo">
<p>
&copy; Copyright 2013-2015, Apache Usergrid.
</p>
</div>
Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'../',
VERSION:'1.0',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<script type="text/javascript" src="../_static/js/theme.js"></script>
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.StickyNav.enable();
});
</script>
</body>
</html>