| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Database.Bolty.ResultSet
Description
Multi-pass decoding of denormalized query results.
When a Cypher query uses OPTIONAL MATCH, the result set is denormalized:
parent fields are repeated for each matched child row. ResultSet bundles
field names with records so you can decode the same rows with different
decoders in multiple passes.
Preferred alternative: Use Cypher COLLECT() or pattern comprehensions
to aggregate children server-side, avoiding denormalization entirely:
MATCH (p:Parent) OPTIONAL MATCH (p)-[:HAS]->(c:Child) RETURN p, COLLECT(c) AS children
When that isn't practical (e.g. multiple independent optional paths),
use groupByField as an escape hatch:
rs queryResult conn "MATCH (p:Parent) OPTIONAL MATCH (p)-[:HAS]-(c:Child) RETURN p.id AS pid, c" groups <- either throwIO pure $ groupByField (field "pid" (nullable int64)) rs -- groups :: Vector (Int64, ResultSet) -- Each sub-ResultSet contains the rows for that parent.
Synopsis
- data ResultSet = ResultSet {}
- decodeResultSet :: RowDecoder a -> ResultSet -> Either DecodeError (Vector a)
- decodeHead :: RowDecoder a -> ResultSet -> Either DecodeError a
- groupByField :: Eq k => RowDecoder (Maybe k) -> ResultSet -> Either DecodeError (Vector (k, ResultSet))
Documentation
A query result: field (column) names paired with the result records.
Supports multi-pass decoding — decode the same rows with different
RowDecoders without re-running the query.
decodeResultSet :: RowDecoder a -> ResultSet -> Either DecodeError (Vector a) Source #
Decode every record in a ResultSet using a RowDecoder.
Fails on the first DecodeError.
decodeHead :: RowDecoder a -> ResultSet -> Either DecodeError a Source #
Decode the first record of a ResultSet, or fail with EmptyResultSet.
groupByField :: Eq k => RowDecoder (Maybe k) -> ResultSet -> Either DecodeError (Vector (k, ResultSet)) Source #
Group consecutive records by a decoded key field.
Records whose key decodes to Nothing (e.g. NULL from an OPTIONAL MATCH
with no match) are skipped. Grouping is consecutive, not global: if the same
key appears in non-adjacent runs, they become separate groups.
Each sub-ResultSet shares the parent's field names.
Prefer Cypher COLLECT() when possible — this function is an escape
hatch for queries where server-side aggregation is impractical.