reify.time is a Cypher procedure included with Quine. Its purpose is to facilitate the instantiation (reification) of a graph of nodes representing time.
reify.time is provided with a timestamp (current wall clock time as the default), and it returns the nodes that represent the passed-in time.
reify.time does this by determining which nodes must exist, and either reading them from the graph or creating them as necessary. Additionally,
reify.time relates the nodes it makes to each other and other nodes previously created by this function.
reify.time does not do anything Cypher can’t do. In this sense, reify.time is unnecessary. So why does it need to exist?
- To reduce the boilerplate necessary to ingest time-series data usefully
- To create a modification point where in the future, changes can be made to how time-series data is modeled in the graph and have this change applied to all usages
- To organize data to be more useful in the Quine web UI
- To settle on a unified convention for representing time so that users don’t have to spend brainpower to create something bespoke (and inconsistent among different users)
- To create the persistent graph structure upon which time-series aggregate values can be stored or related
reify.time builds a hierarchy of related nodes for a single datetime value. Each node in this hierarchy represents a different period where the input datetime value belongs.
- Each node in the hierarchy is defined by a start datetime value and a period.
- Each node in the hierarchy is related to its parent node (except the largest).
- Each node in the hierarchy is also related to the next node in time (and the same period).
- ZonedDateTime (optional; defaults to now)
- Periods (optional list of strings; defaults to all periods)
reify.time returns each of the time nodes reified by this function directly related to the input time. Note that this function creates time nodes that do not exist and reuses time nodes that already exist.
reify.time with default arguments, which will be to reify time nodes at all periods for the current system clock time:
CALL reify.time() YIELD node AS n RETURN n
Run with a time parsed from a string:
CALL reify.time(datetime("2022-04-11T11:06:12-0700"), ["month", "day"]) YIELD node AS n RETURN n
Use within a Recipe:
version: 1 title: Ingest Wikipedia page create stream contributor: https://github.com/landon9720 summary: Consume events about new Wikipedia pages to build a timeseries reified graph description: |- Wikipedia page creation events are instantiated in the graph with relationships to a refied time model. Additionally, page creation event comments are echoed to standard output. Data source documentation: https://stream.wikimedia.org/?doc#/streams/get_v2_stream_page_create ingestStreams: - type: ServerSentEventsIngest url: https://stream.wikimedia.org/v2/stream/page-create format: type: CypherJson query: |- MATCH (revNode) WHERE id(revNode) = idFrom("revision", $that.rev_id) MATCH (dbNode) WHERE id(dbNode) = idFrom("db", $that.database) MATCH (userNode) WHERE id(userNode) = idFrom("id", $that.performer.user_id) SET revNode = $that, revNode.type = "rev" SET dbNode.database = $that.database, dbNode.type = "db" SET userNode = $that.performer, userNode.type = "user" WITH *, datetime($that.rev_timestamp) AS d CALL create.setLabels(revNode, ["rev:" + $that.page_title]) CALL create.setLabels(dbNode, ["db:" + $that.database]) CALL create.setLabels(userNode, ["user:" + $that.performer.user_text]) CALL reify.time(d, ["year", "month", "day", "hour", "minute"]) YIELD node AS timeNode CALL incrementCounter(timeNode, "count") CREATE (revNode)-[:at]->(timeNode) CREATE (revNode)-[:db]->(dbNode) CREATE (revNode)-[:by]->(userNode) standingQueries: - pattern: type: Cypher query: |- MATCH (n) WHERE EXISTS(n.comment) RETURN DISTINCT id(n) AS id outputs: output-1: type: CypherQuery query: |- MATCH (n) WHERE id(n) = $that.data.id RETURN n.comment AS line andThen: type: PrintToStandardOut nodeAppearances:  quickQueries:  sampleQueries: - name: time nodes query: > MATCH (n) WHERE EXISTS(n.period) RETURN n - name: revision nodes query: > MATCH (n) WHERE n.type = "rev" RETURN n - name: database nodes query: > MATCH (n) WHERE n.type = "db" RETURN n - name: user nodes query: > MATCH (n) WHERE n.type = "user" RETURN n
The above Recipe consumes an event stream that describes new Wikipedia pages. Each event includes a timestamp, which is passed to