Gram: a data graph format
Tags: gram, graph, neo4j, json
Published: 2021-01-19 12:41:21

Gram is a textual format for data. We have `CSV` for tables, `JSON` for documents, and `gram` for data graphs.

Use `gram` when `[a,b,c]` becomes `(a)-->(b)<--(c)`.

### Why another data format?

> Anything worth talking about is worth inventing a language for.
>
> -- probably not [L. Wittgenstein](https://en.wikipedia.org/wiki/Ludwig_Wittgenstein)

Graphs are a powerful and increasingly popular way to think about and work with data. ISO has established a project to formalize an 
[international standard Graph Query Language](https://en.wikipedia.org/wiki/GQL_Graph_Query_Language). ISO GQL will become the "language of graphs".

But graph technology includes databases, analytics libraries, visualization software, and a host of other tools.

How do we use these things together? We need a common format to connect tools when performing the usual operations:

- import/export data file
- send/receive network transmissions
- copy & paste across applications

We all expect these actions to just work. It's frustrating when any of them are not possible. Tools with limited interoperability feel locked-in and isolated. That's not the graph way. 

`Gram` can make it possible for data graphs to be used in normal everyday work.

[
![Another standard](https://imgs.xkcd.com/comics/standards.png)
](https://xkcd.com/927/)

## Data graphs as information architecture

While there are existing graph formats, `gram` is designed to complement the Property Graph Model defined by ISO GQL.

`Gram` is interested in information architectures. Data graphs are the means, not the goal. Rather than talking about graphs, `gram` speaks in graph to talk about other things.

Some motivating examples include:

- [Association class](https://developer.ibm.com/articles/the-class-diagram/#association-class): How do we describe the relationship between two things? Not just that they are connected, but _how_ they are connected.
- [Decorator pattern](https://en.wikipedia.org/wiki/Decorator_pattern): Can multiple applications share data while reserving space for their own use?
- [U.S. Route 66](https://en.wikipedia.org/wiki/U.S._Route_66): How can we represent path membership and also information about the path itself?
- [Bill of materials](https://en.wikipedia.org/wiki/Bill_of_materials) with [finished goods](https://en.wikipedia.org/wiki/Finished_goods): How do we describe both the plan to build stuff and the stuff that has been built?

`Gram` attempts to address these scenarios while being friendly to read and write by adopting a path-based representation. Paths all the way down, or all the way up with path composition.

### Friendly to read and write

Gram is intuitively simple, inspired by Cypher<sup>[1](#cypher-lang)</sup> path expressions.

Information starts with a familiar looking data record of nested properties:

```js
({
    name:"Andreas Kollegger", 
    address: {
        city:"Malmö", country:"Sweden"
    }
})
```

The extra set of parenthesis wrapping the record provides space for an identifier and a set of labels:

```js
(a:Person:Author { name:"Andreas Kollegger", address: { city:"Malmö", country:"Sweden" }})
```

Data records can be composed into information structures using relationships:

```js
(a)-[:Wrote]->(b:Blog {title:"Gram: a data graph format"})
```

We can complete this scene with another related record:

```js
(b:Blog)<-[:Read]-(c:Person)
```

Putting it all together we could write:

```js
(a:Person)-[:Wrote]->(b:Blog)<-[:Read]-(c:Person)
(a:Author { name:"Andreas Kollegger", address: { city:"Malmö", country:"Sweden" }})
(b {title:"Gram: a data graph format"})
(c {when:date`2021-01-21`})
```

Nice. The first path is readable as a sentence that "a `Person` `Wrote` a `Blog` that was `Read` by another `Person`." Notice in this rewrite we accumulated information -- all the `a`'s are the same record. 

Like writing prose, you don't have to say everything at once. Paths appear in an ordered stream that merges forward into a final result. In fact, because any path or sequence of paths forms a valid result you can time-travel or page through a graph.

# Use `gram` for data graphs

`Gram` is:

- friendly to read and write
- composable, sliceable, pageable and streamable
- vendor-neutral
- a work-in-progress :)

There is a reference implementation called [gram-js](https://gram-data.github.io/gram-js/) which is used along with d3.js in a [collection of ObservableHQ notebooks](https://observablehq.com/collection/@akollegger/gram-for-graphs). Next up is integration with other Javascript libraries and conversion to/from other formats. 

Check it out and let me know what you think!

---
Footnotes:

<sup><a name="cypher-lang">[1]</a> [Cypher Language] (https://neo4j.com/developer/cypher/) inspired both ISO GQL and `gram` with the use of "ASCII art" to draw graph elements. `cypher` is a graph database query language.
</sup>
<sup><a name="gram-collection">[2]</a> [Gram of Graphs](https://observablehq.com/collection/@akollegger/gram-for-graphs) - an Observable HQ notebook collection which illustrates how to use `gram` and provides handy utilities for visualizing graphs.
</sup>
<sup><a name="gram-js">[3]</a> [gram-js](https://gram-data.github.io/gram-js/) - the `gram` reference implementation, written in TypeScript
</sup>