{"action":"created","comment":{"url":"https://api.github.com/repos/cloudant/sync-android/pulls/comments/24669599","id":24669599,"diff_hunk":"@@ -0,0 +1,545 @@\n+# Cloudant Query - Android\n+\n+Cloudant Query - Android is a Java implementation of [Cloudant Query][1] for Android mobile devices. It is included as a sub-package of [sync-android][2].\n+\n+Cloudant Query is inspired by MongoDB's query implementation, so users of MongoDB should feel at home using Cloudant Query in their mobile applications.\n+\n+The aim is that the query you use on our cloud-based database works for your mobile application.\n+\n+**Note**: this is a very early version, and it probably won't work as you expect yet! In\n+particular, there's very little information to help debugging when errors happen, leaving you\n+in the debugger. There is also little error checking, so things might explode without warning.\n+  \n+\n+[1]: https://docs.cloudant.com/api/cloudant-query.html\n+[2]: https://github.com/cloudant/sync-android\n+\n+## Usage\n+\n+These notes assume familiarity with Cloudant Sync Datastore.\n+\n+Cloudant Query uses indexes explicitly defined over the fields in the document. Multiple indexes can be created for use in different queries, the same field may end up indexed in more than one index.\n+\n+Querying is carried out by supplying a query in the form of a map which describes the query.\n+\n+For the following examples, assume two things.\n+\n+Firstly, we set up an `IndexManager` object, `im`, as follows:\n+\n+```java\n+import com.cloudant.sync.datastore.DatastoreManager;\n+import com.cloudant.sync.datastore.Datastore;\n+import com.cloudant.sync.query.IndexManager;\n+\n+File path = getApplicationContext().getDir(\"datastores\");\n+DatastoreManager manager = new DatastoreManager(path.getAbsolutePath());\n+Datastore ds = manager.openDatastore(\"my_datastore\");\n+IndexManager im = new IndexManager(ds);\n+```\n+\n+The `IndexManager` object provides the ability to manage query indexes and execute queries.\n+\n+Secondly, these documents are in the datastore:\n+\n+```java\n+{ \"name\": \"mike\", \n+  \"age\": 12, \n+  \"pet\": {\"species\": \"cat\"} };\n+\n+{ \"name\": \"mike\", \n+  \"age\": 34, \n+  \"pet\": {\"species\": \"dog\"} };\n+\n+{ \"name\": \"fred\", \n+  \"age\": 23, \n+  \"pet\": {\"species\": \"cat\"} };\n+```\n+\n+### Creating indexes\n+\n+In order to query documents, indexes need to be created over\n+the fields to be queried against.\n+\n+Use `ensureIndexed(List<Object> fieldNames, String indexName)` to create indexes. These indexes are persistent across application restarts as they are saved to disk. They are kept up to date documents change; there's no need to call `ensureIndexed(List<Object> fieldNames, String indexName)` each time your applications starts, though there is no harm in doing so.\n+\n+The first argument to `ensureIndexed(List<Object> fieldNames, String indexName)` is a list of fields to put into this index. The second argument is a name for the index. This is used to delete indexes at a later stage and appears when you list the indexes in the database.\n+\n+A field can appear in more than one index. The query engine will select an appropriate index to use for a given query. However, the more indexes you have, the more disk space they will use and the greater overhead in keeping them up to date.\n+\n+To index values in sub-documents, use _dotted notation_. This notation puts the field names in the path to a particular value into a single string, separated by dots. Therefore, to index the `species` field of the `pet` sub-document in the examples above, use `pet.species`.\n+\n+```java\n+// Create an index over the name, age, and species fields.\n+String name = im.ensureIndexed(Arrays.<Object>asList(\"name\", \"age\", \"pet.species\"), \n+                               \"basic\");\n+if (name == null) {\n+    // there was an error creating the index\n+}\n+```\n+\n+`ensureIndexed(List<Object> fieldNames, String indexName)` returns the name of the index if it is successful, otherwise it returns `null`.\n+\n+If an index needs to be changed, first delete the existing index by calling `deleteIndexNamed(String indexName)` where the argument is the index name, then call  `ensureIndexed(List<Object> fieldNames, String indexName)` with the new definition.\n+\n+#### Indexing document metadata (_id and _rev)\n+\n+The document ID and revision ID are automatically indexed under `_id` and `_rev` \n+respectively. If you need to query on document ID or document revision ID,\n+use these field names.\n+\n+#### Indexing array fields\n+\n+Indexing of array fields is supported. See \"Array fields\" below for the indexing and\n+querying semantics.\n+\n+### Querying syntax\n+\n+Query documents using `Map` objects. These use the [Cloudant Query `selector`][sel]\n+syntax. Several features of Cloudant Query are not yet supported in this implementation.\n+See below for more details.\n+\n+[sel]: https://docs.cloudant.com/api/cloudant-query.html#selector-syntax\n+\n+#### Equality and comparisons\n+\n+To query for all documents where `pet.species` is `cat`:\n+\n+```java\n+// query: { \"pet.species\": \"cat\" }\n+Map<String, Object> query = new HashMap<String, Object>();\n+query.put(\"pet.species\", \"cat\");\n+```\n+\n+If you don't specify a condition for the clause, equality (`$eq`) is used. To use other conditions, supply them explicitly in the clause.\n+\n+To query for documents where `age` is greater than twelve use the `$gt` condition:\n+\n+```java\n+// query: { \"age\": { \"$gt\": 12 } }\n+Map<String, Object> query = new HashMap<String, Object>();\n+Map<String, Object> gt12 = new HashMap<String, Object>();\n+gt12.put(\"$gt\", 12);\n+query.put(\"age\", gt12);\n+```\n+\n+See below for supported operators (Selections -> Conditions).\n+\n+#### Compound queries\n+\n+Compound queries allow selection of documents based on more than one criteria.  If you specify several clauses, they are implicitly joined by AND.\n+\n+To find all people named `fred` with a `cat` use:\n+\n+```java\n+// query: { \"name\": \"fred\", \"pet.species\": \"cat\" }\n+Map<String, Object> query = new HashMap<String, Object>();\n+query.put(\"name\", \"fred\");\n+query.put(\"pet.species\", \"cat\");\n+```\n+\n+##### Using OR to join clauses\n+\n+Use `$or` to find documents where just one of the clauses match.\n+\n+To find all people with a `dog` who are under thirty:\n+\n+```java\n+// query: { \"$or\": [ { \"pet.species\": { \"$eq\": \"dog\" } }, \n+//                   { \"age\": { \"$lt\": 30 } }\n+//                 ]}\n+Map<String, Object> query = new HashMap<String, Object>();\n+Map<String, Object> petClause = new HashMap<String, Object>();\n+Map<String, Object> eqDog = new HashMap<String, Object>();\n+eqDog.put(\"$eq\", \"dog\");\n+petClause.put(\"pet.species\", eqDog);\n+Map<String, Object> ageClause = new HashMap<String, Object>();\n+Map<String, Object> lt30 = new HashMap<String, Object>();\n+lt30.put(\"$lt\", 30);\n+ageClause.put(\"age\", lt30);\n+query.put(\"$or\", Arrays.<Object>asList(eqDog, lt30));\n+```\n+\n+#### Using AND and OR in queries\n+\n+Using a combination of AND and OR allows the specification of complex queries.\n+\n+This selects documents where _either_ the person has a pet `dog` _or_ they are\n+both over thirty _and_ named `mike`:\n+\n+```java\n+// query: { \"$or\": [ { \"pet.species\": { \"$eq\": \"dog\" } }, \n+//                   { \"$and\": [ { \"age\": { \"$gt\": 30 } },\n+//                               { \"name\": { \"$eq\": \"mike\" } }\n+//                             ] }\n+//                 ]}\n+Map<String, Object> query = new HashMap<String, Object>();\n+Map<String, Object> petClause = new HashMap<String, Object>();\n+Map<String, Object> eqDog = new HashMap<String, Object>();\n+eqDog.put(\"$eq\", \"dog\");\n+petClause.put(\"pet.species\", eqDog);\n+Map<String, Object> andClause = new HashMap<String, Object>();\n+Map<String, Object> ageClause = new HashMap<String, Object>();\n+Map<String, Object> nameClause = new HashMap<String, Object>();\n+Map<String, Object> gt30 = new HashMap<String, Object>();\n+gt30.put(\"$gt\", 30);\n+ageClause.put(\"age\", gt30);\n+Map<String, Object> eqMike = new HashMap<String, Object>();\n+eqMike.put(\"$eq\", \"mike\");\n+nameClause.put(\"name\", eqMike);\n+andClause.put(\"$and\", Arrays.<Object>asList(ageClause, nameClause));\n+query.put(\"$or\", Arrays.<Object>asList(petClause, andClause));\n+```\n+\n+### Executing queries\n+\n+To find documents matching a query, use the `IndexManager` object's `find(Map<String, Object> query)` method. This returns an object that can be used in `for ( : )` loops to enumerate over the results.\n+\n+```java\n+QueryResult result = im.find(query);\n+for (DocumentRevision rev : result) {\n+    // The returned revision object contains all fields for\n+    // the object. You cannot project certain fields in the\n+    // current implementation.\n+}\n+```\n+\n+There is an extended version of the `find` method which supports:\n+\n+- Sorting results.\n+- Projecting fields from documents rather than returning whole documents.\n+- Skipping results.\n+- Limiting the number of results returned.\n+\n+For any of these, use \n+\n+```java\n+find(Map<String, Object> query,\n+     long skip,\n+     long limit,\n+     List<String> fields,\n+     List<Map<String, String>> sortDocument)\n+```\n+\n+#### Sorting\n+\n+Provide a sort document to the extended version of the `find` method to sort the results of a query. \n+\n+The sort document is a list of fields to sort by. Each field is represented by a map specifying the name of the field to sort by and the direction to sort.\n+\n+The sort document must use fields from a single index.\n+\n+As yet, you can't leave out the sort direction. The sort direction can be `asc` (ascending) or `desc` (descending).\n+\n+```java\n+// sort document: [ { \"name\": \"asc\" },\n+//                  { \"age\": \"desc\" } ]\n+List<Map<String, String>> sortDocument = new ArrayList<Map<String, String>>();\n+Map<String, String> sortByName = new HashMap<String, String>();\n+Map<String, String> sortByAge = new HashMap<String, String>();\n+sortByName.put(\"name\", \"asc\");\n+sortByAge.put(\"age\", \"desc\");\n+sortDocument.add(sortName);\n+sortDocument.add(sortAge);\n+QueryResult queryResult = im.find(query, 0, 0, null, sortDocument);\n+```\n+\n+Pass `null` as the `sort` argument to disable sorting.\n+\n+#### Projecting fields\n+\n+Projecting fields is useful when you have a large document and only need to use a\n+subset of the fields for a given view.\n+\n+To project certain fields from the documents included in the results, pass a list of field names to the `fields` argument. These field names:\n+\n+- Must be top level fields in the document.\n+- Cannot use dotted notation to access sub-documents.\n+\n+For example, in the following document the `name`, `age` and `pet` fields could be projected, but the `species` field inside `pet` cannot:\n+\n+```json\n+{\n+    \"name\": \"mike\",\n+    \"age\": 12,\n+    \"pet\": { \"species\": \"cat\" }\n+}\n+```\n+\n+To project the `name` and `age` fields of the above document:\n+\n+```java\n+List<String> fields = new ArrayList<String>();\n+fields.add(\"name\");\n+fields.add(\"age\");\n+QueryResult queryResult = im.find(query, 0, 0, fields, null);\n+```\n+\n+Pass `null` as the `fields` argument to disable projection.\n+\n+#### Skip and limit\n+\n+Skip and limit allow retrieving subsets of the results. Amongst other things, this is useful in pagination.\n+\n+* `skip` skips over a number of results from the result set.\n+* `limit` defines the maximum number of results to return for the query.\n+\n+To display the twenty-first to thirtieth results:\n+\n+```java\n+QueryResult result = im.find(query, 20, 10, fields, null);\n+```\n+\n+To disable:\n+\n+- `skip`, pass `0` as the `skip` argument.\n+- `limit`, pass `0` as the `limit` argument.\n+\n+### Array fields\n+\n+Indexing and querying over array fields is supported in Cloudant Query Android, with some caveats.\n+\n+Take this document as an example:\n+\n+```\n+{\n+  _id: mike32\n+  pet: [ cat, dog, parrot ],\n+  name: mike,\n+  age: 32\n+}\n+```\n+\n+You can create an index over the `pet` field:\n+\n+```java\n+String name = im.ensureIndexed(Arrays.<Object>asList(\"name\", \"age\", \"pet\"), \n+                               \"basic\");\n+```\n+\n+Each value of the array is treated as a separate entry in the index. This means that a query such as:\n+\n+```\n+{ pet: { $eq: cat } }\n+```\n+\n+Will return the document `mike32`. Negation may be slightly confusing:\n+\n+```\n+{ pet: { $not: { $eq: cat } } }\n+```\n+\n+Will also return `mike32` because there are values in the array that are not `cat`. That is,\n+this operator is matching for \"any values that do not equal 'cat'\".\n+\n+#### Restrictions\n+\n+Only one field in a given index may be an array. This is because each entry in each array\n+requires an entry in the index, causing a Cartesian explosion in index size. Taking the\n+above example, this document wouldn't be indexed because the `name` and `pet` fields are\n+both indexed in a single index:\n+\n+\n+```\n+{\n+  _id: mike32\n+  pet: [ cat, dog, parrot ],\n+  name: [ mike, rhodes ],\n+  age: 32\n+}\n+```\n+\n+If this happens, an error will be emitted into the log but the indexing process will be\n+successful.\n+\n+However, if there was one index with `pet` in and another with `name` in, like this:\n+\n+```java\n+String indexOne = im.ensureIndexed(Arrays.<Object>asList(\"name\", \"age\"), \n+                                   \"index_one\");\n+String indexTwo = im.ensureIndexed(Arrays.<Object>asList(\"age\", \"pet\"),\n+                                   \"index_two\");\n+```\n+\n+The document _would_ be indexed in both of these indexes: each index only contains one of\n+the array fields.\n+\n+Also see \"Unsupported features\", below.\n+\n+\n+### Errors\n+\n+Error reporting is terrible right now. The only indication something went wrong is a `null` return value from the `find` methods or `ensureIndexed(List<Object> fieldNames, String indexName)`. We're working on\n+adding logging.\n+\n+## Supported Cloudant Query features\n+\n+Right now the list of supported features is:\n+\n+- Create compound indexes using dotted notation that index JSON fields.\n+- Delete index by name.\n+- Execute nested queries.\n+- Limiting returned results.\n+- Skipping results.\n+- Queries can include unindexed fields.\n+      \n+Selectors -> combination\n+\n+- `$and`\n+- `$or`\n+\n+Selectors -> Conditions -> Equalities\n+\n+- `$lt`\n+- `$lte`\n+- `$eq`\n+- `$gte`\n+- `$gt`\n+- `$ne`\n+\n+Selectors -> combination\n+\n+- `$not`\n+\n+Selectors -> Condition -> Objects\n+\n+- `$exists`\n+\n+Implicit operators\n+\n+- Implicit `$and`.\n+- Implicit `$eq`.\n+\n+Arrays\n+\n+- Indexing individual values in an array.\n+- Querying for individual values in an array.\n+\n+## Unsupported Cloudant Query features\n+\n+As this is an early version of Query on this platform, some features are\n+not supported yet. We're actively working to support features -- check\n+the commit log :)\n+\n+### Query\n+\n+Overall restrictions:\n+\n+- Cannot use covering indexes with projection (`fields`) to avoid loading \n+  documents from the datastore.\n+\n+#### Query syntax\n+\n+- Using non-dotted notation to query sub-documents.\n+    - That is, `{\"pet\": { \"species\": {\"$eq\": \"cat\"} } }` is unsupported,\n+      you must use `{\"pet.species\": {\"$eq\": \"cat\"}}`.\n+- Cannot use multiple conditions in a single clause, `{ field: { $gt: 7, $lt: 14 } }`.\n+\n+Selectors -> combination\n+\n+- `$nor` #10\n+- `$all` (unplanned)\n+- `$elemMatch` (unplanned, waiting on arrays support for query)\n+\n+Selectors -> Condition -> Objects\n+\n+- `$type` (unplanned)\n+\n+Selectors -> Condition -> Array\n+\n+- `$in` (waiting on arrays support)\n+- `$nin` (waiting on arrays support)\n+- `$size` (waiting on arrays support)\n+\n+Selectors -> Condition -> Misc\n+\n+- `$mod` (unplanned, waiting on filtering)\n+- `$regex` (unplanned, waiting on filtering)\n+\n+\n+Arrays\n+\n+- Dotted notation to index or query sub-documents in arrays.\n+- Querying for exact array match, `{ field: [ 1, 3, 7 ] }`.\n+- Querying to match a specific array element using dotted notation, `{ field.0: 1 }`.\n+- Querying using `$all`.\n+- Querying using `$elemMatch`.\n+\n+\n+## Performance\n+\n+### Indexing\n+\n+N/A\n+\n+\n+## Grammar\n+\n+To help, I've tried to write a grammar/schema for the Query language.\n+\n+Here:\n+\n+* Bold is used for the JSON formatting (or to indicate the representation of the use of Map, List etc. in Java).\n+* Italic is variables in the grammar-like thing.\n+* Quotes enclose literal string values.\n+\n+<pre>\n+<em>query</em> := \n+    <strong>{ }</strong>\n+    <strong>{</strong> <em>many-expressions</em> <strong>}</strong>\n+\n+<em>many-expressions</em> := <em>expression</em> (&quot;,&quot; <em>expression</em>)*\n+\n+<em>expression</em> := \n+    <em>compound-expression</em>\n+    <em>comparison-expression</em>\n+\n+<em>compound-expression</em> := \n+    <strong>{</strong> (&quot;$and&quot; | &quot;$nor&quot; | &quot;$or&quot;) <strong>:</strong> <strong>[</strong> <em>many-expressions</em> <strong>] }</strong>  // nor not implemented\n+    \n+<em>comparison-expression</em> :=\n+    <strong>{</strong> <em>field</em> <strong>:</strong> <strong>{</strong> <em>operator-expression</em> <strong>} }</strong>\n+\n+<em>negation-expression</em> := \n+    <strong>{</strong> &quot;$not&quot; <strong>:</strong> <strong>{</strong> <em>operator-expression</em> <strong>} }</strong>\n+\n+<em>operator-expression</em> := \n+    <em>negation-expression</em>\n+    <strong>{</strong> <em>operator</em> <strong>:</strong> <em>simple-value</em> <strong>}</strong>\n+    <strong>{</strong> &quot;$regex&quot; <strong>:</strong> <em>Pattern</em> <strong>}</strong>  // not implemented\n+    <strong>{</strong> &quot;$mod&quot; <strong>:</strong> <strong>[</strong> <em>divisor, remainder</em> <strong>] }</strong>  // not implemented\n+    <strong>{</strong> &quot;$elemMatch&quot; <strong>: {</strong> <em>many-expressions</em> <strong>} }</strong>  // not implemented\n+    <strong>{</strong> &quot;$size&quot; <strong>:</strong> <em>positive-integer</em> <strong>}</strong>  // not implemented\n+    <strong>{</strong> &quot;$all&quot; <strong>:</strong> <em>array-value</em> <strong>}</strong>  // not implemented\n+    <strong>{</strong> &quot;$in&quot; <strong>:</strong> <em>array-value</em> <strong>}</strong>  // not implemented\n+    <strong>{</strong> &quot;$nin&quot; <strong>:</strong> <em>array-value</em> <strong>}</strong>  // not implemented\n+    <strong>{</strong> &quot;$exists&quot; <strong>:</strong> <em>boolean</em> <strong>}</strong>\n+    <strong>{</strong> &quot;$type&quot; <strong>:</strong> <em>type</em> <strong>}</strong>  // not implemented\n+\n+<em>operator</em> := &quot;$gt&quot; | &quot;$gte&quot; | &quot;$lt&quot; | &quot;$lte&quot; | &quot;$eq&quot; | &quot;$neq&quot;\n+\n+// Obviously List, but easier to express like this\n+<em>array-value</em> := <strong>[</strong> simple-value (&quot;,&quot; simple-value)+ <strong>]</strong>\n+\n+// Java mappings of basic types\n+\n+<em>field</em> := <em>String</em>  // a field name\n+\n+<em>simple-value</em> := <em>String</em> | <em>Number</em>\n+\n+<em>positive-integer</em> := <em>Integer</em>\n+\n+<em>boolean</em> := <em>Boolean</em>\n+\n+<em>type</em> := <em>Class</em>\n+</pre>\n+\n+\n+\n+## Requirements\n+\n+This package as well as all of its dependencies co-exist in the [Cloudant Sync - Android Datastore][2].  Installing that package by default installs this sub-package.","path":"doc/query.md","position":null,"original_position":540,"commit_id":"d5b4f7825035187c3ef55b5962f38b66806f68d3","original_commit_id":"5bb220936d0d68cb146a0012668235b7cae70804","user":{"login":"alfinkel","id":8793303,"avatar_url":"https://avatars.githubusercontent.com/u/8793303?v=3","gravatar_id":"","url":"https://api.github.com/users/alfinkel","html_url":"https://github.com/alfinkel","followers_url":"https://api.github.com/users/alfinkel/followers","following_url":"https://api.github.com/users/alfinkel/following{/other_user}","gists_url":"https://api.github.com/users/alfinkel/gists{/gist_id}","starred_url":"https://api.github.com/users/alfinkel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alfinkel/subscriptions","organizations_url":"https://api.github.com/users/alfinkel/orgs","repos_url":"https://api.github.com/users/alfinkel/repos","events_url":"https://api.github.com/users/alfinkel/events{/privacy}","received_events_url":"https://api.github.com/users/alfinkel/received_events","type":"User","site_admin":false},"body":"Done in https://github.com/cloudant/sync-android/commit/d5b4f7825035187c3ef55b5962f38b66806f68d3","created_at":"2015-02-13T15:09:16Z","updated_at":"2015-02-13T15:09:16Z","html_url":"https://github.com/cloudant/sync-android/pull/94#discussion_r24669599","pull_request_url":"https://api.github.com/repos/cloudant/sync-android/pulls/94","_links":{"self":{"href":"https://api.github.com/repos/cloudant/sync-android/pulls/comments/24669599"},"html":{"href":"https://github.com/cloudant/sync-android/pull/94#discussion_r24669599"},"pull_request":{"href":"https://api.github.com/repos/cloudant/sync-android/pulls/94"}}},"pull_request":{"url":"https://api.github.com/repos/cloudant/sync-android/pulls/94","id":29029053,"html_url":"https://github.com/cloudant/sync-android/pull/94","diff_url":"https://github.com/cloudant/sync-android/pull/94.diff","patch_url":"https://github.com/cloudant/sync-android/pull/94.patch","issue_url":"https://api.github.com/repos/cloudant/sync-android/issues/94","number":94,"state":"open","locked":false,"title":"Add Cloudant Query markdown document","user":{"login":"alfinkel","id":8793303,"avatar_url":"https://avatars.githubusercontent.com/u/8793303?v=3","gravatar_id":"","url":"https://api.github.com/users/alfinkel","html_url":"https://github.com/alfinkel","followers_url":"https://api.github.com/users/alfinkel/followers","following_url":"https://api.github.com/users/alfinkel/following{/other_user}","gists_url":"https://api.github.com/users/alfinkel/gists{/gist_id}","starred_url":"https://api.github.com/users/alfinkel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alfinkel/subscriptions","organizations_url":"https://api.github.com/users/alfinkel/orgs","repos_url":"https://api.github.com/users/alfinkel/repos","events_url":"https://api.github.com/users/alfinkel/events{/privacy}","received_events_url":"https://api.github.com/users/alfinkel/received_events","type":"User","site_admin":false},"body":"This PR adds documentation for the new Cloudant Query functionality and redirects the link in the main sync-android readme.md from the old index-query.md to the new query.md.  Also, added empty lines at the end of all Query Java classes that did not have them before.  This was noted in a previous comment as a need to bring the code more in line with our coding standards.","created_at":"2015-02-10T17:53:52Z","updated_at":"2015-02-13T15:09:16Z","closed_at":null,"merged_at":null,"merge_commit_sha":"05699e88dcdfed2baac5ea697736941497482978","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/cloudant/sync-android/pulls/94/commits","review_comments_url":"https://api.github.com/repos/cloudant/sync-android/pulls/94/comments","review_comment_url":"https://api.github.com/repos/cloudant/sync-android/pulls/comments/{number}","comments_url":"https://api.github.com/repos/cloudant/sync-android/issues/94/comments","statuses_url":"https://api.github.com/repos/cloudant/sync-android/statuses/d5b4f7825035187c3ef55b5962f38b66806f68d3","head":{"label":"cloudant:44269-query-add-query-doc","ref":"44269-query-add-query-doc","sha":"d5b4f7825035187c3ef55b5962f38b66806f68d3","user":{"login":"cloudant","id":44642,"avatar_url":"https://avatars.githubusercontent.com/u/44642?v=3","gravatar_id":"","url":"https://api.github.com/users/cloudant","html_url":"https://github.com/cloudant","followers_url":"https://api.github.com/users/cloudant/followers","following_url":"https://api.github.com/users/cloudant/following{/other_user}","gists_url":"https://api.github.com/users/cloudant/gists{/gist_id}","starred_url":"https://api.github.com/users/cloudant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cloudant/subscriptions","organizations_url":"https://api.github.com/users/cloudant/orgs","repos_url":"https://api.github.com/users/cloudant/repos","events_url":"https://api.github.com/users/cloudant/events{/privacy}","received_events_url":"https://api.github.com/users/cloudant/received_events","type":"Organization","site_admin":false},"repo":{"id":16811502,"name":"sync-android","full_name":"cloudant/sync-android","owner":{"login":"cloudant","id":44642,"avatar_url":"https://avatars.githubusercontent.com/u/44642?v=3","gravatar_id":"","url":"https://api.github.com/users/cloudant","html_url":"https://github.com/cloudant","followers_url":"https://api.github.com/users/cloudant/followers","following_url":"https://api.github.com/users/cloudant/following{/other_user}","gists_url":"https://api.github.com/users/cloudant/gists{/gist_id}","starred_url":"https://api.github.com/users/cloudant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cloudant/subscriptions","organizations_url":"https://api.github.com/users/cloudant/orgs","repos_url":"https://api.github.com/users/cloudant/repos","events_url":"https://api.github.com/users/cloudant/events{/privacy}","received_events_url":"https://api.github.com/users/cloudant/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cloudant/sync-android","description":"A JSON-based document datastore for Android applications","fork":false,"url":"https://api.github.com/repos/cloudant/sync-android","forks_url":"https://api.github.com/repos/cloudant/sync-android/forks","keys_url":"https://api.github.com/repos/cloudant/sync-android/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cloudant/sync-android/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cloudant/sync-android/teams","hooks_url":"https://api.github.com/repos/cloudant/sync-android/hooks","issue_events_url":"https://api.github.com/repos/cloudant/sync-android/issues/events{/number}","events_url":"https://api.github.com/repos/cloudant/sync-android/events","assignees_url":"https://api.github.com/repos/cloudant/sync-android/assignees{/user}","branches_url":"https://api.github.com/repos/cloudant/sync-android/branches{/branch}","tags_url":"https://api.github.com/repos/cloudant/sync-android/tags","blobs_url":"https://api.github.com/repos/cloudant/sync-android/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cloudant/sync-android/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cloudant/sync-android/git/refs{/sha}","trees_url":"https://api.github.com/repos/cloudant/sync-android/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cloudant/sync-android/statuses/{sha}","languages_url":"https://api.github.com/repos/cloudant/sync-android/languages","stargazers_url":"https://api.github.com/repos/cloudant/sync-android/stargazers","contributors_url":"https://api.github.com/repos/cloudant/sync-android/contributors","subscribers_url":"https://api.github.com/repos/cloudant/sync-android/subscribers","subscription_url":"https://api.github.com/repos/cloudant/sync-android/subscription","commits_url":"https://api.github.com/repos/cloudant/sync-android/commits{/sha}","git_commits_url":"https://api.github.com/repos/cloudant/sync-android/git/commits{/sha}","comments_url":"https://api.github.com/repos/cloudant/sync-android/comments{/number}","issue_comment_url":"https://api.github.com/repos/cloudant/sync-android/issues/comments/{number}","contents_url":"https://api.github.com/repos/cloudant/sync-android/contents/{+path}","compare_url":"https://api.github.com/repos/cloudant/sync-android/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cloudant/sync-android/merges","archive_url":"https://api.github.com/repos/cloudant/sync-android/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cloudant/sync-android/downloads","issues_url":"https://api.github.com/repos/cloudant/sync-android/issues{/number}","pulls_url":"https://api.github.com/repos/cloudant/sync-android/pulls{/number}","milestones_url":"https://api.github.com/repos/cloudant/sync-android/milestones{/number}","notifications_url":"https://api.github.com/repos/cloudant/sync-android/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cloudant/sync-android/labels{/name}","releases_url":"https://api.github.com/repos/cloudant/sync-android/releases{/id}","created_at":"2014-02-13T17:52:09Z","updated_at":"2015-02-12T17:46:56Z","pushed_at":"2015-02-13T15:04:28Z","git_url":"git://github.com/cloudant/sync-android.git","ssh_url":"git@github.com:cloudant/sync-android.git","clone_url":"https://github.com/cloudant/sync-android.git","svn_url":"https://github.com/cloudant/sync-android","homepage":"","size":14585,"stargazers_count":65,"watchers_count":65,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":20,"mirror_url":null,"open_issues_count":6,"forks":20,"open_issues":6,"watchers":65,"default_branch":"master"}},"base":{"label":"cloudant:master","ref":"master","sha":"1f844cc8892e403ff2a43104340f51ba00b39460","user":{"login":"cloudant","id":44642,"avatar_url":"https://avatars.githubusercontent.com/u/44642?v=3","gravatar_id":"","url":"https://api.github.com/users/cloudant","html_url":"https://github.com/cloudant","followers_url":"https://api.github.com/users/cloudant/followers","following_url":"https://api.github.com/users/cloudant/following{/other_user}","gists_url":"https://api.github.com/users/cloudant/gists{/gist_id}","starred_url":"https://api.github.com/users/cloudant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cloudant/subscriptions","organizations_url":"https://api.github.com/users/cloudant/orgs","repos_url":"https://api.github.com/users/cloudant/repos","events_url":"https://api.github.com/users/cloudant/events{/privacy}","received_events_url":"https://api.github.com/users/cloudant/received_events","type":"Organization","site_admin":false},"repo":{"id":16811502,"name":"sync-android","full_name":"cloudant/sync-android","owner":{"login":"cloudant","id":44642,"avatar_url":"https://avatars.githubusercontent.com/u/44642?v=3","gravatar_id":"","url":"https://api.github.com/users/cloudant","html_url":"https://github.com/cloudant","followers_url":"https://api.github.com/users/cloudant/followers","following_url":"https://api.github.com/users/cloudant/following{/other_user}","gists_url":"https://api.github.com/users/cloudant/gists{/gist_id}","starred_url":"https://api.github.com/users/cloudant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cloudant/subscriptions","organizations_url":"https://api.github.com/users/cloudant/orgs","repos_url":"https://api.github.com/users/cloudant/repos","events_url":"https://api.github.com/users/cloudant/events{/privacy}","received_events_url":"https://api.github.com/users/cloudant/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cloudant/sync-android","description":"A JSON-based document datastore for Android applications","fork":false,"url":"https://api.github.com/repos/cloudant/sync-android","forks_url":"https://api.github.com/repos/cloudant/sync-android/forks","keys_url":"https://api.github.com/repos/cloudant/sync-android/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cloudant/sync-android/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cloudant/sync-android/teams","hooks_url":"https://api.github.com/repos/cloudant/sync-android/hooks","issue_events_url":"https://api.github.com/repos/cloudant/sync-android/issues/events{/number}","events_url":"https://api.github.com/repos/cloudant/sync-android/events","assignees_url":"https://api.github.com/repos/cloudant/sync-android/assignees{/user}","branches_url":"https://api.github.com/repos/cloudant/sync-android/branches{/branch}","tags_url":"https://api.github.com/repos/cloudant/sync-android/tags","blobs_url":"https://api.github.com/repos/cloudant/sync-android/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cloudant/sync-android/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cloudant/sync-android/git/refs{/sha}","trees_url":"https://api.github.com/repos/cloudant/sync-android/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cloudant/sync-android/statuses/{sha}","languages_url":"https://api.github.com/repos/cloudant/sync-android/languages","stargazers_url":"https://api.github.com/repos/cloudant/sync-android/stargazers","contributors_url":"https://api.github.com/repos/cloudant/sync-android/contributors","subscribers_url":"https://api.github.com/repos/cloudant/sync-android/subscribers","subscription_url":"https://api.github.com/repos/cloudant/sync-android/subscription","commits_url":"https://api.github.com/repos/cloudant/sync-android/commits{/sha}","git_commits_url":"https://api.github.com/repos/cloudant/sync-android/git/commits{/sha}","comments_url":"https://api.github.com/repos/cloudant/sync-android/comments{/number}","issue_comment_url":"https://api.github.com/repos/cloudant/sync-android/issues/comments/{number}","contents_url":"https://api.github.com/repos/cloudant/sync-android/contents/{+path}","compare_url":"https://api.github.com/repos/cloudant/sync-android/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cloudant/sync-android/merges","archive_url":"https://api.github.com/repos/cloudant/sync-android/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cloudant/sync-android/downloads","issues_url":"https://api.github.com/repos/cloudant/sync-android/issues{/number}","pulls_url":"https://api.github.com/repos/cloudant/sync-android/pulls{/number}","milestones_url":"https://api.github.com/repos/cloudant/sync-android/milestones{/number}","notifications_url":"https://api.github.com/repos/cloudant/sync-android/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cloudant/sync-android/labels{/name}","releases_url":"https://api.github.com/repos/cloudant/sync-android/releases{/id}","created_at":"2014-02-13T17:52:09Z","updated_at":"2015-02-12T17:46:56Z","pushed_at":"2015-02-13T15:04:28Z","git_url":"git://github.com/cloudant/sync-android.git","ssh_url":"git@github.com:cloudant/sync-android.git","clone_url":"https://github.com/cloudant/sync-android.git","svn_url":"https://github.com/cloudant/sync-android","homepage":"","size":14585,"stargazers_count":65,"watchers_count":65,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":20,"mirror_url":null,"open_issues_count":6,"forks":20,"open_issues":6,"watchers":65,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cloudant/sync-android/pulls/94"},"html":{"href":"https://github.com/cloudant/sync-android/pull/94"},"issue":{"href":"https://api.github.com/repos/cloudant/sync-android/issues/94"},"comments":{"href":"https://api.github.com/repos/cloudant/sync-android/issues/94/comments"},"review_comments":{"href":"https://api.github.com/repos/cloudant/sync-android/pulls/94/comments"},"review_comment":{"href":"https://api.github.com/repos/cloudant/sync-android/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/cloudant/sync-android/pulls/94/commits"},"statuses":{"href":"https://api.github.com/repos/cloudant/sync-android/statuses/d5b4f7825035187c3ef55b5962f38b66806f68d3"}}}}