diff --git a/docs/api/reading.md b/docs/api/reading.md index 5cd7a39c9..ea2a4460a 100644 --- a/docs/api/reading.md +++ b/docs/api/reading.md @@ -20,7 +20,7 @@ GET /people ``` There are no `deeply/nested/routes`. Each route provides `OPTIONS`, -`GET`, `POST`, `PUT`, `PATCH`, and `DELETE` verbs depending entirely +`GET`, `POST`, `PATCH`, and `DELETE` verbs depending entirely on database permissions.
@@ -28,9 +28,9 @@ on database permissions.

Why not provide nested routes? Many APIs allow nesting to retrieve related information, such as /films/1/director. - We offer a more flexible mechanism instead to embed related - information, including many-to-many relationships. This is covered - in the section about Embedding.

+ We offer a more flexible mechanism (inspired by GraphQL) to embed + related information. It can handle one-to-many and many-to-many + relationships. This is covered in the section about Embedding.

### Stored Procedures @@ -47,7 +47,7 @@ POST /rpc/proc_name PostgREST supports calling procedures with [named arguments](http://www.postgresql.org/docs/9.4/static/sql-syntax-calling-funcs.html#SQL-SYNTAX-CALLING-FUNCS-NAMED). -To do so include a JSON object in the request payload and each +Include a JSON object in the request payload and each key/value of the object will become an argument.
@@ -212,7 +212,7 @@ count total using a ```Prefer``` header as: Prefer: count=none ``` -So the PostgREST response will be something like: +With count suppressed the PostgREST response will look like: ``` Range-Unit: items @@ -227,7 +227,7 @@ API you can have it embed the client within each project response. For example, ```HTTP -GET /projects?id=eq.1&select=id, name, clients(*) +GET /projects?id=eq.1&select=id, name, clients{*} ``` Notice this is the same `select` keyword which is used to choose @@ -240,7 +240,15 @@ The embedding works for 1-N, N-1, and N-N relationships. That means you could also ask for a client and all their projects: ```HTTP -GET /clients?id=eq.42&select=id, name, projects(*) +GET /clients?id=eq.42&select=id, name, projects{*} +``` + +In the examples above we asked for all columns in the embedded resource +but the the select query is recursive. You could for instance specify + + +```HTTP +GET /foo?select=x, y, bar{z, w, baz{*}} ``` ### Response Format @@ -265,7 +273,8 @@ For consistency's sake all these endpoints return a JSON array, `/stories`, `/stories?genre=eq.mystery`, `/stories?id=eq.1`. They are all filtering a bigger array. However you might want the last one to return a single JSON object, not an array with one -element. There is currently an open issue to enable this. +element. To request a singular response send the header +`Prefer: plurality=singular`. ### Data Schema diff --git a/docs/api/writing.md b/docs/api/writing.md index bfd847050..0c9473694 100644 --- a/docs/api/writing.md +++ b/docs/api/writing.md @@ -26,9 +26,13 @@ the server side. * ❌ Cannot be cached or prefetched * ❌ Not idempotent -While regular insertion uses JSON to encode the value, bulk insertion -uses CSV. Simply post to a table route with `Content-Type: text/csv` -and include the names of the columns as the first row. For instance +You can POST a JSON array or CSV to insert multiple rows in a single +HTTP request. Note that using CSV requires less parsing on the server +and is **much faster**. + +Example of CSV bulk insert. Simply post to a table route with +`Content-Type: text/csv` and include the names of the columns as +the first row. For instance ```HTTP POST /people @@ -41,42 +45,31 @@ An empty field (`,,`) is coerced to an empty string and the reserved word `NULL` is mapped to the SQL null value. Note that there should be no spaces between the column names and commas. -The server sends a multipart response for bulk insertions. Each part -contains a Location header with URL of each created resource. +Example of JSON bulk insert. Send an array: ```HTTP -Content-Type: application/json -Location: /festival?name=eq.Venice%20Film%20Festival - - ---postgrest_boundary -Content-Type: application/json -Location: /festival?name=eq.Cannes%20Film%20Festival +POST /people +[ + { "name": "J Doe", "age": 62, "height": 70 }, + { "name": "Janus", "age": 10, "height": 55 } +] ``` -### Upsertion - -* ❌ Cannot be cached or prefetched -* ✅ Idempotent - -To insert or update a single row use the `PUT` verb on a properly -filtered table url: - -```HTTP -PUT /table_name?primary_key=eq.foo -{ "col1": "value1", "col2": "value2" } -``` - -The request must satisfy two things. First all columns must be -specified (because a default value might be a changing value which -would violate idempotence). Second the URL must match the URL you -would use to get the value of the resource. This means that all -primary key columns must be included in the filter (there are more -than one when the primary key is compound). - If you would like to get the full object back in the response to your request, include the header `Prefer: return=representation`. -It will of match exactly the object you sent though. +Chances are you only want certain information back, though, like +created ids. You can pass a `select` parameter to affect the shape +of the response (further documented in the [reading](/api/reading/) +page). For instance + +```HTTP +POST /people?select=id +[...] +``` +returns something like +```json +[ { "id": 1 }, { "id": 2 } ] +``` ### Bulk Updates @@ -110,7 +103,7 @@ Simply use the `DELETE` verb. All recors that match your filter will be removed. For instance deleting inactive users: ```HTTP -DELETE /user?active=eq.false +DELETE /user?active=is.false ``` ### Protecting Dangerous Actions @@ -118,7 +111,6 @@ DELETE /user?active=eq.false Notice that it is very easy to delete or update many records at once. In fact forgetting a filter will affect an entire table! -

Invitation to Contribute