Add to a Graph
All changes to a graph are appended to a graph. As long as you have append privileges for a graph, you may add new facts to it, even if you do not currently host the graph.
As a GraphDelta!!!
The general syntax is:
receipt = list_of_actions | transact[g] | run
Entities can appear in the list as single items:
receipt = [
ET.Machine,
] | transact[g] | run
Atomic entities can be given with value assignment operations:
receipt = [
AET.String <= "TX-9000",
] | transact[g] | run
Individual relations can appear as a triple in the list:
receipt = [
(ET.Machine, RT.Model, "TX-9000"),
] | transact[g] | run
The above will create a relation of type RT.Model
that connects the source and
target to the first and third elements respectively of the triple. These are created automatically, such
that the above is equivalent to:
receipt = [
(Z["source"], RT.Model, Z["target"]),
ET.Machine["source"],
AET.String["target"] <= "TX-9000",
] | transact[g] | run
A Z[internal_id]
references a different RAE in the GraphDelta. RAEs that can
be referenced are ET
, AET
, RT
, QuantityInt
and QuantityFloat
. These
references will then appear in the receipt. For example, the previous receipt
should satisfy:
assert receipt["source"] | is_a[ET.Machine] | collect
assert receipt["target"] | is_a[AET.String] | collect
assert receipt["target"] | value | equals["TX-9000"] collect
A RAE from any graph can be referenced or merged using the GraphDelta:
g_machines = Graph()
g_employees = Graph()
r1 = [ET.Machine["machine"]] | transact[g_machines] | run
r2 = [ET.Employee["alex"]] | transact[g_employees] | run
assert type(r1["machine"]) == ZefRef
assert type(r2["alex"]) == ZefRef
receipt = [
(r1["machine"], RT.OperatedBy, r2["alex"])
] | transact[g_machines] | run
Composite relation syntax
It is common to create an entity with many fields simulataneously. This can be done via the long-winded way:
receipt = [
ET.Person["p"],
(Z["p"], RT.FirstName, "Alex"),
(Z["p"], RT.LastName, "Smith"),
(Z["p"], RT.DOB, now()),
(Z["p"], RT.WorksFor, "Actionable Items"),
] | transact[g] | run
or made more concise by using a length-2 tuple, where the second element is a list of (relation, value) pairs:
receipt = [
(ET.Person["p"], [
(RT.FirstName, "Alex"),
(RT.LastName, "Smith"),
(RT.DOB, now()),
(RT.WorksFor, "Actionable Items"),
])
] | transact[g] | run
In a different scenario, many relations of the same type are made to connect entities, which in long-winded format could be:
receipt = [
ET.Person["p"],
ET.Pet["rufus"],
ET.Pet["spot"],
ET.Pet["mittens"],
(Z["p"], RT.OwnerOf, Z["rufus"]),
(Z["p"], RT.OwnerOf, Z["spot"]),
(Z["p"], RT.OwnerOf, Z["mittens"]),
] transact[g] | run
This can instead be written as as length-3 tuple, where the 3rd element is a list:
receipt = [
(ET.Person["p"], RT.OwnerOf, [
ET.Pet["rufus"],
ET.Pet["spot"],
ET.Pet["mittens"],
]),
] | transact[g] | run
Separation of actions from GraphDelta
You can build the list of changes separately to creating the GraphDelta. This is useful when building a large GraphDelta in multiple functions:
def create_machine(name, model, is_large=False):
actions = [
ET.Character[name],
(Z[name], [(RT.Name, name),
(RT.Modle, model)])
]
if is_large:
actions += [(Z[name], RT.Large, True)]
return actions
actions = []
actions += create_machine("Maker", "TX-9000", True)
actions += create_machine("Generator", "TX-8000")
actions += create_machine("Creator", "CZ-9999")
receipt = actions | transact[g] | run
Shorthand syntax
When a single item is being created, an even shorter syntax is permitted, allowing you to avoid creating a GraphDelta and without needing to unpack the receipt by hand. For example:
z = ET.Machine | g | run
is equivalent to:
receipt = [ET.Machine["z"]] | transact[g] | run
z = receipt["z"]
A more complicated example is shown below:
person,rel,[pet1,pet2,pet3] = (ET.Person, RT.OwnerOf, [ET.Pet, ET.Pet, ET.Pet]) | g | run
is equivalent to:
receipt =[
(ET.Person["person"], RT.OwnerOf, [
ET.Pet["pet1"],
ET.Pet["pet2"],
ET.Pet["pet3"],
])
] | transact[g] | run
person = receipt["person"]
rel = None
pet1 = receipt["pet1"]
pet2 = receipt["pet2"]
pet3 = receipt["pet3"]
Note that rel
is None
. This is to allow the same "unpacking" structure as
the input, but substituting None
where the output maps to multiple values.
This is because the above creates three relations, so it is nonsensical to
return any particular relation in the output.