Provides a simple, MongoDB-inspired query language that accomplishes the same thing as the map/reduce API, but with far less code.
Eventually this will replace PouchDB's map/reduce API entirely. You'll still be able to use map/reduce, but it will be distributed as a separate plugin.
Warning: this is beta software! It may change at anytime and could be unstable.
Implemented: $lt
, $gt
, $lte
, $gte
, $eq
, $exists
, $type
, multi-field queries, multi-field indexes, multi-field sort, 'deep.fields.like.this'
, ascending and descending sort.
0.2.0: $and
, $ne
0.3.0: limit
, skip
, ddoc
when creating an index
Not implemented yet: $regex
, $in
, $nin
, $or
, $not
, $nor
, $all
, $elemMatch
, $size
, $mod
To use this plugin in the browser, include it after pouchdb.js
in your HTML page:
<script src="pouchdb.js"></script>
<script src="pouchdb.find.js"></script>
You can also download it from Bower:
bower install pouchdb-find
Or to use it in Node.js, just npm install it:
npm install pouchdb-find
And then attach it to the PouchDB
object:
var PouchDB = require('pouchdb');
PouchDB.plugin(require('pouchdb-find'));
This API is modeled after the Cloudant query API, soon to be merged into CouchDB 2.0. Read that page for more details.
As with PouchDB, the entire API accepts either the callback or the Promise style.
Overview
db.createIndex(index [, callback])
db.getIndexes([callback])
db.deleteIndex(index [, callback])
db.find(request [, callback])
Create an index if it doesn't exist, or do nothing if it already exists.
Example:
db.createIndex({
index: {
fields: ['foo']
}
}).then(function (result) {
// yo, a result
}).catch(function (err) {
// ouch, an error
});
The result can be either:
{"result": "created"} // index was created
or:
{"result": "exists"} // index already exists
You can also create an index on multiple fields:
db.createIndex({
index: {
fields: ['foo', 'bar', 'baz']
}
});
Or an index on deep fields:
db.createIndex({
index: {
fields: ['person.address.zipcode']
}
});
You can also specify additional options, if you want more control over how your index is created:
db.createIndex({
index: {
fields: ['foo', 'bar'],
name: 'myindex',
ddoc: 'mydesigndoc'
type: 'json',
}
});
Options
fields
is a list of fields to indexname
(optional) name of the index, auto-generated if you don't include itddoc
(optional) design document name (i.e. the part after'_design/'
, auto-generated if you don't include ittype
(optional) only supports'json'
, and it's also the default
Get a list of all the indexes you've created. Also tells you about the special _all_docs
index, i.e. the default index on the _id
field.
Example:
db.getIndexes().then(function (result) {
// yo, a result
}).catch(function (err) {
// ouch, an error
});
Example result:
{
"indexes": [
{
"ddoc": null,
"name": "_all_docs",
"type": "special",
"def": {
"fields": [
{
"_id": "asc"
}
]
}
},
{
"ddoc": "_design/idx-0f3a6f73110868266fa5c688caf8acd3",
"name": "idx-0f3a6f73110868266fa5c688caf8acd3",
"type": "json",
"def": {
"fields": [
{
"foo": "asc"
},
{
"bar": "asc"
}
]
}
}
]
}
Delete an index and clean up any leftover data on the disk.
Options
index
Definition of an index to delete. You can pass it in exactly as you received it from thegetIndexes()
API. You cannot delete the built-in_all_docs
index.
Example:
db.deleteIndex({
"ddoc": "_design/idx-0f3a6f73110868266fa5c688caf8acd3",
"name": "idx-0f3a6f73110868266fa5c688caf8acd3",
"type": "json",
"def": {
"fields": [
{
"foo": "asc"
},
{
"bar": "asc"
}
]
}
}).then(function (result) {
// yo, a result
}).catch(function (err) {
// ouch, an error
});
Notice that you don't need to provide a _rev
! The design doc is also deleted.
Query the API to find some documents.
Example:
db.find({
selector: {name: 'Mario'},
fields: ['_id', 'name'],
sort: ['name']
}).then(function (result) {
// yo, a result
}).catch(function (err) {
// ouch, an error
});
Example result:
{
"docs": [
{
"_id": "mario",
"name": "Mario"
}
]
}
Options;
selector
Defines a selector to filter the results. Required.$lt
Match fields "less than" this one.$gt
Match fields "greater than" this one.$lte
Match fields "less than or equal to" this one.$gte
Match fields "greater than or equal to" this one.$eq
Match fields equal to this one.$ne
Match fields not equal to this one.$exists
True if the field should exist, false otherwise.$type
One of: "null", "boolean", "number", "string", "array", or "object".
fields
(Optional) Defines a list of fields that you want to receive. If omitted, you get the full documents.sort
(Optional) Defines a list of fields defining how you want to sort. Note that sorted fields also have to be selected in theselector
.limit
(Optional) Maximum number of documents to return.skip
(Optional) Number of docs to skip before returning.
If there's no index that matches your selector
/sort
, then this method will throw an error. This is a good thing, because it means it's pretty much impossible to write a slow query. :)
The best index will be chosen automatically. If you want to see the query plan for your query, then turn on debugging.
See the Cloudant docs for more details.
Find all docs where doc.name === 'Mario'
:
db.find({
selector: {name: {$eq: 'Mario'}}
});
This is equivalent to:
db.find({
selector: {name: 'Mario'}
});
Find all docs where doc.series === 'Mario'
and doc.debut > 1990
:
db.find({
selector: {
series: 'Mario',
debut: { $gt: 1990 }
}
});
This is equivalent to:
db.find({
selector: {
$and: [
{ series: 'Mario' },
{ debut: { $gt: 1990 } }
]
}
});
Return all docs sorted by doc.debut
descending:
db.find({
selector: {
debut: {'$exists': true}
},
sort: [{debut: 'desc'}]
});
For more examples, refer to Cloudant's _find
documentation.
Over HTTP, this plugin currently only works with Cloudant. Cloudant is the reference implementation, so the API should be the same.
PouchDB Server also has this API, since it includes this very plugin by default.
Eventually CouchDB 2.0 will also be supported.
Just call:
PouchDB.debug.enable('pouchdb:find')
Then pouchdb-find
will start logging some debug information to the console. This can be useful if, for instance, you want to see the query plan that is being used to execute your queries.
Instructions are in CONTRIBUTING.md.