Mango Query
***********

Summary
=======


With the new release of CouchDB 2.0, Apache brought us the Mango Query. It's an adapted version of Cloudant Query for CouchDB. It's very similar to MongoDB Query syntax.

It lets you create indexes and perform queries with more ease that map/reduce. For more details, you may take a look at this :

- `New feature: Mango Query <https://blog.couchdb.org/2016/08/03/feature-mango-query/>`_
- `Cloudant Query <https://developer.ibm.com/clouddataservices/docs/cloudant/get-started/use-cloudant-query/>`_
- `Mango source code <https://github.com/cloudant/mango/>`_

PHPOnCouch and Mango
====================

With the recently added new available function to let you use the new Mango Query. This is very minimalist at the moment but feel free to suggest any ameliorations.

The Mango Query functionalities have been implemented directly in the CouchClient.



Functions
=========

.. php:namespace:: PHPOnCouch

.. php:class:: CouchClient


:hidden:`getIndexes`
""""""""""""""""""""

    .. php:method:: getIndexes()

        This function returns you an array of indexes. Each index will have those properties :

        - ddoc: The design document id  of the index
        - name: The name of the index
        - type: The type of the index (special,text,json)
        - def: The fields indexes

        By default, you always have one index:  \_all_docs

        Example :

        .. code-block:: php

            $indexes = $client->getIndexes();

            /*
            [
                {
                    "ddoc": null,
                    "name": "_all_docs",
                    "type": "special",
                    "def": {
                        "fields": [
                            {
                                "_id": "asc"
                            }
                        ]
                    }
                }
            ]
             */
            }

:hidden:`createIndex`
"""""""""""""""""""""

    .. php:method:: createIndex(array $fields, $name = null, $ddoc = null, $type = 'json')

        This function creates an index.

        :params array $fields: The fields that will be indexed
        :params string $name: The name of the index. If null, one will be generated by Couch.
        :params string $ddoc: The design document id to store the index. If null, CouchDB will create one.
        :params string $type: The type of the index. Only JSON is supported for the moment.

        :returns stdClass: An object. The object contains the following properties:

            - result : Message that normally returns "created" or "exists"
            - id     : The id of the undex.
            - name   : The name of the index.

        Example :

        .. code-block:: php

            $index = client->createIndex(['firstName', 'birthDate', 'lastName'], 'personIdx', 'person');

            /*
            $index should give :
            {
                "result":"created",
                "id":"_design/person",
                "name":"personIdx"
            }
             */

:hidden:`find`
""""""""""""""

    .. php:method:: find($selector, $index = null)

        The new **find()** function let you query the database by using the new Mango Query.  You can provide a selector query multiple fields and use conditional queries.
        You can sort your query and also determine which fields you want to retrieve. CouchDB will automatically select the most efficient index for your query but
        it's preferred to specify the index for faster results. Also, the **limit(number)** and **skip(number)** can be applied to the client before the query.

        **Supported query parameters**

        You can use the following query parameters :

        - limit(number) : Limit  the number of documents that will be returned.
        - skip(n) : Skip n documents and return the documents following.
        - sort(sortSyntax) : Array or values that follow the `sort syntax <http://docs.couchdb.org/en/latest/api/database/find.html#find-sort/>`_
        - fields(fieldsArray) : An array of fields that you want to return from the documents. If null, all the fields will be returned.

        :params stdClass|array $selector: A selector object or array that follows the `Mango query documentation <http://docs.couchdb.org/en/latest/api/database/find.html#selector-syntax/>`_
        :params string $index: The name of the index to use("<design_document>" or ["<design_document>", "<index_name>"]). Otherwise automatically choosen.
        :returns array: Returns an array of documents

        Example :

        .. code-block:: php

            $selector = [
                '$and' =>
                [
                    ['age' => ['$gt' => 16]],
                    ['gender' => ['$eq' => 'Female']]
                ]
            ];
            $docs = $client->skip(10)->limit(30)->sort(["age"])->fields(['firstName'])->find($selector);

:hidden:`explain`
"""""""""""""""""

    .. php:method:: explain($selector, $index = null)

        Let you perform a query like if you were using the :meth:`CouchClient::find` function. Therefore, the explain will not returns any documents. Instead, it will give you all the details about the query. For example, it could tell you which index has been automatically selected.

        For the parameter, please refer to the :meth:`CouchClient::find` parameters.

        :returns: It returns a object with a lot of detailed properties. Here are main properties :

            - dbname : The name of the database
            - index : Index object used to fullfil the query
            - selector : The selector used for the query
            - opts : The query options used for the query
            - limit : The limit used
            - skip : The skip parameter used
            - fields : The fields returned by the query
            - range : Range parameters passed to the underlying view

        Example :

        .. code-block:: php

            $selector = [
            'year'=>['$gt'=>2010]
            ];
            $details = $client->skip(0)->limit(2)->fields(['_id','_rev','year','title'])->sort(['year'=>'asc'])->find($selector);

        The $details values would be the equivalent in JSON :

        .. code-block:: json

            {
                "dbname": "movies",
                "index": {
                    "ddoc": "_design/0d61d9177426b1e2aa8d0fe732ec6e506f5d443c",
                    "name": "0d61d9177426b1e2aa8d0fe732ec6e506f5d443c",
                    "type": "json",
                    "def": {
                        "fields": [
                            {
                                "year": "asc"
                            }
                        ]
                    }
                },
                "selector": {
                    "year": {
                        "$gt": 2010
                    }
                },
                "opts": {
                    "use_index": [],
                    "bookmark": "nil",
                    "limit": 2,
                    "skip": 0,
                    "sort": {},
                    "fields": [
                        "_id",
                        "_rev",
                        "year",
                        "title"
                    ],
                    "r": [
                        49
                    ],
                    "conflicts": false
                },
                "limit": 2,
                "skip": 0,
                "fields": [
                    "_id",
                    "_rev",
                    "year",
                    "title"
                ],
                "range": {
                    "start_key": [
                        2010
                    ],
                    "end_key": [
                        {}
                    ]
                }
            }


