foundationdb/simple-indexes.html

382 lines
28 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Simple Indexes &#8212; FoundationDB ON documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
<script src="_static/doctools.js"></script>
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="Simple Indexes" href="simple-indexes-java.html" />
<link rel="prev" title="Segmented Range Reads" href="segmented-range-reads-java.html" />
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1'>
<meta name="apple-mobile-web-app-capable" content="yes">
<script type="text/javascript" src="_static/js/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="_static/js/jquery-fix.js"></script>
<script type="text/javascript" src="_static/bootstrap-3.4.1/js/bootstrap.min.js"></script>
<script type="text/javascript" src="_static/bootstrap-sphinx.js"></script>
</head><body>
<div id="navbar" class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<!-- .btn-navbar is used as the toggle for collapsed navbar content -->
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">
FoundationDB</a>
<span class="navbar-text navbar-version pull-left"><b>7.3.57</b></span>
</div>
<div class="collapse navbar-collapse nav-collapse">
<ul class="nav navbar-nav">
<li><a href="contents.html">Site Map</a></li>
<li class="dropdown globaltoc-container">
<a role="button"
id="dLabelGlobalToc"
data-toggle="dropdown"
data-target="#"
href="index.html">Site <b class="caret"></b></a>
<ul class="dropdown-menu globaltoc"
role="menu"
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="local-dev.html">Local Development</a></li>
<li class="toctree-l1"><a class="reference internal" href="internal-dev-tools.html">Internal Dev Tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="why-foundationdb.html">Why FoundationDB</a><ul>
<li class="toctree-l2"><a class="reference internal" href="transaction-manifesto.html">Transaction Manifesto</a></li>
<li class="toctree-l2"><a class="reference internal" href="cap-theorem.html">CAP Theorem</a></li>
<li class="toctree-l2"><a class="reference internal" href="consistency.html">Consistency</a></li>
<li class="toctree-l2"><a class="reference internal" href="scalability.html">Scalability</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="technical-overview.html">Technical Overview</a><ul>
<li class="toctree-l2"><a class="reference internal" href="architecture.html">Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="performance.html">Performance</a></li>
<li class="toctree-l2"><a class="reference internal" href="benchmarking.html">Benchmarking</a></li>
<li class="toctree-l2"><a class="reference internal" href="engineering.html">Engineering</a></li>
<li class="toctree-l2"><a class="reference internal" href="features.html">Features</a></li>
<li class="toctree-l2"><a class="reference internal" href="layer-concept.html">Layer Concept</a></li>
<li class="toctree-l2"><a class="reference internal" href="anti-features.html">Anti-Features</a></li>
<li class="toctree-l2"><a class="reference internal" href="experimental-features.html">Experimental-Features</a></li>
<li class="toctree-l2"><a class="reference internal" href="transaction-processing.html">Transaction Processing</a></li>
<li class="toctree-l2"><a class="reference internal" href="fault-tolerance.html">Fault Tolerance</a></li>
<li class="toctree-l2"><a class="reference internal" href="flow.html">Flow</a></li>
<li class="toctree-l2"><a class="reference internal" href="testing.html">Simulation and Testing</a></li>
<li class="toctree-l2"><a class="reference internal" href="kv-architecture.html">FoundationDB Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="read-write-path.html">FDB Read and Write Path</a></li>
<li class="toctree-l2"><a class="reference internal" href="ha-write-path.html">FDB HA Write Path: How a mutation travels in FDB HA</a></li>
<li class="toctree-l2"><a class="reference internal" href="consistency-check-urgent.html">Consistency Checker Urgent</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="client-design.html">Client Design</a><ul>
<li class="toctree-l2"><a class="reference internal" href="getting-started-mac.html">Getting Started on macOS</a></li>
<li class="toctree-l2"><a class="reference internal" href="getting-started-linux.html">Getting Started on Linux</a></li>
<li class="toctree-l2"><a class="reference internal" href="downloads.html">Downloads</a></li>
<li class="toctree-l2"><a class="reference internal" href="developer-guide.html">Developer Guide</a></li>
<li class="toctree-l2"><a class="reference internal" href="data-modeling.html">Data Modeling</a></li>
<li class="toctree-l2"><a class="reference internal" href="client-testing.html">Client Testing</a></li>
<li class="toctree-l2"><a class="reference internal" href="client-testing.html#testing-error-handling-with-buggify">Testing Error Handling with Buggify</a></li>
<li class="toctree-l2"><a class="reference internal" href="client-testing.html#simulation-and-cluster-workloads">Simulation and Cluster Workloads</a></li>
<li class="toctree-l2"><a class="reference internal" href="client-testing.html#api-tester">API Tester</a></li>
<li class="toctree-l2"><a class="reference internal" href="api-general.html">Using FoundationDB Clients</a></li>
<li class="toctree-l2"><a class="reference internal" href="transaction-tagging.html">Transaction Tagging</a></li>
<li class="toctree-l2"><a class="reference internal" href="known-limitations.html">Known Limitations</a></li>
<li class="toctree-l2"><a class="reference internal" href="transaction-profiler-analyzer.html">Transaction profiling and analyzing</a></li>
<li class="toctree-l2"><a class="reference internal" href="api-version-upgrade-guide.html">API Version Upgrade Guide</a></li>
<li class="toctree-l2"><a class="reference internal" href="tenants.html">Tenants</a></li>
<li class="toctree-l2"><a class="reference internal" href="automatic-idempotency.html">Automatic Idempotency</a></li>
</ul>
</li>
<li class="toctree-l1 current"><a class="reference internal" href="design-recipes.html">Design Recipes</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="blob.html">Blob</a></li>
<li class="toctree-l2"><a class="reference internal" href="blob-java.html">Blob</a></li>
<li class="toctree-l2"><a class="reference internal" href="hierarchical-documents.html">Hierarchical Documents</a></li>
<li class="toctree-l2"><a class="reference internal" href="hierarchical-documents-java.html">Hierarchical Documents</a></li>
<li class="toctree-l2"><a class="reference internal" href="multimaps.html">Multimaps</a></li>
<li class="toctree-l2"><a class="reference internal" href="multimaps-java.html">Multimaps</a></li>
<li class="toctree-l2"><a class="reference internal" href="priority-queues.html">Priority Queues</a></li>
<li class="toctree-l2"><a class="reference internal" href="priority-queues-java.html">Priority Queues</a></li>
<li class="toctree-l2"><a class="reference internal" href="queues.html">Queues</a></li>
<li class="toctree-l2"><a class="reference internal" href="queues-java.html">Queues</a></li>
<li class="toctree-l2"><a class="reference internal" href="segmented-range-reads.html">Segmented Range Reads</a></li>
<li class="toctree-l2"><a class="reference internal" href="segmented-range-reads-java.html">Segmented Range Reads</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">Simple Indexes</a></li>
<li class="toctree-l2"><a class="reference internal" href="simple-indexes-java.html">Simple Indexes</a></li>
<li class="toctree-l2"><a class="reference internal" href="spatial-indexing.html">Spatial Indexing</a></li>
<li class="toctree-l2"><a class="reference internal" href="spatial-indexing-java.html">Spatial Indexing</a></li>
<li class="toctree-l2"><a class="reference internal" href="subspace-indirection.html">Subspace Indirection</a></li>
<li class="toctree-l2"><a class="reference internal" href="subspace-indirection-java.html">Subspace Indirection</a></li>
<li class="toctree-l2"><a class="reference internal" href="tables.html">Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="tables-java.html">Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="vector.html">Vector</a></li>
<li class="toctree-l2"><a class="reference internal" href="vector-java.html">Vector</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="api-reference.html">API Reference</a><ul>
<li class="toctree-l2"><a class="reference internal" href="api-python.html">Python API</a></li>
<li class="toctree-l2"><a class="reference internal" href="api-ruby.html">Ruby API</a></li>
<li class="toctree-l2"><a class="reference external" href="relative://javadoc/index.html">Java API</a></li>
<li class="toctree-l2"><a class="reference external" href="https://godoc.org/github.com/apple/foundationdb/bindings/go/src/fdb">Go API</a></li>
<li class="toctree-l2"><a class="reference internal" href="api-c.html">C API</a></li>
<li class="toctree-l2"><a class="reference internal" href="api-error-codes.html">Error Codes</a></li>
<li class="toctree-l2"><a class="reference internal" href="special-keys.html">Special Keys</a></li>
<li class="toctree-l2"><a class="reference internal" href="global-configuration.html">Global Configuration</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="tutorials.html">Tutorials</a><ul>
<li class="toctree-l2"><a class="reference internal" href="class-scheduling.html">Class Scheduling</a></li>
<li class="toctree-l2"><a class="reference internal" href="largeval.html">Managing Large Values and Blobs</a></li>
<li class="toctree-l2"><a class="reference internal" href="time-series.html">Time-Series Data</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="administration.html">Administration</a><ul>
<li class="toctree-l2"><a class="reference internal" href="configuration.html">Configuration</a></li>
<li class="toctree-l2"><a class="reference internal" href="moving-a-cluster.html">Moving a Cluster to New Machines</a></li>
<li class="toctree-l2"><a class="reference internal" href="tls.html">Transport Layer Security</a></li>
<li class="toctree-l2"><a class="reference internal" href="authorization.html">Authorization</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="monitored-metrics.html"><strong>Monitored Metrics</strong></a></li>
<li class="toctree-l1"><a class="reference internal" href="redwood.html">Redwood Storage Engine</a></li>
<li class="toctree-l1"><a class="reference internal" href="visibility.html">Visibility Documents</a><ul>
<li class="toctree-l2"><a class="reference internal" href="request-tracing.html">Request Tracing</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="earlier-release-notes.html">Earlier Release Notes</a><ul>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-014.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-016.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-021.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-022.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-023.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-100.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-200.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-300.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-400.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-410.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-420.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-430.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-440.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-450.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-460.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-500.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-510.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-520.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-600.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-610.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-620.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-630.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-700.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-710.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-720.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-730.html">Release Notes</a></li>
</ul>
</li>
</ul>
</ul>
</li>
<li class="dropdown">
<a role="button"
id="dLabelLocalToc"
data-toggle="dropdown"
data-target="#"
href="#">Page <b class="caret"></b></a>
<ul class="dropdown-menu localtoc"
role="menu"
aria-labelledby="dLabelLocalToc"><ul>
<li><a class="reference internal" href="#">Simple Indexes</a><ul>
<li><a class="reference internal" href="#goal">Goal</a></li>
<li><a class="reference internal" href="#challenges">Challenges</a></li>
<li><a class="reference internal" href="#strategy">Strategy</a></li>
<li><a class="reference internal" href="#pattern">Pattern</a></li>
<li><a class="reference internal" href="#extensions">Extensions</a><ul>
<li><a class="reference internal" href="#additional-indexes">Additional indexes</a></li>
<li><a class="reference internal" href="#covering-indexes">Covering indexes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#code">Code</a></li>
</ul>
</li>
</ul>
</ul>
</li>
<li>
<a href="segmented-range-reads-java.html" title="Previous Chapter: Segmented Range Reads"><span class="glyphicon glyphicon-chevron-left visible-sm"></span><span class="hidden-sm hidden-tablet">&laquo; Segmented Range Reads</span>
</a>
</li>
<li>
<a href="simple-indexes-java.html" title="Next Chapter: Simple Indexes"><span class="glyphicon glyphicon-chevron-right visible-sm"></span><span class="hidden-sm hidden-tablet">Simple Indexes &raquo;</span>
</a>
</li>
</ul>
<form class="navbar-form navbar-right" action="search.html" method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" />
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-3">
<div id="sidebar" class="bs-sidenav" role="complementary"><ul>
<li><a class="reference internal" href="#">Simple Indexes</a><ul>
<li><a class="reference internal" href="#goal">Goal</a></li>
<li><a class="reference internal" href="#challenges">Challenges</a></li>
<li><a class="reference internal" href="#strategy">Strategy</a></li>
<li><a class="reference internal" href="#pattern">Pattern</a></li>
<li><a class="reference internal" href="#extensions">Extensions</a><ul>
<li><a class="reference internal" href="#additional-indexes">Additional indexes</a></li>
<li><a class="reference internal" href="#covering-indexes">Covering indexes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#code">Code</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div class="body col-md-9 content" role="main">
<section id="simple-indexes">
<h1>Simple Indexes</h1>
<p><strong>Python</strong> <a class="reference internal" href="simple-indexes-java.html"><span class="doc">Java</span></a></p>
<section id="goal">
<h2>Goal</h2>
<p>Add (one or more) indexes to allow efficient retrieval of data in multiple ways.</p>
</section>
<section id="challenges">
<h2>Challenges</h2>
<p>There are two big challenges with building indexes in a key-value store: 1) Storing the index so that multiple data elements “matching” the index read are returned as efficiently as possible, and 2) Keeping the indexes in sync with the data with concurrent readers and writers.</p>
</section>
<section id="strategy">
<h2>Strategy</h2>
<p>By using the key ordering of FoundationDB, we can store indexes so that an index query can return multiple matches using a single efficient range read operation. By updating the data element and all of its associated indexes together within a single ACID transaction we can guarantee that the data and indexes stay in sync.</p>
</section>
<section id="pattern">
<h2>Pattern</h2>
<p>Lets say the primary copy of the data is stored with key-value pairs where the key has a tuple-structure consisting of a subspace and an ID:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">main_subspace</span><span class="p">,</span> <span class="n">ID</span><span class="p">)</span> <span class="o">=</span> <span class="n">value</span>
</pre></div>
</div>
<p>This structure lets you lookup an “ID” easily and get its associated value. But, lets say part of the value is a zipcode. You might be interested in all IDs that have a zipcode of 22182. You could answer that question, but it would require scanning every single ID. What we need to improve the efficiency is an “index on zipcode”.</p>
<p>An index is essentially another representation of the data, designed to be looked up in a different way:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">index_subspace</span><span class="p">,</span> <span class="n">zipcode</span><span class="p">,</span> <span class="n">ID</span><span class="p">)</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span>
</pre></div>
</div>
<p>To make the index, you store both the zipcode and the ID as parts of the key, but dont store the whole value again. You also put the index in its own subspace to keep it separate from the primary data.</p>
<p>Now, to answer the question of what IDs match zipcode 22182, you can now restrict the search to all tuples matching <code class="docutils literal notranslate"><span class="pre">(index_subspace,</span> <span class="pre">22182,</span> <span class="pre">*)</span></code>. Happily, because of the way that ordered tuples get packed into ordered keys, all of the tuples matching this pattern can be retrieved using a single range-read operation on the database. This makes index queries blazing fastrequiring one database operation instead of a scan of the entire dataset.</p>
<p>You can use the pattern above in any ordered key-value store. But, as anyone who has tried it will tell you, the trick is dealing with maintaining these indexes during concurrent reads and writes. In most distributed databases, this is a nightmare of race conditions and extra logic to deal with the fact that, while the data and the indexes both get updated, they do not necessarily do so at the same time.</p>
<p>By contrast, FoundationDBs ACID transactions completely handle the difficult concurrency problem automatically. This is accomplished by simply updating the data and the indexes in the same transaction. A good approach is to implement a transactional setter function that does nothing but perform a logical write to both the data record and its indexes. This approach keeps your code clean and makes it easier to add further indexes in the future.</p>
</section>
<section id="extensions">
<h2>Extensions</h2>
<section id="additional-indexes">
<h3>Additional indexes</h3>
<p>Of course, you can maintain as many indexes as you need. You are trading off write performance (and a bit of capacity usage) to speed up read performance. In general, you usually add indexes to support all of the access patterns that you actually use. For example, if we need fast access by both the “X” and “Y” properties, we could maintain three data representations (the main data plus two indexes):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">main_subspace</span><span class="p">,</span> <span class="n">ID</span><span class="p">)</span> <span class="o">=</span> <span class="n">value</span>
<span class="p">(</span><span class="n">index_x</span><span class="p">,</span> <span class="n">X</span><span class="p">,</span> <span class="n">ID</span><span class="p">)</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span>
<span class="p">(</span><span class="n">index_y</span><span class="p">,</span> <span class="n">Y</span><span class="p">,</span> <span class="n">ID</span><span class="p">)</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span>
</pre></div>
</div>
</section>
<section id="covering-indexes">
<h3>Covering indexes</h3>
<p>In the above examples, the index gives you an entity ID or primary key with which the rest of the record can be retrieved. Sometimes might you want to retrieve the entire record from an index with a single read. In this case, you can store all data components in the key, possibly including the value.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">main_subspace</span><span class="p">,</span> <span class="n">ID</span><span class="p">)</span> <span class="o">=</span> <span class="n">value</span>
<span class="p">(</span><span class="n">index_subspace</span><span class="p">,</span> <span class="n">X</span><span class="p">,</span> <span class="n">ID</span><span class="p">)</span> <span class="o">=</span> <span class="n">value</span>
</pre></div>
</div>
<p>The obvious tradeoff is that you are storing another entire copy of the value.</p>
</section>
</section>
<section id="code">
<h2>Code</h2>
<p>In this example, were storing user data based on user_ID but sometimes need to retrieve users based on their zipcode. We use a transactional function to set user data and its index and another to retrieve data using the index.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">user</span> <span class="o">=</span> <span class="n">fdb</span><span class="o">.</span><span class="n">Subspace</span><span class="p">((</span><span class="s1">&#39;user&#39;</span><span class="p">,))</span>
<span class="n">index</span> <span class="o">=</span> <span class="n">fdb</span><span class="o">.</span><span class="n">Subspace</span><span class="p">((</span><span class="s1">&#39;zipcode_index&#39;</span><span class="p">,))</span>
<span class="nd">@fdb</span><span class="o">.</span><span class="n">transactional</span>
<span class="k">def</span> <span class="nf">set_user</span><span class="p">(</span><span class="n">tr</span><span class="p">,</span> <span class="n">ID</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">zipcode</span><span class="p">):</span>
<span class="n">tr</span><span class="p">[</span><span class="n">user</span><span class="p">[</span><span class="n">ID</span><span class="p">][</span><span class="n">zipcode</span><span class="p">]]</span> <span class="o">=</span> <span class="n">name</span>
<span class="n">tr</span><span class="p">[</span><span class="n">index</span><span class="p">[</span><span class="n">zipcode</span><span class="p">][</span><span class="n">ID</span><span class="p">]]</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span>
<span class="c1"># Normal lookup</span>
<span class="nd">@fdb</span><span class="o">.</span><span class="n">transactional</span>
<span class="k">def</span> <span class="nf">get_user</span><span class="p">(</span><span class="n">tr</span><span class="p">,</span> <span class="n">ID</span><span class="p">):</span>
<span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="n">tr</span><span class="p">[</span><span class="n">user</span><span class="p">[</span><span class="n">ID</span><span class="p">]</span><span class="o">.</span><span class="n">range</span><span class="p">()]:</span>
<span class="k">return</span> <span class="n">v</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="c1"># Index lookup</span>
<span class="nd">@fdb</span><span class="o">.</span><span class="n">transactional</span>
<span class="k">def</span> <span class="nf">get_user_IDs_in_region</span><span class="p">(</span><span class="n">tr</span><span class="p">,</span> <span class="n">zipcode</span><span class="p">):</span>
<span class="k">return</span> <span class="p">[</span><span class="n">index</span><span class="o">.</span><span class="n">unpack</span><span class="p">(</span><span class="n">k</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">tr</span><span class="p">[</span><span class="n">index</span><span class="p">[</span><span class="n">zipcode</span><span class="p">]</span><span class="o">.</span><span class="n">range</span><span class="p">()]]</span>
</pre></div>
</div>
<p>Thats just about all you need to create an index.</p>
</section>
</section>
</div>
</div>
</div>
<footer class="footer">
<div class="container">
<p class="pull-right">
<a href="#">Back to top</a>
<br/>
<div id="sourcelink">
<a href="_sources/simple-indexes.rst.txt"
rel="nofollow">Source</a>
</div>
</p>
<p>
&copy; Copyright 2013-2022 Apple, Inc and the FoundationDB project authors.<br/>
Last updated on Nov 20, 2024.<br/>
</p>
</div>
</footer>
</body>
</html>