From 14de9f1dfd1d3dc974f96d2086727ab1893ccadd Mon Sep 17 00:00:00 2001 From: Steve Chavez Date: Thu, 22 Jun 2023 09:14:23 -0500 Subject: [PATCH] references: add computed fields page (#650) --- docs/references/api.rst | 7 +- docs/references/api/computed_fields.rst | 86 ++++++++++++++++++++++++ docs/references/api/tables_views.rst | 89 +++++++++---------------- 3 files changed, 122 insertions(+), 60 deletions(-) create mode 100644 docs/references/api/computed_fields.rst diff --git a/docs/references/api.rst b/docs/references/api.rst index 2a6479781..c156ffa67 100644 --- a/docs/references/api.rst +++ b/docs/references/api.rst @@ -12,9 +12,10 @@ PostgREST exposes three database objects of a schema as resources: tables, views api/tables_views.rst api/stored_procedures.rst api/schemas.rst + api/computed_fields.rst api/resource_embedding.rst - api/openapi.rst api/resource_representation.rst + api/openapi.rst api/* .. raw:: html @@ -34,7 +35,7 @@ PostgREST exposes three database objects of a schema as resources: tables, views '#casting-columns': 'api/tables_views.html#casting-columns', '#json-columns': 'api/tables_views.html#json-columns', '#composite-array-columns': 'api/tables_views.html#composite-array-columns', - '#computed-virtual-columns': 'api/tables_views.html#computed-virtual-columns', + '#computed-virtual-columns': 'api/computed_fields.html#computed-fields', '#ordering': 'api/tables_views.html#ordering', '#limits-and-pagination': 'api/tables_views.html#limits-and-pagination', '#exact-count': 'api/tables_views.html#exact-count', @@ -115,4 +116,4 @@ PostgREST exposes three database objects of a schema as resources: tables, views if (willRedirectTo) { window.location.href = willRedirectTo; } - \ No newline at end of file + diff --git a/docs/references/api/computed_fields.rst b/docs/references/api/computed_fields.rst new file mode 100644 index 000000000..194a48f3c --- /dev/null +++ b/docs/references/api/computed_fields.rst @@ -0,0 +1,86 @@ +.. _computed_cols: + +Computed Fields +############### + +Computed fields are virtual columns that are not stored in a table. PostgreSQL makes it possible to implement them using functions on table types. + +.. code-block:: postgres + + CREATE TABLE people ( + first_name text + , last_name text + , job text + ); + + -- a computed field that combines data from two columns + CREATE FUNCTION full_name(people) + RETURNS text AS $$ + SELECT $1.first_name || ' ' || $1.last_name; + $$ LANGUAGE SQL; + +:ref:`h_filter` can be applied to computed fields. For example, we can do a :ref:`fts` on :code:`full_name`: + +.. code-block:: postgres + + -- (optional) you can add an index on the computed field to speed up the query + CREATE INDEX people_full_name_idx ON people + USING GIN (to_tsvector('english', full_name(people))); + +.. tabs:: + + .. code-tab:: http + + GET /people?full_name=fts.Beckett HTTP/1.1 + + .. code-tab:: bash Curl + + curl "http://localhost:3000/people?full_name=fts.Beckett" + +.. code-block:: json + + [ + {"first_name": "Samuel", "last_name": "Beckett", "job": "novelist"} + ] + + +Computed fields won't appear on the response by default but you can use :ref:`v_filter` to include them: + +.. tabs:: + + .. code-tab:: http + + GET /people?select=full_name,job HTTP/1.1 + + .. code-tab:: bash Curl + + curl "http://localhost:3000/people?select=full_name,job" + +.. code-block:: json + + [ + {"full_name": "Samuel Beckett", "job": "novelist"} + ] + + +:ref:`ordering` on computed fields is also possible: + +.. tabs:: + + .. code-tab:: http + + GET /people?order=full_name.desc HTTP/1.1 + + .. code-tab:: bash Curl + + curl "http://localhost:3000/people?order=full_name.desc" + +.. important:: + + Computed columns must be created in the :ref:`exposed schema ` or in a schema in the :ref:`extra search path ` to be used in this way. When placing the computed column in the :ref:`exposed schema ` you can use an **unnamed** parameter, as in the example above, to prevent it from being exposed as an :ref:`RPC ` under ``/rpc``. + +.. note:: + + - PostgreSQL 12 introduced `generated columns `_, which can also compute a value based on other columns. However they're stored, not virtual. + - "computed fields" are documented on https://www.postgresql.org/docs/current/rowtypes.html#ROWTYPES-USAGE (search for "computed fields") + - On previous PostgREST versions this feature was documented with the name of "computed columns". diff --git a/docs/references/api/tables_views.rst b/docs/references/api/tables_views.rst index 989c1f8d8..fa796c813 100644 --- a/docs/references/api/tables_views.rst +++ b/docs/references/api/tables_views.rst @@ -31,8 +31,8 @@ There are no deeply/nested/routes. Each route provides OPTIONS, GET, HEAD, POST, .. _h_filter: -Horizontal Filtering (Rows) ---------------------------- +Horizontal Filtering +-------------------- You can filter result rows by adding conditions on columns. For instance, to return people aged under 13 years old: @@ -249,10 +249,10 @@ Using `websearch_to_tsquery` requires PostgreSQL of version at least 11.0 and wi .. _v_filter: -Vertical Filtering (Columns) ----------------------------- +Vertical Filtering +------------------ -When certain columns are wide (such as those holding binary data), it is more efficient for the server to withhold them in a response. The client can specify which columns are required using the sql:`select` parameter. +When certain columns are wide (such as those holding binary data), it is more efficient for the server to withhold them in a response. The client can specify which columns are required using the :code:`select` parameter. .. tabs:: @@ -455,57 +455,6 @@ The arrow operators(``->``, ``->>``) can also be used for accessing composite fi CREATE INDEX ON mytable ((to_jsonb(data) -> 'identification' ->> 'registration_number')); -.. _computed_cols: - -Computed / Virtual Columns --------------------------- - -Filters may be applied to computed columns(**a.k.a. virtual columns**) as well as actual table/view columns, even though the computed columns will not appear in the output. For example, to search first and last names at once we can create a computed column that will not appear in the output but can be used in a filter: - -.. code-block:: postgres - - CREATE TABLE people ( - fname text, - lname text - ); - - CREATE FUNCTION full_name(people) RETURNS text AS $$ - SELECT $1.fname || ' ' || $1.lname; - $$ LANGUAGE SQL; - - -- (optional) add an index to speed up anticipated query - CREATE INDEX people_full_name_idx ON people - USING GIN (to_tsvector('english', full_name(people))); - -A full-text search on the computed column: - -.. tabs:: - - .. code-tab:: http - - GET /people?full_name=fts.Beckett HTTP/1.1 - - .. code-tab:: bash Curl - - curl "http://localhost:3000/people?full_name=fts.Beckett" - -As mentioned, computed columns do not appear in the output by default. However you can include them by listing them in the vertical filtering :code:`select` parameter: - -.. tabs:: - - .. code-tab:: http - - GET /people?select=*,full_name HTTP/1.1 - - .. code-tab:: bash Curl - - curl "http://localhost:3000/people?select=*,full_name" - -.. important:: - - Computed columns must be created in the :ref:`exposed schema ` or in a schema in the :ref:`extra search path ` to be used in this way. When placing the computed column in the :ref:`exposed schema ` you can use an **unnamed** argument, as in the example above, to prevent it from being exposed as an :ref:`RPC ` under ``/rpc``. - - .. _ordering: Ordering @@ -557,7 +506,17 @@ If you care where nulls are sorted, add ``nullsfirst`` or ``nullslast``: curl "http://localhost:3000/people?order=age.desc.nullslast" -You can also use :ref:`computed_cols` to order the results, even though the computed columns will not appear in the output. You can sort by nested fields of :ref:`json_columns` with the JSON operators. +You can also sort on fields of :ref:`composite_array_columns` or :ref:`json_columns`. + +.. tabs:: + + .. code-tab:: http + + GET /countries?order=location->>lat HTTP/1.1 + + .. code-tab:: bash Curl + + curl "http://localhost:3000/countries?order=location->>lat" .. _limits: @@ -1142,3 +1101,19 @@ Using ``offset`` to target a different subset of rows is also possible. There is no native ``UPDATE...LIMIT`` or ``DELETE...LIMIT`` support in PostgreSQL; the generated query simulates that behavior and is based on `this Crunchy Data blog post `_. +.. raw:: html + +