Files
boc/quixzoom-capture-pipeline/persistence/neo4j-schema.cypher
T
Bernt bae705aa97 ARCHITECTURE: NFC roadmap, edge AI, audit logging
- Add NFC ePassport roadmap (ICAO 9303, eIDAS)
- Add TensorFlow.js edge face detection (BlazeFace)
- Add structured audit logger (GDPR-compliant)
- Risk scoring support

Part of KYC Apple Native UX v1.1.0
2026-06-29 16:24:48 +00:00

241 lines
7.1 KiB
Plaintext

// QUIXZOOM Neo4j Schema
//
// Ansvarsområden:
// - Objektrelationer
// - Evidensgraf
// - Knowledge Graph
// - Relationer mellan objekt
// - Härledningar ("den här lyktstolpen tillhör denna gata")
// ============================================================
// NODER
// ============================================================
// Urban Objects
CREATE CONSTRAINT object_id IF NOT EXISTS
FOR (o:Object) REQUIRE o.object_id IS UNIQUE;
CREATE INDEX object_type IF NOT EXISTS
FOR (o:Object) ON (o.type);
CREATE INDEX object_location IF NOT EXISTS
FOR (o:Object) ON (o.location);
// Observations
CREATE CONSTRAINT observation_id IF NOT EXISTS
FOR (obs:Observation) REQUIRE obs.observation_id IS UNIQUE;
// Evidence
CREATE CONSTRAINT evidence_id IF NOT EXISTS
FOR (e:Evidence) REQUIRE e.evidence_id IS UNIQUE;
// Areas
CREATE CONSTRAINT area_id IF NOT EXISTS
FOR (a:Area) REQUIRE a.area_id IS UNIQUE;
// Zoomers
CREATE CONSTRAINT zoomer_id IF NOT EXISTS
FOR (z:Zoomer) REQUIRE z.zoomer_id IS UNIQUE;
// Missions
CREATE CONSTRAINT mission_id IF NOT EXISTS
FOR (m:Mission) REQUIRE m.mission_id IS UNIQUE;
// ============================================================
// RELATIONER
// ============================================================
// Object -> Observation (ett objekt observeras många gånger)
// (:Object)-[:OBSERVED_IN]->(:Observation)
// Object -> Evidence (ett objekt har många bevis)
// (:Object)-[:SUPPORTED_BY]->(:Evidence)
// Evidence -> Observation (bevis kommer från observation)
// (:Evidence)-[:DERIVED_FROM]->(:Observation)
// Object -> Object (relationer mellan objekt)
// (:Object)-[:NEAR {distance: 5}]->(:Object)
// (:Object)-[:CONNECTED_TO]->(:Object)
// (:Object)-[:PART_OF]->(:Object)
// (:Object)-[:SUPPORTS]->(:Object)
// (:Object)-[:OPPOSITE_TO]->(:Object)
// Object -> Area (objekt tillhör område)
// (:Object)-[:LOCATED_IN]->(:Area)
// Observation -> Zoomer (vem som observerade)
// (:Observation)-[:OBSERVED_BY]->(:Zoomer)
// Mission -> Object (uppdrag gäller objekt)
// (:Mission)-[:TARGETS]->(:Object)
// Mission -> Area (uppdrag i område)
// (:Mission)-[:IN_AREA]->(:Area)
// Mission -> Zoomer (uppdrag tilldelat zoomer)
// (:Mission)-[:ASSIGNED_TO]->(:Zoomer)
// Object -> Object (temporal — ersätter)
// (:Object)-[:REPLACED_BY {date: '2026-11-02'}]->(:Object)
// ============================================================
// EXEMPEL: Skapa objekt med relationer
// ============================================================
// Skapa gatlykta
CREATE (lamp:Object {
object_id: 'street_lamp_3e6a09cfabc7',
type: 'street_lamp',
subtype: 'led',
location: point({latitude: 13.725, longitude: 100.555}),
attributes: {
material: 'steel',
height: 7.8,
paint: 'grey',
rust: false,
lean: 0,
light: 'working'
},
verification_status: 'verified',
confidence: 0.94,
first_seen: datetime('2026-06-01T00:00:00Z'),
last_seen: datetime('2026-06-28T08:15:30Z')
});
// Skapa observation
CREATE (obs:Observation {
observation_id: 'obs_1782638086138_ab6ndwzwo',
source_type: 'quixzoom',
source_id: 'zoomer_001',
timestamp: datetime('2026-06-28T08:15:30Z'),
quality: {
resolution: 1080,
sharpness: 0.9
}
});
// Skapa evidens
CREATE (ev:Evidence {
evidence_id: 'ev_1782638086138_h3fstkqnd',
proof_type: 'video',
proof_url: 'https://r2.landvex.com/videos/bangkok_001.mp4#frame=342',
reliability: 0.85,
timestamp: datetime('2026-06-28T08:15:30Z')
});
// Skapa relationer
MATCH (lamp:Object {object_id: 'street_lamp_3e6a09cfabc7'})
MATCH (obs:Observation {observation_id: 'obs_1782638086138_ab6ndwzwo'})
MATCH (ev:Evidence {evidence_id: 'ev_1782638086138_h3fstkqnd'})
CREATE (lamp)-[:OBSERVED_IN]->(obs)
CREATE (lamp)-[:SUPPORTED_BY]->(ev)
CREATE (ev)-[:DERIVED_FROM]->(obs);
// ============================================================
// EXEMPEL: Spatiala relationer
// ============================================================
// Hitta objekt nära en plats
MATCH (o:Object)
WHERE point.distance(o.location, point({latitude: 13.725, longitude: 100.555})) < 50
RETURN o.object_id, o.type, o.location;
// Hitta närliggande objekt
MATCH (o1:Object)-[:NEAR]->(o2:Object)
WHERE o1.object_id = 'street_lamp_3e6a09cfabc7'
RETURN o2.object_id, o2.type;
// Hitta alla objekt av en typ i ett område
MATCH (o:Object)-[:LOCATED_IN]->(a:Area)
WHERE a.name = 'Sukhumvit' AND o.type = 'street_lamp'
RETURN o.object_id, o.location, o.attributes;
// ============================================================
// EXEMPEL: Härledningar
// ============================================================
// "Den här lyktstolpen tillhör denna gata"
MATCH (lamp:Object {type: 'street_lamp'})
MATCH (road:Object {type: 'road'})
WHERE point.distance(lamp.location, road.location) < 10
CREATE (lamp)-[:PART_OF {confidence: 0.9}]->(road);
// Hitta alla lyktstolpar på en gata
MATCH (road:Object {object_id: 'sukhumvit_road'})
<-[:PART_OF]-(lamp:Object)
RETURN lamp.object_id, lamp.attributes;
// ============================================================
// EXEMPEL: Temporal
// ============================================================
// Gatlykta ersatt
MATCH (old:Object {object_id: 'street_lamp_3e6a09cfabc7'})
CREATE (new:Object {
object_id: 'street_lamp_new_001',
type: 'street_lamp',
location: point({latitude: 13.725, longitude: 100.555}),
attributes: {
material: 'aluminum',
height: 8.0,
paint: 'black',
rust: false,
lean: 0,
light: 'working'
},
verification_status: 'verified',
confidence: 0.98,
first_seen: datetime('2026-11-02T00:00:00Z')
})
CREATE (old)-[:REPLACED_BY {date: datetime('2026-11-02T00:00:00Z')}]->(new);
// Hitta ersättningskedja
MATCH (old:Object)-[:REPLACED_BY*]->(new:Object)
WHERE old.object_id = 'street_lamp_3e6a09cfabc7'
RETURN old, new;
// ============================================================
// EXEMPEL: Evidensgraf
// ============================================================
// Hitta alla bevis för ett objekt
MATCH (o:Object {object_id: 'street_lamp_3e6a09cfabc7'})
-[:SUPPORTED_BY]->(e:Evidence)
RETURN e.evidence_id, e.proof_type, e.reliability, e.source_type;
// Hitta objekt med flest bevis
MATCH (o:Object)-[:SUPPORTED_BY]->(e:Evidence)
WITH o, count(e) as evidence_count
ORDER BY evidence_count DESC
LIMIT 10
RETURN o.object_id, o.type, evidence_count;
// ============================================================
// EXEMPEL: Knowledge Graph-frågor
// ============================================================
// Hitta objekt som behöver verifiering
MATCH (o:Object)
WHERE o.verification_status = 'unverified'
RETURN o.object_id, o.type, o.location, o.confidence;
// Hitta objekt med låg konfidens
MATCH (o:Object)
WHERE o.confidence < 0.5
RETURN o.object_id, o.type, o.confidence;
// Hitta "ensamma" objekt (få relationer)
MATCH (o:Object)
OPTIONAL MATCH (o)-[r]-()
WITH o, count(r) as relation_count
WHERE relation_count < 2
RETURN o.object_id, o.type, relation_count;
// Hitta objekt med motsägande evidens
MATCH (o:Object)-[:SUPPORTED_BY]->(e1:Evidence)
MATCH (o)-[:SUPPORTED_BY]->(e2:Evidence)
WHERE e1.reliability > 0.8 AND e2.reliability > 0.8
AND e1.proof_type <> e2.proof_type
RETURN o.object_id, count(e1) as evidence_count;