Skip to content

Concept rule definition and usage for event types #536

Open

Description

@suibianha

Hi:

Just would like to raise a question here regarding the usage of concept rules and relevant rule/constraint definition for event types in SPG schema and associated concept rule file, thanks.

I have a SPG schema with the following concept types and associated event types defined:

EntityB(EntityB): EntityType
properties:
....

EntityA(EntityA): EntityType
properties:
....
relations:
hasB: EntityB

TaxOfEntityBEvent(TaxOfEntityBEvent): ConceptType
hypernymPredicate: isA

EntityBEvent(EntityBEvent): EventType
properties:
subject(subject): EntityB
eventName(eventName): Text
IND#belongTo(belongTo): TaxOfEntityBEvent

TaxOfEntityAEvent(TaxOfEntityAEvent): ConceptType
hypernymPredicate: isA
relations:
CAU#leadTo(leadTo): TaxOfEntityBEvent

EntityAEvent(EntityAEvent): EventType
properties:
subject(subject): EntityA
eventName(eventName): Text
IND#belongTo(belongTo): TaxOfEntityAEvent
CAU#leadTo(leadTo): EntityBEvent

And in the associated schema/concept.rule file, I have the following definitions:

TaxOfEntityAEvent/A_down:TaxOfEntityBEvent/B_down
rule: [[
Define (s:TaxOfEntityAEvent/A_down)-[p:leadTo]->(o:TaxOfEntityBEvent/B_down) {
Structure {
(s)-[:subject]->(n1:EntityA)-[:hasB]->(n2:EntityB)<-[:subject]-(o)
}
Constraint {}
Action {
downEvent = createNodeInstance(
type=EntityBEvent,
value={
subject=tp.id
}
)
createEdgeInstance(
src=s,
dst=downEvent,
type=leadTo,
value={}
)
}
}
]]

And in the builder directory I have the associated instance data for EntityA, EntityB, TaxOfEntityAEvent, TaxOfEntityBEvent, and EntityAEvent. I left instance data for EntityBEvent as empty, as I'm expecting the concept rule for 'leadTo' above would automatically create a graph node as 'EntityBEvent' and the edge linking it to graph node 'EntityAEvent', with the values set as configured in the Action field.

In reality, after importing the instance data into Graph DB using the indexer python script, the ConceptType graph nodes TaxOfEntityAEvent, TaxOfEntityBEvent, the EntityType nodes EntityA, EntityB, and the EventType EntityAEvent have been successfully created in the graph, but there is no graph node 'EntityBEvent' created, and no edge linked to graph node 'EntityAEvent' as expected. Querying the 'leadTo' relation with DSL also returns empty results.

I was wondering if there is something I did wrong during the definition, and was curious about how exactly the rules and constraints (not just in concept.rule, but also rules/constraints defined directly in the schema) work in general, are they taking effect on builder level or on query level? i.e., the rules / constraints would be validated during the process of indexing data to graph DB, or only on querying the graph data after that?

Any feedback would be appreciated, thanks.

Activity

  1. suibianha commented on Apr 11, 2025

    @suibianha
    Author

    Just found out it might be related to #240, where usage of leadTo needs to be explicitly specified.

    However the solution for that issue and the relevant user manual update seems to be compatible with SPG version 0.5, and since version 0.6 the builder workflow seems to be updated.

    Is it possible to provide a solution equivalent to the one for issue #240, which is compatible with the existing indexer python script on builder? Thanks.

  2. JJUN99 commented on Aug 11, 2026

    @JJUN99

    We hit almost exactly the same symptoms with the supplychain example and spent a few days root-causing them, so sharing what we found.

    To answer your last question first: concept rules execute at build (ingestion) time, not at query time. When a record whose type has associated concept rules passes through the builder's reason stage, the server classifies it (belongTo) and fires causal (leadTo) rules, materializing the Action's nodes/edges into the graph right then. Nothing is ever created at query time — queries only compute over what ingestion materialized. So your expectation was correct: EntityBEvent should have been created during indexing.

    Why it silently doesn't happen — we traced three server-side defects in this exact code path:

    1. fix(reasoner): store business id as property on DDL-created vertices #622 — vertices created by createNodeInstance don't carry an id property. Any follow-up rule run that starts from such a vertex dies with an NPE that LocalReasonerRunner swallows, returning an empty result. The generated event then loses its belongTo classification, and nothing downstream fires. Crucially, no error reaches the client or docker logs — the stack trace only lands in /logs/openspgapp/common-error.log inside the server container. I'd check that file first; it likely explains your empty result.
    2. Concept-level event propagation always stops after one hop #623 — even when creation works, generated records are not standardized (entity-typed property → edge, e.g. subject) until the sink stage after the whole pass, so any subsequent rule matching on those edges finds nothing and propagation stops after one hop.
    3. fix(cloudext): do not JSON-encode scalar String property values #621 — string property values are stored double-JSON-encoded, which makes numeric/date constraints in rules silently match zero rows.

    Two more practical checks that bit us: the concept rules must be registered (knext schema reg_concept_rule --file ./schema/concept.rule) after schema commit, and stale builder checkpoint directories (*ckpt*) silently skip already-seen records on re-runs — delete them before re-indexing. Also note your Action references tp.id while the Structure binds n1/n2 — if that's not just a transcription slip, the rule would fail to evaluate as well.

    With the fixes from #621/#622 applied (and the change proposed in #623), one ingestion propagates the full event chain in our tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions