[#314,couchdb][s]: remove couchdb backend as now in its own repo at https://github.com/Recline/backend.couchdb.

This commit is contained in:
Rufus Pollock 2013-02-16 15:47:10 +00:00
parent 64c9e488dd
commit 369bd5f257
6 changed files with 3 additions and 1111 deletions

View File

@ -5,6 +5,6 @@
<li><a href="{{page.root}}/docs/src/backend.elasticsearch.html">elasticsearch: ElasticSearch</a></li>
<li><a href="{{page.root}}/docs/src/backend.dataproxy.html">dataproxy: DataProxy (CSV and XLS on the Web)</a></li>
<li><a href="{{page.root}}/docs/src/backend.ckan.html">ckan: CKAN</a> &ndash; support for <a href="http://docs.ckan.org/en/latest/datastore.html">CKAN datastore</a></li>
<li><a href="{{page.root}}/docs/src/backend.couchdb.html">couchdb: CouchDB</a></li>
<li><a href="https://github.com/Recline/backend.couchdb">couchdb: CouchDB</a></li>
<li><a href="{{page.root}}/docs/src/backend.memory.html">memory: Memory (local data)</a></li>
</ul>

View File

@ -1,73 +0,0 @@
jQuery(function($) {
window.dataExplorer = null;
window.explorerDiv = $('.data-explorer-here');
var queryParameters = recline.View.parseQueryString(decodeURIComponent(window.location.search));
var dataset = new recline.Model.Dataset({
db_url: queryParameters['url'] || '/couchdb/yourcouchdb',
view_url: queryParameters['view_url'] || '/couchdb/yourcouchdb/_design/yourdesigndoc/_view/yourview',
backend: 'couchdb',
query_options: {
'key': '_id'
}
});
dataset.fetch().done(function(dataset) {
console.log('records: ' + dataset.records);
});
createExplorer(dataset);
});
// make Explorer creation / initialization in a function so we can call it
// again and again
var createExplorer = function(dataset, state) {
// remove existing data explorer view
var reload = false;
if (window.dataExplorer) {
window.dataExplorer.remove();
reload = true;
}
window.dataExplorer = null;
var $el = $('<div />');
$el.appendTo(window.explorerDiv);
var views = [
{
id: 'grid',
label: 'Grid',
view: new recline.View.SlickGrid({
model: dataset
}),
},
{
id: 'graph',
label: 'Graph',
view: new recline.View.Graph({
model: dataset
}),
},
{
id: 'map',
label: 'Map',
view: new recline.View.Map({
model: dataset
}),
},
{
id: 'transform',
label: 'Transform',
view: new recline.View.Transform({
model: dataset
})
}
];
window.dataExplorer = new recline.View.MultiView({
model: dataset,
el: $el,
state: state,
views: views
});
}

View File

@ -1,40 +0,0 @@
---
layout: container
title: CouchDB Multiview - Demos
recline-deps: true
root: ../../
---
<style type="text/css">
.recline-slickgrid {
height: 550px;
}
.recline-timeline .vmm-timeline {
height: 550px;
}
</style>
<div class="instructions">
<h2>Instructions</h2>
<p>To use this demo you will need a CouchDB instance running and accessible over HTTP. You should then pass the following 2 query parameters to this page:</p>
<pre>url: url-to-your-couchdb-instance
view_url: url-to-your-couchdb-view
Example:
http://path-to-this-page/?url=/mycouchdb/&amp;view_url=/mycouchdb/_design/yourdesigndoc/_view/yourview
</pre>
<p>Note that if the CouchDB database is <em>not</em> running on the same domain as this page then the host it is on <em>must</em> support CORS &ndash; the simplest approach here is probably to set up a reverse proxy or proxy so your CouchDB database appears on the local domain at e.g. /mycouchdb/.</p>
</div>
<h2>Demo</h2>
<div class="data-explorer-here"></div>
<div style="clear: both;"></div>
<script type="text/javascript" src="../../src/backend.couchdb.js"></script>
<script type="text/javascript" src="app.js"></script>

View File

@ -95,13 +95,13 @@ root: ../
<div class="row" id="couchdb">
<div class="span4">
<div class="well">
<h3><a href="couchdb/">CouchDB Demo</a></h3>
<h3><a href="https://github.com/Recline/backend.couchdb">CouchDB Demo</a></h3>
<p>Using CouchDB with Recline Multiview to provide an elegant powerful
browser for a CouchDB database and view.</p>
</div>
</div>
<div class="span8">
<a href="multiview/"><img src="http://farm8.staticflickr.com/7251/7508402742_03c74a9763_c.jpg" style="width: 100%" /></a>
<a href="https://github.com/Recline/backend.couchdb"><img src="http://farm8.staticflickr.com/7251/7508402742_03c74a9763_c.jpg" style="width: 100%" /></a>
</div>
</div>

View File

@ -1,432 +0,0 @@
<!DOCTYPE html> <html> <head> <title>backend.couchdb.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="backend.ckan.html"> backend.ckan.js </a> <a class="source" href="backend.couchdb.html"> backend.couchdb.js </a> <a class="source" href="backend.csv.html"> backend.csv.js </a> <a class="source" href="backend.dataproxy.html"> backend.dataproxy.js </a> <a class="source" href="backend.elasticsearch.html"> backend.elasticsearch.js </a> <a class="source" href="backend.gdocs.html"> backend.gdocs.js </a> <a class="source" href="backend.memory.html"> backend.memory.js </a> <a class="source" href="data.transform.html"> data.transform.js </a> <a class="source" href="ecma-fixes.html"> ecma-fixes.js </a> <a class="source" href="model.html"> model.js </a> <a class="source" href="view.graph.html"> view.graph.js </a> <a class="source" href="view.grid.html"> view.grid.js </a> <a class="source" href="view.map.html"> view.map.js </a> <a class="source" href="view.multiview.html"> view.multiview.js </a> <a class="source" href="view.slickgrid.html"> view.slickgrid.js </a> <a class="source" href="view.timeline.html"> view.timeline.js </a> <a class="source" href="view.transform.html"> view.transform.js </a> <a class="source" href="widget.facetviewer.html"> widget.facetviewer.js </a> <a class="source" href="widget.fields.html"> widget.fields.js </a> <a class="source" href="widget.filtereditor.html"> widget.filtereditor.js </a> <a class="source" href="widget.pager.html"> widget.pager.js </a> <a class="source" href="widget.queryeditor.html"> widget.queryeditor.js </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> backend.couchdb.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="k">this</span><span class="p">.</span><span class="nx">recline</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">recline</span> <span class="o">||</span> <span class="p">{};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">recline</span><span class="p">.</span><span class="nx">Backend</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">recline</span><span class="p">.</span><span class="nx">Backend</span> <span class="o">||</span> <span class="p">{};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">recline</span><span class="p">.</span><span class="nx">Backend</span><span class="p">.</span><span class="nx">CouchDB</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">recline</span><span class="p">.</span><span class="nx">Backend</span><span class="p">.</span><span class="nx">CouchDB</span> <span class="o">||</span> <span class="p">{};</span>
<span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">$</span><span class="p">,</span> <span class="nx">my</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">my</span><span class="p">.</span><span class="nx">__type__</span> <span class="o">=</span> <span class="s1">&#39;couchdb&#39;</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <h2>CouchDB Wrapper</h2>
<p>Connecting to [CouchDB] (http://www.couchdb.apache.org/) endpoints.
@param {String} endpoint: url for CouchDB database, e.g. for Couchdb running
on localhost:5984 with database // ckan-std it would be:</p>
<p>TODO Add user/password arguments for couchdb authentication support.</p>
<p>See the example how to use this in: "demos/couchdb/"</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">my</span><span class="p">.</span><span class="nx">CouchDBWrapper</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">db_url</span><span class="p">,</span> <span class="nx">view_url</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="nx">self</span><span class="p">.</span><span class="nx">endpoint</span> <span class="o">=</span> <span class="nx">db_url</span><span class="p">;</span>
<span class="nx">self</span><span class="p">.</span><span class="nx">view_url</span> <span class="o">=</span> <span class="p">(</span><span class="nx">view_url</span><span class="p">)</span> <span class="o">?</span> <span class="nx">view_url</span> <span class="o">:</span> <span class="nx">db_url</span><span class="o">+</span><span class="s1">&#39;/&#39;</span><span class="o">+</span><span class="s1">&#39;_all_docs&#39;</span><span class="p">;</span>
<span class="nx">self</span><span class="p">.</span><span class="nx">options</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
<span class="nx">dataType</span><span class="o">:</span> <span class="s1">&#39;json&#39;</span>
<span class="p">},</span>
<span class="nx">options</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_makeRequest</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="nx">headers</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">extras</span> <span class="o">=</span> <span class="p">{};</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">headers</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">extras</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">beforeSend</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">headers</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">req</span><span class="p">.</span><span class="nx">setRequestHeader</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="nx">data</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span><span class="nx">extras</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <h3>mapping</h3>
<p>Get mapping for this database.
Assume all docs in the view have the same schema so
limit query to single result.</p>
<p>@return promise compatible deferred object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">mapping</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">schemaUrl</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">view_url</span> <span class="o">+</span> <span class="s1">&#39;?limit=1&amp;include_docs=true&#39;</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">jqxhr</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">_makeRequest</span><span class="p">({</span>
<span class="nx">url</span><span class="o">:</span> <span class="nx">schemaUrl</span><span class="p">,</span>
<span class="nx">dataType</span><span class="o">:</span> <span class="nx">self</span><span class="p">.</span><span class="nx">options</span><span class="p">.</span><span class="nx">dataType</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">jqxhr</span><span class="p">;</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <h3>get</h3>
<p>Get record corresponding to specified id</p>
<p>@return promise compatible deferred object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">get</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">_id</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">base</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">endpoint</span> <span class="o">+</span> <span class="s1">&#39;/&#39;</span> <span class="o">+</span> <span class="nx">_id</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">self</span><span class="p">.</span><span class="nx">_makeRequest</span><span class="p">({</span>
<span class="nx">url</span><span class="o">:</span> <span class="nx">base</span><span class="p">,</span>
<span class="nx">dataType</span><span class="o">:</span> <span class="s1">&#39;json&#39;</span>
<span class="p">});</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <h3>upsert</h3>
<p>create / update a record to CouchDB backend</p>
<p>@param {Object} doc an object to insert to the index.
@return deferred supporting promise API</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">upsert</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">doc</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">doc</span><span class="p">);</span>
<span class="nx">url</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">doc</span><span class="p">.</span><span class="nx">_id</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">url</span> <span class="o">+=</span> <span class="s1">&#39;/&#39;</span> <span class="o">+</span> <span class="nx">doc</span><span class="p">.</span><span class="nx">_id</span><span class="p">;</span>
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>use a PUT, not a POST to update the document:
http://wiki.apache.org/couchdb/HTTP<em>Document</em>API#POST</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span> <span class="nx">self</span><span class="p">.</span><span class="nx">_makeRequest</span><span class="p">({</span>
<span class="nx">url</span><span class="o">:</span> <span class="nx">url</span><span class="p">,</span>
<span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;PUT&#39;</span><span class="p">,</span>
<span class="nx">data</span><span class="o">:</span> <span class="nx">data</span><span class="p">,</span>
<span class="nx">dataType</span><span class="o">:</span> <span class="s1">&#39;json&#39;</span><span class="p">,</span>
<span class="nx">contentType</span><span class="o">:</span> <span class="s1">&#39;application/json&#39;</span>
<span class="p">});</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <h3>delete</h3>
<p>Delete a record from the CouchDB backend.</p>
<p>@param {Object} id id of object to delete
@return deferred supporting promise API</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">remove</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">_id</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">url</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">;</span>
<span class="nx">url</span> <span class="o">+=</span> <span class="s1">&#39;/&#39;</span> <span class="o">+</span> <span class="nx">_id</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">self</span><span class="p">.</span><span class="nx">_makeRequest</span><span class="p">({</span>
<span class="nx">url</span><span class="o">:</span> <span class="nx">url</span><span class="p">,</span>
<span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;DELETE&#39;</span><span class="p">,</span>
<span class="nx">dataType</span><span class="o">:</span> <span class="s1">&#39;json&#39;</span>
<span class="p">});</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <h3>_normalizeQuery</h3>
<p>Convert the query object from Elastic Search format to a
Couchdb View API compatible format.
See: http://wiki.apache.org/couchdb/HTTP<em>view</em>API</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">_normalizeQuery</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">queryObj</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">out</span> <span class="o">=</span> <span class="nx">queryObj</span> <span class="o">&amp;&amp;</span> <span class="nx">queryObj</span><span class="p">.</span><span class="nx">toJSON</span> <span class="o">?</span> <span class="nx">queryObj</span><span class="p">.</span><span class="nx">toJSON</span><span class="p">()</span> <span class="o">:</span> <span class="nx">_</span><span class="p">.</span><span class="nx">extend</span><span class="p">({},</span> <span class="nx">queryObj</span><span class="p">);</span>
<span class="k">delete</span> <span class="nx">out</span><span class="p">.</span><span class="nx">sort</span><span class="p">;</span>
<span class="k">delete</span> <span class="nx">out</span><span class="p">.</span><span class="nx">query</span><span class="p">;</span>
<span class="k">delete</span> <span class="nx">out</span><span class="p">.</span><span class="nx">filters</span><span class="p">;</span>
<span class="k">delete</span> <span class="nx">out</span><span class="p">.</span><span class="nx">fields</span><span class="p">;</span>
<span class="k">delete</span> <span class="nx">out</span><span class="p">.</span><span class="nx">facets</span><span class="p">;</span>
<span class="nx">out</span><span class="p">[</span><span class="s1">&#39;skip&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nx">out</span><span class="p">.</span><span class="nx">from</span> <span class="o">||</span> <span class="mi">0</span><span class="p">;</span>
<span class="nx">out</span><span class="p">[</span><span class="s1">&#39;limit&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nx">out</span><span class="p">.</span><span class="nx">size</span> <span class="o">||</span> <span class="mi">100</span><span class="p">;</span>
<span class="k">delete</span> <span class="nx">out</span><span class="p">.</span><span class="nx">from</span><span class="p">;</span>
<span class="k">delete</span> <span class="nx">out</span><span class="p">.</span><span class="nx">size</span><span class="p">;</span>
<span class="nx">out</span><span class="p">[</span><span class="s1">&#39;include_docs&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">out</span><span class="p">;</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <h3>query</h3>
<p>@param {Object} recline.Query instance.
@param {Object} additional couchdb view query options.
@return deferred supporting promise API</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">query</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">query_object</span><span class="p">,</span> <span class="nx">query_options</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">norm_q</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">_normalizeQuery</span><span class="p">(</span><span class="nx">query_object</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">url</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">view_url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">q</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span><span class="nx">query_options</span><span class="p">,</span> <span class="nx">norm_q</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">jqxhr</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">_makeRequest</span><span class="p">({</span>
<span class="nx">url</span><span class="o">:</span> <span class="nx">url</span><span class="p">,</span>
<span class="nx">data</span><span class="o">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">q</span><span class="p">),</span>
<span class="nx">dataType</span><span class="o">:</span> <span class="nx">self</span><span class="p">.</span><span class="nx">options</span><span class="p">.</span><span class="nx">dataType</span><span class="p">,</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">jqxhr</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <h2>CouchDB Backend</h2>
<p>Backbone connector for a CouchDB backend.</p>
<pre><code>var dataset = new recline.Model.Dataset({
db_url: path-to-couchdb-database e.g. '/couchdb/mydb',
view_url: path-to-couchdb-database-view e.g. '/couchdb/mydb/_design/design1/_views/view1',
backend: 'couchdb',
query_options: {
'key': '_id'
}
});
backend.query(query, dataset.toJSON()).done(function () { ... });
</code></pre>
<p>Alternatively:</p>
<pre><code>var dataset = new recline.Model.Dataset({ ... }, 'couchdb');
dataset.fetch();
var results = dataset.query(query_obj);
</code></pre>
<p>Additionally, the Dataset instance may define three methods:</p>
<p>function record<em>update (record, document) { ... }
function record</em>delete (record, document) { ... }
function record_create (record, document) { ... }</p>
<p>Where <code>record</code> is the JSON representation of the Record/Document instance
and <code>document</code> is the JSON document stored in couchdb.
When <em>all</em>docs view is used (default), a record is the same as a document
so these methods need not be defined.
They are most useful when using a custom view that performs a map-reduce
operation on each document to yield a record. Hence, when the record is
created, updated or deleted, an inverse operation must be performed on the original
document.</p>
<p>@param {string} url of couchdb database.
@param {string} (optional) url of couchdb view. default:<code>db_url</code>/<em>all</em>docs
@param {Object} (optional) query options accepted by couchdb views.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">my</span><span class="p">.</span><span class="nx">couchOptions</span> <span class="o">=</span> <span class="p">{};</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <h3>fetch</h3>
<p>@param {object} dataset json object with the db<em>url, view</em>url, and query_options args.
@return promise object that resolves to the document mapping.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">my</span><span class="p">.</span><span class="nx">fetch</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">dataset</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">db_url</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">db_url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">view_url</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">view_url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">cdb</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">my</span><span class="p">.</span><span class="nx">CouchDBWrapper</span><span class="p">(</span><span class="nx">db_url</span><span class="p">,</span> <span class="nx">view_url</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">dfd</span> <span class="o">=</span> <span class="nx">$</span><span class="p">.</span><span class="nx">Deferred</span><span class="p">();</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>if 'doc' attribute is present, return schema of that
else return schema of 'value' attribute which contains
the map-reduced document.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">cdb</span><span class="p">.</span><span class="nx">mapping</span><span class="p">().</span><span class="nx">done</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">row</span> <span class="o">=</span> <span class="nx">result</span><span class="p">.</span><span class="nx">rows</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">keys</span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">view_url</span><span class="p">.</span><span class="nx">search</span><span class="p">(</span><span class="s2">&quot;_all_docs&quot;</span><span class="p">)</span> <span class="o">!==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">keys</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">row</span><span class="p">[</span><span class="s1">&#39;doc&#39;</span><span class="p">]);</span>
<span class="nx">keys</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="nx">keys</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">k</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">k</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">!==</span> <span class="s1">&#39;_&#39;</span> <span class="p">});</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="nx">keys</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">row</span><span class="p">[</span><span class="s1">&#39;value&#39;</span><span class="p">]);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">fieldData</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">keys</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">k</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span> <span class="s1">&#39;id&#39;</span> <span class="o">:</span> <span class="nx">k</span> <span class="p">};</span>
<span class="p">});</span>
<span class="nx">dfd</span><span class="p">.</span><span class="nx">resolve</span><span class="p">({</span>
<span class="nx">fields</span><span class="o">:</span> <span class="nx">fieldData</span>
<span class="p">});</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">fail</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">arguments</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">dfd</span><span class="p">.</span><span class="nx">reject</span><span class="p">(</span><span class="nx">arguments</span><span class="p">);</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">dfd</span><span class="p">.</span><span class="nx">promise</span><span class="p">();</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <h3>save</h3>
<p>Iterate through all the changes and save them to the server.
N.B. This method is asynchronous and attempts to do multiple
operation concurrently. This can be problematic when more than
one operation is requested on the same document (as in the case
of bulk column transforms).</p>
<p>@param {object} lists of create, update, delete.
@param {object} dataset json object.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">my</span><span class="p">.</span><span class="nx">save</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">changes</span><span class="p">,</span> <span class="nx">dataset</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">dfd</span> <span class="o">=</span> <span class="nx">$</span><span class="p">.</span><span class="nx">Deferred</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">total</span> <span class="o">=</span> <span class="nx">changes</span><span class="p">.</span><span class="nx">creates</span><span class="p">.</span><span class="nx">length</span> <span class="o">+</span> <span class="nx">changes</span><span class="p">.</span><span class="nx">updates</span><span class="p">.</span><span class="nx">length</span> <span class="o">+</span> <span class="nx">changes</span><span class="p">.</span><span class="nx">deletes</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">results</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;done&#39;</span><span class="o">:</span> <span class="p">[],</span> <span class="s1">&#39;fail&#39;</span><span class="o">:</span> <span class="p">[]</span> <span class="p">};</span>
<span class="kd">var</span> <span class="nx">decr_cb</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="nx">total</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span> <span class="p">}</span>
<span class="kd">var</span> <span class="nx">resolve_cb</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="nx">total</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="nx">dfd</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">results</span><span class="p">);</span> <span class="p">}</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">changes</span><span class="p">.</span><span class="nx">creates</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">new_doc</span> <span class="o">=</span> <span class="nx">changes</span><span class="p">.</span><span class="nx">creates</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">succ_cb</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">msg</span><span class="p">)</span> <span class="p">{</span><span class="nx">results</span><span class="p">.</span><span class="nx">done</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="s1">&#39;op&#39;</span><span class="o">:</span> <span class="s1">&#39;create&#39;</span><span class="p">,</span> <span class="s1">&#39;record&#39;</span><span class="o">:</span> <span class="nx">new_doc</span><span class="p">,</span> <span class="s1">&#39;reason&#39;</span><span class="o">:</span> <span class="s1">&#39;&#39;</span><span class="p">});</span> <span class="p">}</span>
<span class="kd">var</span> <span class="nx">fail_cb</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">msg</span><span class="p">)</span> <span class="p">{</span><span class="nx">results</span><span class="p">.</span><span class="nx">fail</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="s1">&#39;op&#39;</span><span class="o">:</span> <span class="s1">&#39;create&#39;</span><span class="p">,</span> <span class="s1">&#39;record&#39;</span><span class="o">:</span> <span class="nx">new_doc</span><span class="p">,</span> <span class="s1">&#39;reason&#39;</span><span class="o">:</span> <span class="nx">msg</span><span class="p">});</span> <span class="p">}</span>
<span class="nx">_createDocument</span><span class="p">(</span><span class="nx">new_doc</span><span class="p">,</span> <span class="nx">dataset</span><span class="p">).</span><span class="nx">then</span><span class="p">([</span><span class="nx">decr_cb</span><span class="p">,</span> <span class="nx">succ_cb</span><span class="p">,</span> <span class="nx">resolve_cb</span><span class="p">],</span> <span class="p">[</span><span class="nx">decr_cb</span><span class="p">,</span> <span class="nx">fail_cb</span><span class="p">,</span> <span class="nx">resolve_cb</span><span class="p">]);</span>
<span class="p">}</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">changes</span><span class="p">.</span><span class="nx">updates</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">new_doc</span> <span class="o">=</span> <span class="nx">changes</span><span class="p">.</span><span class="nx">updates</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">succ_cb</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">msg</span><span class="p">)</span> <span class="p">{</span><span class="nx">results</span><span class="p">.</span><span class="nx">done</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="s1">&#39;op&#39;</span><span class="o">:</span> <span class="s1">&#39;update&#39;</span><span class="p">,</span> <span class="s1">&#39;record&#39;</span><span class="o">:</span> <span class="nx">new_doc</span><span class="p">,</span> <span class="s1">&#39;reason&#39;</span><span class="o">:</span> <span class="s1">&#39;&#39;</span><span class="p">});</span> <span class="p">}</span>
<span class="kd">var</span> <span class="nx">fail_cb</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">msg</span><span class="p">)</span> <span class="p">{</span><span class="nx">results</span><span class="p">.</span><span class="nx">fail</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="s1">&#39;op&#39;</span><span class="o">:</span> <span class="s1">&#39;update&#39;</span><span class="p">,</span> <span class="s1">&#39;record&#39;</span><span class="o">:</span> <span class="nx">new_doc</span><span class="p">,</span> <span class="s1">&#39;reason&#39;</span><span class="o">:</span> <span class="nx">msg</span><span class="p">});</span> <span class="p">}</span>
<span class="nx">_updateDocument</span><span class="p">(</span><span class="nx">new_doc</span><span class="p">,</span> <span class="nx">dataset</span><span class="p">).</span><span class="nx">then</span><span class="p">([</span><span class="nx">decr_cb</span><span class="p">,</span> <span class="nx">succ_cb</span><span class="p">,</span> <span class="nx">resolve_cb</span><span class="p">],</span> <span class="p">[</span><span class="nx">decr_cb</span><span class="p">,</span> <span class="nx">fail_cb</span><span class="p">,</span> <span class="nx">resolve_cb</span><span class="p">]);</span>
<span class="p">}</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">changes</span><span class="p">.</span><span class="nx">deletes</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">old_doc</span> <span class="o">=</span> <span class="nx">changes</span><span class="p">.</span><span class="nx">deletes</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">succ_cb</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">msg</span><span class="p">)</span> <span class="p">{</span><span class="nx">results</span><span class="p">.</span><span class="nx">done</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="s1">&#39;op&#39;</span><span class="o">:</span> <span class="s1">&#39;delete&#39;</span><span class="p">,</span> <span class="s1">&#39;record&#39;</span><span class="o">:</span> <span class="nx">old_doc</span><span class="p">,</span> <span class="s1">&#39;reason&#39;</span><span class="o">:</span> <span class="s1">&#39;&#39;</span><span class="p">});</span> <span class="p">}</span>
<span class="kd">var</span> <span class="nx">fail_cb</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">msg</span><span class="p">)</span> <span class="p">{</span><span class="nx">results</span><span class="p">.</span><span class="nx">fail</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="s1">&#39;op&#39;</span><span class="o">:</span> <span class="s1">&#39;delete&#39;</span><span class="p">,</span> <span class="s1">&#39;record&#39;</span><span class="o">:</span> <span class="nx">old_doc</span><span class="p">,</span> <span class="s1">&#39;reason&#39;</span><span class="o">:</span> <span class="nx">msg</span><span class="p">});</span> <span class="p">}</span>
<span class="nx">_deleteDocument</span><span class="p">(</span><span class="nx">new_doc</span><span class="p">,</span> <span class="nx">dataset</span><span class="p">).</span><span class="nx">then</span><span class="p">([</span><span class="nx">decr_cb</span><span class="p">,</span> <span class="nx">succ_cb</span><span class="p">,</span> <span class="nx">resolve_cb</span><span class="p">],</span> <span class="p">[</span><span class="nx">decr_cb</span><span class="p">,</span> <span class="nx">fail_cb</span><span class="p">,</span> <span class="nx">resolve_cb</span><span class="p">]);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">dfd</span><span class="p">.</span><span class="nx">promise</span><span class="p">();</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <h3>query</h3>
<p>fetch the data from the couchdb view and filter it.
@param {Object} recline.Dataset instance
@param {Object} recline.Query instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">my</span><span class="p">.</span><span class="nx">query</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">queryObj</span><span class="p">,</span> <span class="nx">dataset</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">dfd</span> <span class="o">=</span> <span class="nx">$</span><span class="p">.</span><span class="nx">Deferred</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">db_url</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">db_url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">view_url</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">view_url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">query_options</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">query_options</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">cdb</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">my</span><span class="p">.</span><span class="nx">CouchDBWrapper</span><span class="p">(</span><span class="nx">db_url</span><span class="p">,</span> <span class="nx">view_url</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">cdb_q</span> <span class="o">=</span> <span class="nx">cdb</span><span class="p">.</span><span class="nx">_normalizeQuery</span><span class="p">(</span><span class="nx">queryObj</span><span class="p">,</span> <span class="nx">query_options</span><span class="p">);</span>
<span class="nx">cdb</span><span class="p">.</span><span class="nx">query</span><span class="p">(</span><span class="nx">queryObj</span><span class="p">,</span> <span class="nx">query_options</span><span class="p">).</span><span class="nx">done</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">records</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">query_result</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">hits</span><span class="o">:</span> <span class="p">[],</span> <span class="nx">total</span><span class="o">:</span> <span class="mi">0</span> <span class="p">};</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">records</span><span class="p">.</span><span class="nx">rows</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">record</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">doc</span> <span class="o">=</span> <span class="p">{};</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">record</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="s1">&#39;doc&#39;</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">doc</span> <span class="o">=</span> <span class="nx">record</span><span class="p">[</span><span class="s1">&#39;doc&#39;</span><span class="p">];</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>couchdb uses _id to identify documents, Backbone models use id.
we add this fix so backbone.Model works correctly.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">doc</span><span class="p">[</span><span class="s1">&#39;id&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nx">doc</span><span class="p">[</span><span class="s1">&#39;_id&#39;</span><span class="p">];</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="nx">doc</span> <span class="o">=</span> <span class="nx">record</span><span class="p">[</span><span class="s1">&#39;value&#39;</span><span class="p">];</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>using dunder to create compound id. need something more robust.
couchdb uses _id to identify documents, Backbone models use id.
we add this fix so backbone.Model works correctly.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">doc</span><span class="p">[</span><span class="s1">&#39;_id&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nx">doc</span><span class="p">[</span><span class="s1">&#39;id&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nx">record</span><span class="p">[</span><span class="s1">&#39;id&#39;</span><span class="p">]</span> <span class="o">+</span> <span class="s1">&#39;__&#39;</span> <span class="o">+</span> <span class="nx">record</span><span class="p">[</span><span class="s1">&#39;key&#39;</span><span class="p">];</span>
<span class="p">}</span>
<span class="nx">query_result</span><span class="p">.</span><span class="nx">total</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">query_result</span><span class="p">.</span><span class="nx">hits</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">doc</span><span class="p">);</span>
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>the following block is borrowed verbatim from recline.backend.Memory
search (with filtering, faceting, and sorting) should be factored
out into a separate library.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">query_result</span><span class="p">.</span><span class="nx">hits</span> <span class="o">=</span> <span class="nx">_applyFilters</span><span class="p">(</span><span class="nx">query_result</span><span class="p">.</span><span class="nx">hits</span><span class="p">,</span> <span class="nx">queryObj</span><span class="p">);</span>
<span class="nx">query_result</span><span class="p">.</span><span class="nx">hits</span> <span class="o">=</span> <span class="nx">_applyFreeTextQuery</span><span class="p">(</span><span class="nx">query_result</span><span class="p">.</span><span class="nx">hits</span><span class="p">,</span> <span class="nx">queryObj</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>not complete sorting!</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">queryObj</span><span class="p">.</span><span class="nx">sort</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">sortObj</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">fieldName</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">sortObj</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span>
<span class="nx">query_result</span><span class="p">.</span><span class="nx">hits</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">sortBy</span><span class="p">(</span><span class="nx">query_result</span><span class="p">.</span><span class="nx">hits</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">doc</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">_out</span> <span class="o">=</span> <span class="nx">doc</span><span class="p">[</span><span class="nx">fieldName</span><span class="p">];</span>
<span class="k">return</span> <span class="p">(</span><span class="nx">sortObj</span><span class="p">[</span><span class="nx">fieldName</span><span class="p">].</span><span class="nx">order</span> <span class="o">==</span> <span class="s1">&#39;asc&#39;</span><span class="p">)</span> <span class="o">?</span> <span class="nx">_out</span> <span class="o">:</span> <span class="o">-</span><span class="mi">1</span><span class="o">*</span><span class="nx">_out</span><span class="p">;</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="nx">query_result</span><span class="p">.</span><span class="nx">total</span> <span class="o">=</span> <span class="nx">query_result</span><span class="p">.</span><span class="nx">hits</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="nx">query_result</span><span class="p">.</span><span class="nx">facets</span> <span class="o">=</span> <span class="nx">_computeFacets</span><span class="p">(</span><span class="nx">query_result</span><span class="p">.</span><span class="nx">hits</span><span class="p">,</span> <span class="nx">queryObj</span><span class="p">);</span>
<span class="nx">query_result</span><span class="p">.</span><span class="nx">hits</span> <span class="o">=</span> <span class="nx">query_result</span><span class="p">.</span><span class="nx">hits</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">cdb_q</span><span class="p">.</span><span class="nx">skip</span><span class="p">,</span> <span class="nx">cdb_q</span><span class="p">.</span><span class="nx">skip</span> <span class="o">+</span> <span class="nx">cdb_q</span><span class="p">.</span><span class="nx">limit</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">dfd</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">query_result</span><span class="p">);</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">dfd</span><span class="p">.</span><span class="nx">promise</span><span class="p">();</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p>in place filtering</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">_applyFilters</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">results</span><span class="p">,</span> <span class="nx">queryObj</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">queryObj</span><span class="p">.</span><span class="nx">filters</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">filter</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">results</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="nx">results</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">doc</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">fieldId</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">filter</span><span class="p">.</span><span class="nx">term</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span>
<span class="k">return</span> <span class="p">(</span><span class="nx">doc</span><span class="p">[</span><span class="nx">fieldId</span><span class="p">]</span> <span class="o">==</span> <span class="nx">filter</span><span class="p">.</span><span class="nx">term</span><span class="p">[</span><span class="nx">fieldId</span><span class="p">]);</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">results</span><span class="p">;</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">&#182;</a> </div> <p>we OR across fields but AND across terms in query string</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">_applyFreeTextQuery</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">results</span><span class="p">,</span> <span class="nx">queryObj</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">queryObj</span><span class="p">.</span><span class="nx">q</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">terms</span> <span class="o">=</span> <span class="nx">queryObj</span><span class="p">.</span><span class="nx">q</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">);</span>
<span class="nx">results</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="nx">results</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">rawdoc</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">matches</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">terms</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">term</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">foundmatch</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">rawdoc</span><span class="p">),</span> <span class="kd">function</span><span class="p">(</span><span class="nx">field</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">value</span> <span class="o">=</span> <span class="nx">rawdoc</span><span class="p">[</span><span class="nx">field</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">value</span> <span class="o">!==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span> <span class="nx">value</span> <span class="o">=</span> <span class="nx">value</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span> <span class="p">}</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">&#182;</a> </div> <p>TODO regexes?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">foundmatch</span> <span class="o">=</span> <span class="nx">foundmatch</span> <span class="o">||</span> <span class="p">(</span><span class="nx">value</span> <span class="o">===</span> <span class="nx">term</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">&#182;</a> </div> <p>TODO: early out (once we are true should break to spare unnecessary testing)
if (foundmatch) return true;</p> </td> <td class="code"> <div class="highlight"><pre> <span class="p">});</span>
<span class="nx">matches</span> <span class="o">=</span> <span class="nx">matches</span> <span class="o">&amp;&amp;</span> <span class="nx">foundmatch</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">&#182;</a> </div> <p>TODO: early out (once false should break to spare unnecessary testing)
if (!matches) return false;</p> </td> <td class="code"> <div class="highlight"><pre> <span class="p">});</span>
<span class="k">return</span> <span class="nx">matches</span><span class="p">;</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">results</span><span class="p">;</span>
<span class="p">};</span>
<span class="nx">_computeFacets</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">records</span><span class="p">,</span> <span class="nx">queryObj</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">facetResults</span> <span class="o">=</span> <span class="p">{};</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">queryObj</span><span class="p">.</span><span class="nx">facets</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">facetResults</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">queryObj</span><span class="p">.</span><span class="nx">facets</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">query</span><span class="p">,</span> <span class="nx">facetId</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">&#182;</a> </div> <p>TODO: remove dependency on recline.Model</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">facetResults</span><span class="p">[</span><span class="nx">facetId</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">recline</span><span class="p">.</span><span class="nx">Model</span><span class="p">.</span><span class="nx">Facet</span><span class="p">({</span><span class="nx">id</span><span class="o">:</span> <span class="nx">facetId</span><span class="p">}).</span><span class="nx">toJSON</span><span class="p">();</span>
<span class="nx">facetResults</span><span class="p">[</span><span class="nx">facetId</span><span class="p">].</span><span class="nx">termsall</span> <span class="o">=</span> <span class="p">{};</span>
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">&#182;</a> </div> <p>faceting</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">records</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">doc</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">queryObj</span><span class="p">.</span><span class="nx">facets</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">query</span><span class="p">,</span> <span class="nx">facetId</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">fieldId</span> <span class="o">=</span> <span class="nx">query</span><span class="p">.</span><span class="nx">terms</span><span class="p">.</span><span class="nx">field</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">val</span> <span class="o">=</span> <span class="nx">doc</span><span class="p">[</span><span class="nx">fieldId</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">tmp</span> <span class="o">=</span> <span class="nx">facetResults</span><span class="p">[</span><span class="nx">facetId</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">val</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">tmp</span><span class="p">.</span><span class="nx">termsall</span><span class="p">[</span><span class="nx">val</span><span class="p">]</span> <span class="o">=</span> <span class="nx">tmp</span><span class="p">.</span><span class="nx">termsall</span><span class="p">[</span><span class="nx">val</span><span class="p">]</span> <span class="o">?</span> <span class="nx">tmp</span><span class="p">.</span><span class="nx">termsall</span><span class="p">[</span><span class="nx">val</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">:</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">tmp</span><span class="p">.</span><span class="nx">missing</span> <span class="o">=</span> <span class="nx">tmp</span><span class="p">.</span><span class="nx">missing</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">queryObj</span><span class="p">.</span><span class="nx">facets</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">query</span><span class="p">,</span> <span class="nx">facetId</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">tmp</span> <span class="o">=</span> <span class="nx">facetResults</span><span class="p">[</span><span class="nx">facetId</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">terms</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">tmp</span><span class="p">.</span><span class="nx">termsall</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">count</span><span class="p">,</span> <span class="nx">term</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span> <span class="nx">term</span><span class="o">:</span> <span class="nx">term</span><span class="p">,</span> <span class="nx">count</span><span class="o">:</span> <span class="nx">count</span> <span class="p">};</span>
<span class="p">});</span>
<span class="nx">tmp</span><span class="p">.</span><span class="nx">terms</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">sortBy</span><span class="p">(</span><span class="nx">terms</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">&#182;</a> </div> <p>want descending order</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span> <span class="o">-</span><span class="nx">item</span><span class="p">.</span><span class="nx">count</span><span class="p">;</span>
<span class="p">});</span>
<span class="nx">tmp</span><span class="p">.</span><span class="nx">terms</span> <span class="o">=</span> <span class="nx">tmp</span><span class="p">.</span><span class="nx">terms</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">10</span><span class="p">);</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">facetResults</span><span class="p">;</span>
<span class="p">};</span>
<span class="nx">_createDocument</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">new_doc</span><span class="p">,</span> <span class="nx">dataset</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">dfd</span> <span class="o">=</span> <span class="nx">$</span><span class="p">.</span><span class="nx">Deferred</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">db_url</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">db_url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">view_url</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">view_url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">_id</span> <span class="o">=</span> <span class="nx">new_doc</span><span class="p">[</span><span class="s1">&#39;id&#39;</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">cdb</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">my</span><span class="p">.</span><span class="nx">CouchDBWrapper</span><span class="p">(</span><span class="nx">db_url</span><span class="p">,</span> <span class="nx">view_url</span><span class="p">);</span>
<span class="k">delete</span> <span class="nx">new_doc</span><span class="p">[</span><span class="s1">&#39;id&#39;</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">view_url</span><span class="p">.</span><span class="nx">search</span><span class="p">(</span><span class="s1">&#39;_all_docs&#39;</span><span class="p">)</span> <span class="o">!==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">jqxhr</span> <span class="o">=</span> <span class="nx">cdb</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">_id</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="nx">_id</span> <span class="o">=</span> <span class="nx">new_doc</span><span class="p">[</span><span class="s1">&#39;_id&#39;</span><span class="p">].</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;__&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span>
<span class="nx">jqxhr</span> <span class="o">=</span> <span class="nx">cdb</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">_id</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">jqxhr</span><span class="p">.</span><span class="nx">done</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">old_doc</span><span class="p">){</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">dataset</span><span class="p">.</span><span class="nx">record_create</span><span class="p">)</span>
<span class="nx">new_doc</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">record_create</span><span class="p">(</span><span class="nx">new_doc</span><span class="p">,</span> <span class="nx">old_doc</span><span class="p">);</span>
<span class="nx">new_doc</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span><span class="nx">old_doc</span><span class="p">,</span> <span class="nx">new_doc</span><span class="p">);</span>
<span class="nx">new_doc</span><span class="p">[</span><span class="s1">&#39;_id&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nx">_id</span><span class="p">;</span>
<span class="nx">dfd</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">cdb</span><span class="p">.</span><span class="nx">upsert</span><span class="p">(</span><span class="nx">new_doc</span><span class="p">));</span>
<span class="p">}).</span><span class="nx">fail</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">args</span><span class="p">){</span>
<span class="nx">dfd</span><span class="p">.</span><span class="nx">reject</span><span class="p">(</span><span class="nx">args</span><span class="p">);</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">dfd</span><span class="p">.</span><span class="nx">promise</span><span class="p">();</span>
<span class="p">};</span>
<span class="nx">_updateDocument</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">new_doc</span><span class="p">,</span> <span class="nx">dataset</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">dfd</span> <span class="o">=</span> <span class="nx">$</span><span class="p">.</span><span class="nx">Deferred</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">db_url</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">db_url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">view_url</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">view_url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">_id</span> <span class="o">=</span> <span class="nx">new_doc</span><span class="p">[</span><span class="s1">&#39;id&#39;</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">cdb</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">my</span><span class="p">.</span><span class="nx">CouchDBWrapper</span><span class="p">(</span><span class="nx">db_url</span><span class="p">,</span> <span class="nx">view_url</span><span class="p">);</span>
<span class="k">delete</span> <span class="nx">new_doc</span><span class="p">[</span><span class="s1">&#39;id&#39;</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">view_url</span><span class="p">.</span><span class="nx">search</span><span class="p">(</span><span class="s1">&#39;_all_docs&#39;</span><span class="p">)</span> <span class="o">!==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">jqxhr</span> <span class="o">=</span> <span class="nx">cdb</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">_id</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="nx">_id</span> <span class="o">=</span> <span class="nx">new_doc</span><span class="p">[</span><span class="s1">&#39;_id&#39;</span><span class="p">].</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;__&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span>
<span class="nx">jqxhr</span> <span class="o">=</span> <span class="nx">cdb</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">_id</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">jqxhr</span><span class="p">.</span><span class="nx">done</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">old_doc</span><span class="p">){</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">dataset</span><span class="p">.</span><span class="nx">record_update</span><span class="p">)</span>
<span class="nx">new_doc</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">record_update</span><span class="p">(</span><span class="nx">new_doc</span><span class="p">,</span> <span class="nx">old_doc</span><span class="p">);</span>
<span class="nx">new_doc</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span><span class="nx">old_doc</span><span class="p">,</span> <span class="nx">new_doc</span><span class="p">);</span>
<span class="nx">new_doc</span><span class="p">[</span><span class="s1">&#39;_id&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nx">_id</span><span class="p">;</span>
<span class="nx">dfd</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">cdb</span><span class="p">.</span><span class="nx">upsert</span><span class="p">(</span><span class="nx">new_doc</span><span class="p">));</span>
<span class="p">}).</span><span class="nx">fail</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">args</span><span class="p">){</span>
<span class="nx">dfd</span><span class="p">.</span><span class="nx">reject</span><span class="p">(</span><span class="nx">args</span><span class="p">);</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">dfd</span><span class="p">.</span><span class="nx">promise</span><span class="p">();</span>
<span class="p">};</span>
<span class="nx">_deleteDocument</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">del_doc</span><span class="p">,</span> <span class="nx">dataset</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">dfd</span> <span class="o">=</span> <span class="nx">$</span><span class="p">.</span><span class="nx">Deferred</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">db_url</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">db_url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">view_url</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">view_url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">_id</span> <span class="o">=</span> <span class="nx">del_doc</span><span class="p">[</span><span class="s1">&#39;id&#39;</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">cdb</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">my</span><span class="p">.</span><span class="nx">CouchDBWrapper</span><span class="p">(</span><span class="nx">db_url</span><span class="p">,</span> <span class="nx">view_url</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">view_url</span><span class="p">.</span><span class="nx">search</span><span class="p">(</span><span class="s1">&#39;_all_docs&#39;</span><span class="p">)</span> <span class="o">!==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="k">return</span> <span class="nx">cdb</span><span class="p">.</span><span class="nx">remove</span><span class="p">(</span><span class="nx">_id</span><span class="p">);</span>
<span class="k">else</span> <span class="p">{</span>
<span class="nx">_id</span> <span class="o">=</span> <span class="nx">model</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;_id&#39;</span><span class="p">).</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;__&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">jqxhr</span> <span class="o">=</span> <span class="nx">cdb</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">_id</span><span class="p">);</span>
<span class="nx">jqxhr</span><span class="p">.</span><span class="nx">done</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">old_doc</span><span class="p">){</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">dataset</span><span class="p">.</span><span class="nx">record_delete</span><span class="p">)</span>
<span class="nx">old_doc</span> <span class="o">=</span> <span class="nx">dataset</span><span class="p">.</span><span class="nx">record_delete</span><span class="p">(</span><span class="nx">del_doc</span><span class="p">,</span> <span class="nx">old_doc</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">isNull</span><span class="p">(</span><span class="nx">del_doc</span><span class="p">))</span>
<span class="nx">dfd</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">cdb</span><span class="p">.</span><span class="nx">remove</span><span class="p">(</span><span class="nx">_id</span><span class="p">));</span> <span class="c1">// XXX is this the right thing to do?</span>
<span class="k">else</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">&#182;</a> </div> <p>couchdb uses _id to identify documents, Backbone models use id.
we should remove it before sending it to the server.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">old_doc</span><span class="p">[</span><span class="s1">&#39;_id&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nx">_id</span><span class="p">;</span>
<span class="k">delete</span> <span class="nx">old_doc</span><span class="p">[</span><span class="s1">&#39;id&#39;</span><span class="p">];</span>
<span class="nx">dfd</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">cdb</span><span class="p">.</span><span class="nx">upsert</span><span class="p">(</span><span class="nx">old_doc</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">}).</span><span class="nx">fail</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">args</span><span class="p">){</span>
<span class="nx">dfd</span><span class="p">.</span><span class="nx">reject</span><span class="p">(</span><span class="nx">args</span><span class="p">);</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">dfd</span><span class="p">.</span><span class="nx">promise</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="p">}(</span><span class="nx">jQuery</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">recline</span><span class="p">.</span><span class="nx">Backend</span><span class="p">.</span><span class="nx">CouchDB</span><span class="p">));</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@ -1,563 +0,0 @@
this.recline = this.recline || {};
this.recline.Backend = this.recline.Backend || {};
this.recline.Backend.CouchDB = this.recline.Backend.CouchDB || {};
(function($, my) {
my.__type__ = 'couchdb';
// use either jQuery or Underscore Deferred depending on what is available
var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
// ## CouchDB Wrapper
//
// Connecting to [CouchDB] (http://www.couchdb.apache.org/) endpoints.
// @param {String} endpoint: url for CouchDB database, e.g. for Couchdb running
// on localhost:5984 with database // ckan-std it would be:
//
//
// TODO Add user/password arguments for couchdb authentication support.
//
// See the example how to use this in: "demos/couchdb/"
my.CouchDBWrapper = function(db_url, view_url, options) {
var self = this;
self.endpoint = db_url;
self.view_url = (view_url) ? view_url : db_url+'/'+'_all_docs';
self.options = _.extend({
dataType: 'json'
},
options);
this._makeRequest = function(data, headers) {
var extras = {};
if (headers) {
extras = {
beforeSend: function(req) {
_.each(headers, function(value, key) {
req.setRequestHeader(key, value);
});
}
};
}
data = _.extend(extras, data);
return $.ajax(data);
};
// ### mapping
//
// Get mapping for this database.
// Assume all docs in the view have the same schema so
// limit query to single result.
//
// @return promise compatible deferred object.
this.mapping = function() {
var schemaUrl = self.view_url + '?limit=1&include_docs=true';
var jqxhr = self._makeRequest({
url: schemaUrl,
dataType: self.options.dataType
});
return jqxhr;
};
// ### get
//
// Get record corresponding to specified id
//
// @return promise compatible deferred object.
this.get = function(_id) {
var base = self.endpoint + '/' + _id;
return self._makeRequest({
url: base,
dataType: 'json'
});
};
// ### upsert
//
// create / update a record to CouchDB backend
//
// @param {Object} doc an object to insert to the index.
// @return deferred supporting promise API
this.upsert = function(doc) {
var data = JSON.stringify(doc);
url = self.endpoint;
if (doc._id) {
url += '/' + doc._id;
}
// use a PUT, not a POST to update the document:
// http://wiki.apache.org/couchdb/HTTP_Document_API#POST
return self._makeRequest({
url: url,
type: 'PUT',
data: data,
dataType: 'json',
contentType: 'application/json'
});
};
// ### delete
//
// Delete a record from the CouchDB backend.
//
// @param {Object} id id of object to delete
// @return deferred supporting promise API
this.remove = function(_id) {
url = self.endpoint;
url += '/' + _id;
return self._makeRequest({
url: url,
type: 'DELETE',
dataType: 'json'
});
};
// ### _normalizeQuery
//
// Convert the query object from Elastic Search format to a
// Couchdb View API compatible format.
// See: http://wiki.apache.org/couchdb/HTTP_view_API
//
this._normalizeQuery = function(queryObj) {
var out = queryObj && queryObj.toJSON ? queryObj.toJSON() : _.extend({}, queryObj);
delete out.sort;
delete out.query;
delete out.filters;
delete out.fields;
delete out.facets;
out['skip'] = out.from || 0;
out['limit'] = out.size || 100;
delete out.from;
delete out.size;
out['include_docs'] = true;
return out;
};
// ### query
//
// @param {Object} recline.Query instance.
// @param {Object} additional couchdb view query options.
// @return deferred supporting promise API
this.query = function(query_object, query_options) {
var norm_q = self._normalizeQuery(query_object);
var url = self.view_url;
var q = _.extend(query_options, norm_q);
var jqxhr = self._makeRequest({
url: url,
data: JSON.stringify(q),
dataType: self.options.dataType,
});
return jqxhr;
}
};
// ## CouchDB Backend
//
// Backbone connector for a CouchDB backend.
//
// var dataset = new recline.Model.Dataset({
// db_url: path-to-couchdb-database e.g. '/couchdb/mydb',
// view_url: path-to-couchdb-database-view e.g. '/couchdb/mydb/_design/design1/_views/view1',
// backend: 'couchdb',
// query_options: {
// 'key': '_id'
// }
// });
//
// backend.query(query, dataset.toJSON()).done(function () { ... });
//
// Alternatively:
//
// var dataset = new recline.Model.Dataset({ ... }, 'couchdb');
// dataset.fetch();
// var results = dataset.query(query_obj);
//
// Additionally, the Dataset instance may define three methods:
//
// function record_update (record, document) { ... }
// function record_delete (record, document) { ... }
// function record_create (record, document) { ... }
//
// Where `record` is the JSON representation of the Record/Document instance
// and `document` is the JSON document stored in couchdb.
// When _all_docs view is used (default), a record is the same as a document
// so these methods need not be defined.
// They are most useful when using a custom view that performs a map-reduce
// operation on each document to yield a record. Hence, when the record is
// created, updated or deleted, an inverse operation must be performed on the original
// document.
//
// @param {string} url of couchdb database.
// @param {string} (optional) url of couchdb view. default:`db_url`/_all_docs
// @param {Object} (optional) query options accepted by couchdb views.
//
my.couchOptions = {};
// ### fetch
// @param {object} dataset json object with the db_url, view_url, and query_options args.
// @return promise object that resolves to the document mapping.
my.fetch = function (dataset) {
var db_url = dataset.db_url;
var view_url = dataset.view_url;
var cdb = new my.CouchDBWrapper(db_url, view_url);
var dfd = new Deferred();
// if 'doc' attribute is present, return schema of that
// else return schema of 'value' attribute which contains
// the map-reduced document.
cdb.mapping().done(function(result) {
var row = result.rows[0];
var keys = [];
if (view_url.search("_all_docs") !== -1) {
keys = _.keys(row['doc']);
keys = _.filter(keys, function (k) { return k.charAt(0) !== '_' });
}
else {
keys = _.keys(row['value']);
}
var fieldData = _.map(keys, function(k) {
return { 'id' : k };
});
dfd.resolve({
fields: fieldData
});
})
.fail(function(arguments) {
dfd.reject(arguments);
});
return dfd.promise();
};
// ### save
//
// Iterate through all the changes and save them to the server.
// N.B. This method is asynchronous and attempts to do multiple
// operation concurrently. This can be problematic when more than
// one operation is requested on the same document (as in the case
// of bulk column transforms).
//
// @param {object} lists of create, update, delete.
// @param {object} dataset json object.
//
//
my.save = function (changes, dataset) {
var dfd = new Deferred();
var total = changes.creates.length + changes.updates.length + changes.deletes.length;
var results = {'done': [], 'fail': [] };
var decr_cb = function () { total -= 1; }
var resolve_cb = function () { if (total == 0) dfd.resolve(results); }
for (var i in changes.creates) {
var new_doc = changes.creates[i];
var succ_cb = function (msg) {results.done.push({'op': 'create', 'record': new_doc, 'reason': ''}); }
var fail_cb = function (msg) {results.fail.push({'op': 'create', 'record': new_doc, 'reason': msg}); }
_createDocument(new_doc, dataset).then([decr_cb, succ_cb, resolve_cb], [decr_cb, fail_cb, resolve_cb]);
}
for (var i in changes.updates) {
var new_doc = changes.updates[i];
var succ_cb = function (msg) {results.done.push({'op': 'update', 'record': new_doc, 'reason': ''}); }
var fail_cb = function (msg) {results.fail.push({'op': 'update', 'record': new_doc, 'reason': msg}); }
_updateDocument(new_doc, dataset).then([decr_cb, succ_cb, resolve_cb], [decr_cb, fail_cb, resolve_cb]);
}
for (var i in changes.deletes) {
var old_doc = changes.deletes[i];
var succ_cb = function (msg) {results.done.push({'op': 'delete', 'record': old_doc, 'reason': ''}); }
var fail_cb = function (msg) {results.fail.push({'op': 'delete', 'record': old_doc, 'reason': msg}); }
_deleteDocument(new_doc, dataset).then([decr_cb, succ_cb, resolve_cb], [decr_cb, fail_cb, resolve_cb]);
}
return dfd.promise();
};
// ### query
//
// fetch the data from the couchdb view and filter it.
// @param {Object} recline.Dataset instance
// @param {Object} recline.Query instance.
my.query = function(queryObj, dataset) {
var dfd = new Deferred();
var db_url = dataset.db_url;
var view_url = dataset.view_url;
var query_options = dataset.query_options;
var cdb = new my.CouchDBWrapper(db_url, view_url);
var cdb_q = cdb._normalizeQuery(queryObj, query_options);
cdb.query(queryObj, query_options).done(function(records){
var query_result = { hits: [], total: 0 };
_.each(records.rows, function(record) {
var doc = {};
if (record.hasOwnProperty('doc')) {
doc = record['doc'];
// couchdb uses _id to identify documents, Backbone models use id.
// we add this fix so backbone.Model works correctly.
doc['id'] = doc['_id'];
}
else {
doc = record['value'];
// using dunder to create compound id. need something more robust.
// couchdb uses _id to identify documents, Backbone models use id.
// we add this fix so backbone.Model works correctly.
doc['_id'] = doc['id'] = record['id'] + '__' + record['key'];
}
query_result.total += 1;
query_result.hits.push(doc);
});
// the following block is borrowed verbatim from recline.backend.Memory
// search (with filtering, faceting, and sorting) should be factored
// out into a separate library.
query_result.hits = _applyFilters(query_result.hits, queryObj);
query_result.hits = _applyFreeTextQuery(query_result.hits, queryObj);
// not complete sorting!
_.each(queryObj.sort, function(sortObj) {
var fieldName = sortObj.field;
query_result.hits = _.sortBy(query_result.hits, function(doc) {
var _out = doc[fieldName];
return _out;
});
if (sortObj.order == 'desc') {
query_result.hits.reverse();
}
});
query_result.total = query_result.hits.length;
query_result.facets = _computeFacets(query_result.hits, queryObj);
query_result.hits = query_result.hits.slice(cdb_q.skip, cdb_q.skip + cdb_q.limit+1);
dfd.resolve(query_result);
});
return dfd.promise();
};
// in place filtering
_applyFilters = function(results, queryObj) {
var filters = queryObj.filters;
// register filters
var filterFunctions = {
term : term,
range : range,
geo_distance : geo_distance
};
var dataParsers = {
integer: function (e) { return parseFloat(e, 10); },
'float': function (e) { return parseFloat(e, 10); },
string : function (e) { return e.toString() },
date : function (e) { return new Date(e).valueOf() },
datetime : function (e) { return new Date(e).valueOf() }
};
function getDataParser(filter) {
//sample = results[0][filter.field]);
var fieldType = 'string';
return dataParsers[fieldType];
}
// filter records
return _.filter(results, function (record) {
var passes = _.map(filters, function (filter) {
return filterFunctions[filter.type](record, filter);
});
// return only these records that pass all filters
return _.all(passes, _.identity);
});
// filters definitions
function term(record, filter) {
var parse = getDataParser(filter);
var value = parse(record[filter.field]);
var term = parse(filter.term);
return (value === term);
}
function range(record, filter) {
var startnull = (filter.start == null || filter.start === '');
var stopnull = (filter.stop == null || filter.stop === '');
var parse = getDataParser(filter);
var value = parse(record[filter.field]);
var start = parse(filter.start);
var stop = parse(filter.stop);
// if at least one end of range is set do not allow '' to get through
// note that for strings '' <= {any-character} e.g. '' <= 'a'
if ((!startnull || !stopnull) && value === '') {
return false;
}
return ((startnull || value >= start) && (stopnull || value <= stop));
}
function geo_distance() {
// TODO code here
}
};
// we OR across fields but AND across terms in query string
_applyFreeTextQuery = function(results, queryObj) {
if (queryObj.q) {
var terms = queryObj.q.split(' ');
results = _.filter(results, function(rawdoc) {
var matches = true;
_.each(terms, function(term) {
var foundmatch = false;
_.each(_.keys(rawdoc), function(field) {
var value = rawdoc[field];
if (value !== null) { value = value.toString(); }
// TODO regexes?
foundmatch = foundmatch || (value === term);
// TODO: early out (once we are true should break to spare unnecessary testing)
// if (foundmatch) return true;
});
matches = matches && foundmatch;
// TODO: early out (once false should break to spare unnecessary testing)
// if (!matches) return false;
});
return matches;
});
}
return results;
};
_computeFacets = function(records, queryObj) {
var facetResults = {};
if (!queryObj.facets) {
return facetResults;
}
_.each(queryObj.facets, function(query, facetId) {
// TODO: remove dependency on recline.Model
facetResults[facetId] = new recline.Model.Facet({id: facetId}).toJSON();
facetResults[facetId].termsall = {};
});
// faceting
_.each(records, function(doc) {
_.each(queryObj.facets, function(query, facetId) {
var fieldId = query.terms.field;
var val = doc[fieldId];
var tmp = facetResults[facetId];
if (val) {
tmp.termsall[val] = tmp.termsall[val] ? tmp.termsall[val] + 1 : 1;
} else {
tmp.missing = tmp.missing + 1;
}
});
});
_.each(queryObj.facets, function(query, facetId) {
var tmp = facetResults[facetId];
var terms = _.map(tmp.termsall, function(count, term) {
return { term: term, count: count };
});
tmp.terms = _.sortBy(terms, function(item) {
// want descending order
return -item.count;
});
tmp.terms = tmp.terms.slice(0, 10);
});
return facetResults;
};
//Define random Id for new records without _id
function randomId(length, chars) {
var mask = '';
if (chars.indexOf('a') > -1) mask += 'abcdefghijklmnopqrstuvwxyz';
if (chars.indexOf('A') > -1) mask += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if (chars.indexOf('#') > -1) mask += '0123456789';
if (chars.indexOf('!') > -1) mask += '~`!@#$%^&*()_+-={}[]:";\'<>?,./|\\';
var result = '';
for (var i = length; i > 0; --i) result += mask[Math.round(Math.random() * (mask.length - 1))];
return result;
}
_createDocument = function (new_doc, dataset) {
var dfd = new Deferred();
var db_url = dataset.db_url;
var view_url = dataset.view_url;
var _id = new_doc['id'];
var cdb = new my.CouchDBWrapper(db_url, view_url);
delete new_doc['id'];
if (dataset.record_create)
new_doc = dataset.record_create(new_doc);
if (_id !== 1 && _id !== undefined) {
new_doc['_id'] = _id;
}
else {
new_doc['_id'] = randomId(32, '#a');
}
dfd.resolve(cdb.upsert(new_doc));
return dfd.promise();
};
_updateDocument = function (new_doc, dataset) {
var dfd = new Deferred();
var db_url = dataset.db_url;
var view_url = dataset.view_url;
var _id = new_doc['id'];
var cdb = new my.CouchDBWrapper(db_url, view_url);
delete new_doc['id'];
if (view_url.search('_all_docs') !== -1) {
jqxhr = cdb.get(_id);
}
else {
_id = new_doc['_id'].split('__')[0];
jqxhr = cdb.get(_id);
}
jqxhr.done(function(old_doc){
if (dataset.record_update)
new_doc = dataset.record_update(new_doc, old_doc);
new_doc = _.extend(old_doc, new_doc);
new_doc['_id'] = _id;
dfd.resolve(cdb.upsert(new_doc));
}).fail(function(args){
dfd.reject(args);
});
return dfd.promise();
};
_deleteDocument = function (del_doc, dataset) {
var dfd = new Deferred();
var db_url = dataset.db_url;
var view_url = dataset.view_url;
var _id = del_doc['id'];
var cdb = new my.CouchDBWrapper(db_url, view_url);
if (view_url.search('_all_docs') !== -1)
return cdb.remove(_id);
else {
_id = model.get('_id').split('__')[0];
var jqxhr = cdb.get(_id);
jqxhr.done(function(old_doc){
if (dataset.record_delete)
old_doc = dataset.record_delete(del_doc, old_doc);
if (_.isNull(del_doc))
dfd.resolve(cdb.remove(_id)); // XXX is this the right thing to do?
else {
// couchdb uses _id to identify documents, Backbone models use id.
// we should remove it before sending it to the server.
old_doc['_id'] = _id;
delete old_doc['id'];
dfd.resolve(cdb.upsert(old_doc));
}
}).fail(function(args){
dfd.reject(args);
});
return dfd.promise();
}
};
}(jQuery, this.recline.Backend.CouchDB));