This project is not being actively maintained. If you are interested in helping to maintain this project, take a look at the open issues on GitHub and submit pull requests.

Views and Map-Reduce Queries

CouchDB uses views filtered through map-reduce to query all the documents of your database. Each view has a map- and optionally a reduce-function. Doctrine CouchDB ODM allows you to create and query views in your application.

Creating and Managing Views

Views are best managed as a folder structure in the filesystem. Create a Directory couchdb/views and instantiate a FolderDesignDocument in the following way and create the design document in the database:

1<?php use Doctrine\CouchDB\View\FolderDesignDocument; $view = new FolderDesignDocument("path/to/app/couchdb"); $designDocJson = $view->getData(); $couchClient->createDesignDocument("myapp", $view);
2
3
4
5
6
7

If the directory structure now looked like the following:

couchdb/
    views/
        username/
            map.js
        article-dates/
            map.js
            reduce.js

It will create two views username and article-dates with corresponding map and reduce functions. For example the username map.js might look like:

1function(doc) { if (doc.type == 'Doctrine.Tests.Models.CMS.CmsUser') { emit(doc.username, doc._id); } }
2
3
4
5

Querying Views

To query a view from Doctrine CouchDB ODM you have to register it with its design document name in the CouchDB ODM Configuration:

1<?php $config = $dm->getConfiguration(); $config->addDesignDocument( "myapp", "Doctrine\CouchDB\View\FolderDesignDocument", "path/to/app/couchdb" );
2
3
4
5
6
7
8

You can then create either a native or a odm-query by calling either DocumentManager#createNativeQuery($designDocName, $viewName) or DocumentManager#createQuery($designDocName, $viewName).

The difference between both queries is their result and some parameters. The ODM query will return instances of php objects that map to the CouchDB documents and the native query will return only convert the json to arrays that have been fetched from the CouchDB.

Both queries have a common base class with a simple API:

1<?php namespace Doctrine\CouchDB\View; abstract class AbstractQuery { /** * Get HTTP Query Parameter * * @param string $key * @return mixed */ public function getParameter($key); /** * Query the view with the current params. * * @return Doctrine\CouchDB\View\Result */ public function execute(); /** * Create design document for this query. * * Method is used internally when querying the view and it doesnt exist yet. * * @return void */ public function createDesignDocument(); }
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

With both query types you just call execute() to retrieve the result from the database.

The following query parameter related methods exist in both the native and odm-query:

1<?php namespace Doctrine\CouchDB\View; class Query extends AbstractQuery { /** * Find key in view. * * @param string $val * @return Query */ public function setKey($val); /** * Set starting key to query view for. * * @param string $val * @return Query */ public function setStartKey($val); /** * Set ending key to query view for. * * @param string $val * @return Query */ public function setEndKey($val); /** * Document id to start with * * @param string $val * @return Query */ public function setStartKeyDocId($val); /** * Last document id to include in the output * * @param string $val * @return Query */ public function setEndKeyDocId($val); /** * Limit the number of documents in the output * * @param int $val * @return Query */ public function setLimit($val); /** * Skip n number of documents * * @param int $val * @return Query */ public function setSkip($val); /** * If stale=ok is set CouchDB will not refresh the view even if it is stalled. * * @param bool $flag * @return Query */ public function setStale($flag); /** * reverse the output * * @param bool $flag * @return Query */ public function setDescending($flag); /** * The group option controls whether the reduce function reduces to a set of distinct keys or to a single result row. * * @param bool $flag * @return Query */ public function setGroup($flag); public function setGroupLevel($level); /** * Use the reduce function of the view. It defaults to true, if a reduce function is defined and to false otherwise. * * @param bool $flag * @return Query */ public function setReduce($flag); /** * Controls whether the endkey is included in the result. It defaults to true. * * @param bool $flag * @return Query */ public function setInclusiveEnd($flag); /** * Automatically fetch and include the document which emitted each view entry * * @param bool $flag * @return Query */ public function setIncludeDocs($flag); }
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

There is a single additional method on the ODM Query that specifies if you just want to return the documents associated with a view result:

1<?php namespace Doctrine\ODM\CouchDB\View; class ODMQuery extends Query { public function onlyDocs($flag); }
2
3
4
5
6
7

An example execution of the username view given above looks like:

1<?php $query = $dm->createQuery("myapp", "username"); $result = $query->setStartKey("b") ->setEndKey("c") ->setLimit(100) ->setSkip(20) ->onlyDocs(true) ->execute();
2
3
4
5
6
7
8
9

This will return all usernames starting with b and ending with c, skipping the first 20 results and limiting the result to 100 documents.

View Results

The result of a view is an instance of Doctrine\CouchDB\View\Result. It implements Countable, IteratorAggregate and ArrayAccess. If you specify onlyDocs(true) each result-row will contain only the associated document, otherwise the document is on the row index doc of the query.

The following snippet shows the difference:

1<?php $query = $dm->createQuery("myapp", "username"); $result = $query->setStartKey("b") ->setEndKey("c") ->setLimit(100) ->setSkip(20) ->onlyDocs(true) ->execute(); foreach ($result AS $user) { echo $user->getUsername() . "\n"; } $query->onlyDocs(false); $result = $query->execute(); foreach ($result AS $userRow) { echo $userRow['doc']->getUsername() . "\n"; }
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20