Skip to content
Byron Ruth edited this page Sep 2, 2014 · 6 revisions

The origins.graph.core contains the core API of Origins that the higher-level types build upon.

Nodes

Module: origins.graph.core.nodes

Attributes
  • uuid - An auto-generated UUID for the node.
  • id - An ID that is persisted across revisions of this node. This may be supplied by the client, otherwise one will be auto-generated.
  • properties - A map of key/value pairs that represent the data of node.

Add

Adds a node to the graph.

Arguments
  • attrs - Attributes for the node.
  • labels - Set of labels to give the node. Labels act as a minimal schema to differentiate nodes in the graph such as Person or Book.

Set

Patches the attributes of the node with the passed attributes. The semantics of patching are as follows:

  • Attributes with a None value will be unset (if present) in the output
  • The nested properties map will be patched using the same semantics
  • All other attributes will be added or changed in the output

If the patched output is different from the prior state, a new revision is created, otherwise it exits.

Arguments
  • uuid (required) - The UUID of the node whose attributes are being set.
  • attrs - Attributes being set on the node.
  • force - If true, forces a change to be recorded.

Remove

Invalidates a node in the graph and invalidates all edges pointing to it.

Arguments
  • uuid (required) - The UUID of the node being removed.

Edges

Module: origins.graph.core.edges

Edges connect two nodes with an optional dependence.

Attributes
  • uuid - An auto-generated UUID for the edge.
  • id - An ID that is persisted across revisions of this edge. This may be supplied by the client, otherwise one will be auto-generated.
  • properties - A map of key/value pairs that represent the data of edge.
  • dependence - Declares the type of dependence between the two nodes: 0 declares no dependence, 1 is uni-directional (start to end), 2 is bi-directional. Default is 1.

Add

Defines an edge between two nodes in the graph. The physical representation of this a node (representing the edge) with origins:start and origins:end edges to the respective nodes. It is modeled this way so provenance can be linked to the edge as it changes.

In addition to this verbose representation, a native edge is formed between the nodes with a type specified by the type attribute. The edge exists as long as the node-based edge is valid. This provides a native representation of the nodes and edges in the graph for query purposes.

Arguments
  • start (required) - The UUID of a node which is the start of the edge.
  • end (required) - The UUID of a node which is the end of the edge.
  • attrs - Attributes for the edge.

Set

Patches the attributes of the edge with the passed attributes. The semantics of patching are as follows:

  • Attributes with a None value will be unset (if present) in the output
  • The nested properties map will be patched using the same semantics
  • All other attributes will be added or changed in the output

If the patched output is different from the prior state, a new revision is created, otherwise it exits.

Arguments
  • uuid (required) - The UUID of the edge whose attributes are being set.
  • attrs - Attributes being set on the edge.
  • force - If true, forces a change to be recorded.

Remove

Invalidates an edge in the graph.

Arguments
  • uuid (required) - The UUID of the edge being removed.

Example

1. Add Joe user

joe = nodes.add({'label': 'Joe'})

Output

{
    'data': {
        'properties': {}, 
        'label': 'Joe', 
        'time': 1409246079588, 
        'uuid': 'eae9ae0f-ea13-4af2-a1cb-cd5239e1a1f3', 
        'id': 'eae9ae0f-ea13-4af2-a1cb-cd5239e1a1f3'
    }, 
    'time': 1409246079604, 
    'prov': {
        'wasGeneratedBy': {
            'wgb': {
                'origins:uuid': '910b0b43-ce0e-45a7-b575-55ece7285019'
            }
        }, 
        'entity': {
            'entity': {
                'origins:uuid': 'eae9ae0f-ea13-4af2-a1cb-cd5239e1a1f3'
            }
        }
    }, 
    'perf': {
        'exec': 8.783249999396503, 
        'total': 16.736075980588794, 
        'prov': 7.655357010662556, 
        'prep': 0.2974689705297351
    }
}

Graph

graph1

2. Joe user uses graphs

Another node graphs is created to be linked to. The formed edge is "Joe uses graphs".

graphs = nodes.add({'label': 'graphs'})
joe_uses_graphs = edges.add(joe, graphs, {'label': 'uses'})

Output

Edges have their start and end nodes embedded in the output.

{
    'data': {
        'properties': {}, 
        'end': {
            'id': 'f8b415aa-ed7d-466d-a21b-e667f571aa60', 
            'properties': {}, 
            'time': 1409246079626, 
            'label': 'graphs', 
            'uuid': 'f8b415aa-ed7d-466d-a21b-e667f571aa60'
        }, 
        'start': {
            'id': 'eae9ae0f-ea13-4af2-a1cb-cd5239e1a1f3', 
            'properties': {}, 
            'time': 1409246079588, 
            'label': 'Joe', 
            'uuid': 'eae9ae0f-ea13-4af2-a1cb-cd5239e1a1f3'
        }, 
        'label': 'uses', 
        'time': 1409246079669, 
        'uuid': 'eec93213-9962-4a8c-b3f8-ed25c7d3689b', 
        'id': 'eec93213-9962-4a8c-b3f8-ed25c7d3689b'
    }, 
    'time': 1409246079688, 
    'prov': {
        'wasGeneratedBy': {
            'wgb': {
                'origins:uuid': '03c0f32e-e137-4ecd-82b4-9e1d43d45b8a'
            }
        }, 
        'entity': {
            'entity': {
                'origins:uuid': 'eec93213-9962-4a8c-b3f8-ed25c7d3689b'
            }
        }
    }, 
    'perf': {
        'exec': 8.26109800254926, 
        'total': 19.8202200117521, 
        'prov': 11.044259008485824, 
        'prep': 0.5148630007170141
    }
}

Graph

graph2

3. Uses, more like abuses

Actually, Joe abuses graphs, so we will update the edge.

joe_abuses_graphs = edges.set(joe_uses_graphs, {'type': 'abuses'})

Output

The notable parts to this is that a new edge is formed with the update type attribute between the same start and end nodes, joe and graphs. The previous edge is invalidated as implied by the wasInvalidatedBy declaration in the prov output.

{
    'data': {
        'properties': {}, 
        'end': {
            'id': 'f8b415aa-ed7d-466d-a21b-e667f571aa60', 
            'properties': {}, 
            'time': 1409246079626, 
            'label': 'graphs', 
            'uuid': 'f8b415aa-ed7d-466d-a21b-e667f571aa60'
        }, 
        'start': {
            'id': 'eae9ae0f-ea13-4af2-a1cb-cd5239e1a1f3', 
            'properties': {}, 
            'time': 1409246079588, 
            'label': 'Joe', 
            'uuid': 'eae9ae0f-ea13-4af2-a1cb-cd5239e1a1f3'
        }, 
        'label': 'abuses', 
        'time': 1409246079720, 
        'uuid': '9fc19b69-c01e-4810-adbf-97218f952957', 
        'id': 'eec93213-9962-4a8c-b3f8-ed25c7d3689b'
    }, 
    'time': 1409246079752, 
    'prov': {
        'wasInvalidatedBy': {
            'wib': {
                'origins:uuid': '238ebc76-adbc-43e1-94e5-2b6903ffa59f'
            }
        }, 
        'wasGeneratedBy': {
            'wgb': {
                'origins:uuid': '48629f0b-7f5e-4874-b7ae-894bf91d5697'
            }
        }, 
        'entity': {
            'entity': {
                'origins:uuid': '9fc19b69-c01e-4810-adbf-97218f952957'
            }, 
            'previous': {
                'origins:uuid': 'eec93213-9962-4a8c-b3f8-ed25c7d3689b'
            }
        }, 
        'wasDerivedFrom': {
            'wdf': {
                'origins:uuid': 'b954c4f3-5b23-484d-95b6-162f0502e6cd'
            }
        }
    }, 
    'perf': {
        'total': 42.75646596215665, 
        'prov': 9.88005695398897, 
        'add_edge': {
            'exec': 7.928737031761557, 
            'total': 21.936770994216204, 
            'prov': 13.81991000380367, 
            'prep': 0.18812395865097642
        }, 
        'get': 10.919241001829505, 
        'prep': 0.020397012121975422
    }
}

Graph

graph3

4. graphs → graph databases

Joe mistakenly generalized graphs for graph databases. We should update this term.

graph_dbs = nodes.set(graphs, {'label': 'graph databases'})

Output

{
    'data': {
        'properties': {}, 
        'label': 'graph databases', 
        'time': 1409246079781, 
        'uuid': 'aee22fd1-abe0-46ac-b358-a5be322bb3f1', 
        'id': 'f8b415aa-ed7d-466d-a21b-e667f571aa60'
    }, 
    'time': 1409246079811, 
    'prov': {
        'wasInvalidatedBy': {
            'wib': {
                'origins:uuid': '2c02a754-293f-41a4-acee-dea4187de376'
            }
        }, 
        'wasGeneratedBy': {
            'wgb': {
                'origins:uuid': '21b1afd7-5e3c-4edb-bba8-c0f726b086c7'
            }
        }, 
        'entity': {
            'entity': {
                'origins:uuid': 'aee22fd1-abe0-46ac-b358-a5be322bb3f1'
            }, 
            'previous': {
                'origins:uuid': 'f8b415aa-ed7d-466d-a21b-e667f571aa60'
            }
        }, 
        'wasDerivedFrom': {
            'wdf': {
                'origins:uuid': '22e3e6db-898b-4ce5-817f-b7f367dc5f14'
            }
        }
    }, 
    'perf': {
        'total': 57.56482103606686, 
        'prov': 6.9136389647610486, 
        'add': 17.835922015365213, 
        'get': 9.680492978077382, 
        'update_edges': 5.3289890056476, 
        'prep': 0.020351028069853783
    }
}

Graph

Joe still abuses graphs, why not graph databases? This is where the notion of a dependency graph comes in. The edge from Joe to graphs is directed therefore implicitly declaring a dependency on graphs by joe. Since Joe didn't confirm this change from his perspective, the edge was not updated.

graph4

5. Change Joe's name

The name "Joe" may be not be recognizable to some, so Joe decides to change his name to include his surname.

joe_smith = nodes.set(joe, {'label': 'Joe Smith'})

Output

{
    'data': {
        'properties': {}, 
        'label': 'Joe Smith', 
        'time': 1409246079836, 
        'uuid': 'a06a8617-57ac-4a3b-8ff4-63829d8f9577', 
        'id': 'eae9ae0f-ea13-4af2-a1cb-cd5239e1a1f3'
    }, 
    'time': 1409246079895, 
    'prov': {
        'wasInvalidatedBy': {
            'wib': {
                'origins:uuid': 'f97939e8-2fd7-4af0-a9fd-5de89ed0c403'
            }
        }, 
        'wasGeneratedBy': {
            'wgb': {
                'origins:uuid': 'f4560375-51e0-48af-b8c8-9c03cd74b7ad'
            }
        }, 
        'entity': {
            'entity': {
                'origins:uuid': 'a06a8617-57ac-4a3b-8ff4-63829d8f9577'
            }, 
            'previous': {
                'origins:uuid': 'eae9ae0f-ea13-4af2-a1cb-cd5239e1a1f3'
            }
        }, 
        'wasDerivedFrom': {
            'wdf': {
                'origins:uuid': 'c6e142d1-2f57-4b26-be6d-9b1373fc1e62'
            }
        }
    }, 
    'perf': {
        'total': 84.33187287300825, 
        'prov': 7.962606963701546, 
        'add': 16.77478099009022, 
        'get': 8.776464965194464, 
        'update_edges': 34.07454496482387, 
        'prep': 0.007753027603030205
    }
}

Graph

Look at that, "Joe Smith" still uses graphs! This demonstrates that changes to nodes having dependencies are always re-linked.

The prov:Generation nodes have been omitted for clarity.

graph5

Clone this wiki locally