Skip to content

JSON and GraphQL

7 / 11 · serving a view in the full document · PDF

A view can be loaded as JSON, whole or as a selection of its fields. A selection loads only what it names — only the selected columns, only the selected child queries — so a GraphQL request becomes one load of exactly the data it asks for. mabat-graphql generates the schema from the views, and turns each root field's selection set, with its arguments, into that load.

Four stages. A GraphQL request for tasks with a where filter on name and a limit of 20, selecting name, assignee name, and notes ordered by createdAt descending with a limit of 3. The selection set becomes a Selection with fields and arguments, fragments resolved and variables applied. build_selected plans only the selected columns and child queries, three queries not five, with recursion unrolled to the selection's depth. The JSON result shows a task with its assignee and three notes. Below, the SQL of the notes query: ROW_NUMBER() OVER (PARTITION BY task_id ORDER BY created_at DESC, id) as $row, keeping rows with $row up to 3. At the right: the schema is generated from the views; one load per root field; the same without GraphQL through Selection::parse and json; overrides apply.

JSON. load::<T>().json(conn) returns serde_json::Value objects: columns through their type's Serialize, json columns as the JSON they hold, collections as arrays, maps as objects, references as objects or null, and enums as objects whose __typename names the variant MPA-JSON-1. select(Selection) loads only the selected fields; Selection::parse reads GraphQL-like text MPA-JSON-3. A view selected without fields loads its columns and embedded values, not its relationships MPA-JSON-4. Overrides apply to selections MPA-JSON-6.

A generated schema. mabat_graphql::schema(&pool).list::<T>("tasks").by_key::<T>("task").finish() builds an async-graphql dynamic schema from the views and every view they reach MPA-GQL-1: objects for views and embedded structs, unions for enums with data, GraphQL enums for enums without, and scalars from the column types MPA-GQL-2. List fields take where, orderBy, limit and offset MPA-GQL-3. There are no mutations in 0.1 MPA-NOT-7.

Arguments at every level. Each root field is one load of its selection set MPA-GQL-4: no resolver per field, so no N+1. Nested arguments filter, order and page the elements of each parent inside the collection's one query — the filter follows the parent keys condition, order_by replaces the collection's order, and limit and offset apply per parent with ROW_NUMBER() OVER (PARTITION BY …) MPA-LOAD-9. Over an override, the arguments wrap it as a subquery and refer to columns by alias MPA-LOAD-10.