bolty-0.1.0.2: Haskell driver for Neo4j (BOLT protocol 4.4-5.4)
Safe HaskellNone
LanguageGHC2021

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

Documentation

data ResultSet Source #

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.

Constructors

ResultSet 

Fields

Instances

Instances details
Show ResultSet Source # 
Instance details

Defined in Database.Bolty.ResultSet

Eq ResultSet Source # 
Instance details

Defined in Database.Bolty.ResultSet

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.