Identifying Existing Entities

While GFEAR scripts are independent script files, they are not intended to be run in isolation. The concept of these script files is that complex codification can be broken up into small, managable, and readable blocks responsible for codifying a single artifact.

For this reason, it is sometimes important to be able to idetnify an existing entity in a graph. This may be so that an entity can be linked to a larger graph, or ensure that any additional properties that have been created in the current gfear script are merged or updated on the materialized entity.

To achieve this linking, GFEAR has the identified by clause that can be added to the end of a create entity or result statement.

A basic identified by clause includes 2 pieces of information:

  • Whether the predicate is required or optional
  • What the predicate Uri is

An example is given below:

create entity accountIssuer as uco-observable:AccountIssuer with {
    create property uco-observable:accountIssuerName as xsd:String with MID;
} identified by required uco-observable:accountIssuerName;

The above code will construct the accountIssuer entity when executing the script for the current instance of the data, however when attempting to merge the ephemeral graph for the current into the final materialized graph, the language will look for an entity that has the property uco-observable:accountIssuerName matching the current value of MID. If an entity is found that has this property, that existing entity will be used. If it’s not found, a new entity with the appropriate properties will be created in the materialized graph.

Nesting identified by Clauses

The identified by clause can be added to any create entity statement, even one within another create entity statement. In this case, the language will start at the deepest entity and attempt to find an existing entity in the materialized graph before moving up.

Identifying Entities by Relationships to Other Entities

It is possible to use an entity in an identified by clause, as shown below:

...
result account as uco-observable:WindowsAccount with {
    create entity accountFacet as uco-observable:AccountFacet with {
        create property uco-observable:accountIdentifier as xsd:String with SID;
    } identified by required uco-observable:accountIdentifier;

    create property uco-core:hasFacet with entity accountFacet;
}identified by required entity uco-core:hasFacet accountFacet;

In the above example, the account result has an entity created (accountFacet) which is identified by a required uco-observable:accountIdentifier. The account result is identified by having a relationship to an entity via the uco-core:hasFacet predicate with the object of the triple being the accountFacet that either already exists (and identified with the accountIdentifier) or created.