// 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;