diff --git a/szpitale-graph/src/main/java/com/developx/szpitale/load/GraphLoader.java b/szpitale-graph/src/main/java/com/developx/szpitale/load/GraphLoader.java index bfca149..38a5df2 100644 --- a/szpitale-graph/src/main/java/com/developx/szpitale/load/GraphLoader.java +++ b/szpitale-graph/src/main/java/com/developx/szpitale/load/GraphLoader.java @@ -30,6 +30,11 @@ public class GraphLoader { loadRoles(session, dataset.roles(), stats); loadAffiliations(session, dataset.affiliations(), stats); loadMandates(session, dataset.mandates(), stats); + loadOrganizations(session, dataset.organizations(), stats); + loadCompanies(session, dataset.companies(), stats); + loadPersonOrganizationLinks(session, dataset.personOrganizationLinks(), stats); + loadOrganizationLinks(session, dataset.organizationLinks(), stats); + loadPersonCompanyLinks(session, dataset.personCompanyLinks(), stats); } } return stats; @@ -176,6 +181,130 @@ public class GraphLoader { } } + private void loadOrganizations(Session session, List organizations, LoadStats stats) { + if (organizations.isEmpty()) return; + + List> batch = new ArrayList<>(); + for (Organization o : organizations) { + batch.add(Map.of( + "id", o.id(), + "name", o.name(), + "krs", o.krs(), + "nip", o.nip(), + "sourceUrls", o.sourceUrls() + )); + } + + for (int i = 0; i < batch.size(); i += BATCH_SIZE) { + List> subList = batch.subList(i, Math.min(i + BATCH_SIZE, batch.size())); + String cypher = "UNWIND $batch AS o " + + "MERGE (org:Organization {id: o.id}) " + + "SET org += {name: o.name, krs: o.krs, nip: o.nip, sourceUrls: o.sourceUrls}"; + session.run(cypher, Map.of("batch", subList)); + stats.addOrganizations(subList.size()); + } + } + + private void loadCompanies(Session session, List companies, LoadStats stats) { + if (companies.isEmpty()) return; + + List> batch = new ArrayList<>(); + for (Company c : companies) { + batch.add(Map.of( + "id", c.id(), + "name", c.name(), + "krs", c.krs(), + "nip", c.nip(), + "ceidgId", c.ceidgId(), + "sourceUrls", c.sourceUrls() + )); + } + + for (int i = 0; i < batch.size(); i += BATCH_SIZE) { + List> subList = batch.subList(i, Math.min(i + BATCH_SIZE, batch.size())); + String cypher = "UNWIND $batch AS c " + + "MERGE (comp:Company {id: c.id}) " + + "SET comp += {name: c.name, krs: c.krs, nip: c.nip, ceidgId: c.ceidgId, sourceUrls: c.sourceUrls}"; + session.run(cypher, Map.of("batch", subList)); + stats.addCompanies(subList.size()); + } + } + + private void loadPersonOrganizationLinks(Session session, List links, LoadStats stats) { + if (links.isEmpty()) return; + + List> batch = new ArrayList<>(); + for (PersonOrganizationLink l : links) { + batch.add(Map.of( + "personId", l.personId(), + "organizationId", l.organizationId(), + "roleLabel", l.roleLabel(), + "basis", l.basis().name(), + "sourceUrls", l.sourceUrls() + )); + } + + for (int i = 0; i < batch.size(); i += BATCH_SIZE) { + List> subList = batch.subList(i, Math.min(i + BATCH_SIZE, batch.size())); + String cypher = "UNWIND $batch AS l " + + "MATCH (p:Person {id: l.personId}), (org:Organization {id: l.organizationId}) " + + "MERGE (p)-[m:CZLONEK_ORGANIZACJI]->(org) " + + "SET m += {roleLabel: l.roleLabel, basis: l.basis, sourceUrls: l.sourceUrls}"; + session.run(cypher, Map.of("batch", subList)); + stats.addPersonOrganizationLinks(subList.size()); + } + } + + private void loadOrganizationLinks(Session session, List links, LoadStats stats) { + if (links.isEmpty()) return; + + List> batch = new ArrayList<>(); + for (OrganizationLink l : links) { + batch.add(Map.of( + "fromId", l.fromOrganizationId(), + "toId", l.toOrganizationId(), + "basis", l.basis().name(), + "note", l.note(), + "sourceUrls", l.sourceUrls() + )); + } + + for (int i = 0; i < batch.size(); i += BATCH_SIZE) { + List> subList = batch.subList(i, Math.min(i + BATCH_SIZE, batch.size())); + String cypher = "UNWIND $batch AS l " + + "MATCH (a:Organization {id: l.fromId}), (b:Organization {id: l.toId}) " + + "MERGE (a)-[m:POWIAZANA_Z]->(b) " + + "SET m += {basis: l.basis, note: l.note, sourceUrls: l.sourceUrls}"; + session.run(cypher, Map.of("batch", subList)); + stats.addOrganizationLinks(subList.size()); + } + } + + private void loadPersonCompanyLinks(Session session, List links, LoadStats stats) { + if (links.isEmpty()) return; + + List> batch = new ArrayList<>(); + for (PersonCompanyLink l : links) { + batch.add(Map.of( + "personId", l.personId(), + "companyId", l.companyId(), + "roleLabel", l.roleLabel(), + "basis", l.basis().name(), + "sourceUrls", l.sourceUrls() + )); + } + + for (int i = 0; i < batch.size(); i += BATCH_SIZE) { + List> subList = batch.subList(i, Math.min(i + BATCH_SIZE, batch.size())); + String cypher = "UNWIND $batch AS l " + + "MATCH (p:Person {id: l.personId}), (comp:Company {id: l.companyId}) " + + "MERGE (p)-[m:POWIAZANY_Z_FIRMA]->(comp) " + + "SET m += {roleLabel: l.roleLabel, basis: l.basis, sourceUrls: l.sourceUrls}"; + session.run(cypher, Map.of("batch", subList)); + stats.addPersonCompanyLinks(subList.size()); + } + } + private String roleTypeToRelName(Role r) { String organ = r.organ().name(); String role = r.roleType().name(); @@ -196,6 +325,11 @@ public class GraphLoader { public int roleCount; public int affiliationCount; public int mandateCount; + public int organizationCount; + public int companyCount; + public int personOrganizationLinkCount; + public int organizationLinkCount; + public int personCompanyLinkCount; public final List voivodeships = new ArrayList<>(); public void addVoivodeship(String v) { voivodeships.add(v); } @@ -204,12 +338,18 @@ public class GraphLoader { public void addRoles(int count) { roleCount += count; } public void addAffiliations(int count) { affiliationCount += count; } public void addMandates(int count) { mandateCount += count; } + public void addOrganizations(int count) { organizationCount += count; } + public void addCompanies(int count) { companyCount += count; } + public void addPersonOrganizationLinks(int count) { personOrganizationLinkCount += count; } + public void addOrganizationLinks(int count) { organizationLinkCount += count; } + public void addPersonCompanyLinks(int count) { personCompanyLinkCount += count; } @Override public String toString() { return String.format( - "Load stats - voivodeships: %s, hospitals: %d, people: %d, roles: %d, affiliations: %d, mandates: %d", - String.join(", ", voivodeships), hospitalCount, personCount, roleCount, affiliationCount, mandateCount + "Load stats - voivodeships: %s, hospitals: %d, people: %d, roles: %d, affiliations: %d, mandates: %d, organizations: %d, companies: %d, personOrgLinks: %d, orgLinks: %d, personCompanyLinks: %d", + String.join(", ", voivodeships), hospitalCount, personCount, roleCount, affiliationCount, mandateCount, + organizationCount, companyCount, personOrganizationLinkCount, organizationLinkCount, personCompanyLinkCount ); } } diff --git a/szpitale-graph/src/main/java/com/developx/szpitale/load/GraphSchema.java b/szpitale-graph/src/main/java/com/developx/szpitale/load/GraphSchema.java index a12f3e8..808a93b 100644 --- a/szpitale-graph/src/main/java/com/developx/szpitale/load/GraphSchema.java +++ b/szpitale-graph/src/main/java/com/developx/szpitale/load/GraphSchema.java @@ -21,6 +21,8 @@ public class GraphSchema { session.run("CREATE CONSTRAINT person_id IF NOT EXISTS FOR (p:Person) REQUIRE p.id IS UNIQUE"); session.run("CREATE CONSTRAINT party_name IF NOT EXISTS FOR (x:Party) REQUIRE x.name IS UNIQUE"); session.run("CREATE CONSTRAINT voiv_slug IF NOT EXISTS FOR (v:Voivodeship) REQUIRE v.slug IS UNIQUE"); + session.run("CREATE CONSTRAINT org_id IF NOT EXISTS FOR (o:Organization) REQUIRE o.id IS UNIQUE"); + session.run("CREATE CONSTRAINT company_id IF NOT EXISTS FOR (c:Company) REQUIRE c.id IS UNIQUE"); session.run("CREATE INDEX person_name IF NOT EXISTS FOR (p:Person) ON (p.fullName)"); session.run("CREATE INDEX govbody_name IF NOT EXISTS FOR (g:GovBody) ON (g.name)"); log.info("Graph constraints and indexes created"); diff --git a/szpitale-graph/target/classes/com/developx/szpitale/load/GraphLoader$LoadStats.class b/szpitale-graph/target/classes/com/developx/szpitale/load/GraphLoader$LoadStats.class index dbdcd31..3be5eea 100644 Binary files a/szpitale-graph/target/classes/com/developx/szpitale/load/GraphLoader$LoadStats.class and b/szpitale-graph/target/classes/com/developx/szpitale/load/GraphLoader$LoadStats.class differ diff --git a/szpitale-graph/target/classes/com/developx/szpitale/load/GraphLoader.class b/szpitale-graph/target/classes/com/developx/szpitale/load/GraphLoader.class index 106189f..6c1c972 100644 Binary files a/szpitale-graph/target/classes/com/developx/szpitale/load/GraphLoader.class and b/szpitale-graph/target/classes/com/developx/szpitale/load/GraphLoader.class differ diff --git a/szpitale-graph/target/classes/com/developx/szpitale/load/GraphSchema.class b/szpitale-graph/target/classes/com/developx/szpitale/load/GraphSchema.class index 6c2b0ea..b677b4a 100644 Binary files a/szpitale-graph/target/classes/com/developx/szpitale/load/GraphSchema.class and b/szpitale-graph/target/classes/com/developx/szpitale/load/GraphSchema.class differ