Standing Queries: Turning Event-Driven Data into Data-Driven Events
Quine's super power is the ability to store and execute business logic within the graph. That query can then operate directly on data as it streams in. We call this type of query a standing query.
A standing query incrementally matches some graph structure while new data is ingested into the graph. Quine’s special design makes this process extremely fast and efficient. When a full pattern match is found, a standing query takes action.
A standing query is defined in two parts: a pattern and an output. The pattern defines what we want to match, expressed in Cypher using the form `MATCH … WHERE … RETURN …`. The output defines the action(s) to take for each result produced by the `RETURN` in the pattern query.
The result of a standing query output is passed to a series of actions which process the output. This output can be logged, passed to other systems (via Kafka, Kinesis, HTTP POST, and more), or can even be used to perform additional actions like running new queries or even rewriting parts of the graph. Whatever logic your application needs.
How nodes match patterns
Each node in Quine is backed by an actor, which makes each graph node act like its own little CPU. Actors function as lightweight, single-threaded logical computation units that maintain state and communicate with each other by passing messages.
The actor model enables you to execute a standing query that is stored in the graph and remembered automatically. When you issue a `DistinctId` standing query, the query is broken into individual steps that can be tested one at a time on individual nodes. Quine stores the result of each successive decomposition of a query (smaller and smaller queries) internally on the node issuing that portion of the query. The previous node's query is essentially a subscription to the next nodes status as either matching the query or not.
Any changes in the next node’s pattern match state result in a notification to the querying node. In this way, a complex query is relayed through the graph, where each node subscribes to whether or not the next node fulfills its part of the query. When a complete match is made, or unmade, the chain is notified with results and an output action is triggered.