From 6d16828df48faa471859d5a36a77f0e92578ef9b Mon Sep 17 00:00:00 2001 From: Artur Kruszewski Date: Wed, 8 Jul 2026 23:30:28 +0200 Subject: [PATCH] T12: GraphLoader Organization/Company loading + GraphSchema constraints [production] --- .../developx/szpitale/load/GraphLoader.java | 144 +++++++++++++++++- .../developx/szpitale/load/GraphSchema.java | 2 + .../szpitale/load/GraphLoader$LoadStats.class | Bin 2060 -> 2965 bytes .../developx/szpitale/load/GraphLoader.class | Bin 14849 -> 20700 bytes .../developx/szpitale/load/GraphSchema.class | Bin 2162 -> 2363 bytes 5 files changed, 144 insertions(+), 2 deletions(-) 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 dbdcd315165e825ee08593f399201df7a6270f94..3be5eeaa435a7e2e988b894624f1621fd57d3e2e 100644 GIT binary patch literal 2965 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 E0TTo^*#H0l literal 14849 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 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 6c2b0eab961f629cc0a95f75f82965ec878af84e..b677b4a7df517b05fd901817861f7edf18e2aefb 100644 GIT binary patch delta 872 zcmb7>O>YuW6o%hBGcbHiwNBMol?Ga>Wq@MUV#O~Irvh4#0d&)(nbL-0=#0T?qb~42 zjBA&=#>Njcsd3}N-{MAh#>9FUN^9yyH|L!9=G^z5=brC_A7sy$U+*^oq;R|KdCm=M zX-!R)Re!pWFO{`aHedFe&DuhJ$@;_{%$SKnv!)yM$NE~`G(vt&EmpFc>Nh9rOa5%h zU&&{S71f0xL-B8;s=0bkHy&-91*?g4?_k%by2s~)^@7W>3F{k|b1D+Th*&A!$0n@> zUh$s7l!((3&fu)|jE_&nC7gqk!BK6P_m@SSXBfJxKh$Fl-KfRND@}7l;smDr?b$^fxlRkSGfvb7a6FOKO%fN7}|2Qd!e&lnANFwO81!*itMzH;Xy(Kkp$KDNotgL%{m z-oP5xDf9NIaST{roq?4sjzPn5>hV$65Ly`78QX&gIDlI;8I7|IP^3BpVT+nM5iXJV zn24Dz41n)xQudMK2VG=jZlhVN;*r+nU4-QSA^4z>Z4A>C`v^zL83+*IC=EVF072>s yAc^rm5aK%sDPu2#@=pvdl=|x-_wHu^ZrSw?S2qyqE}z*y+Qsaym!V9VL*+N7(vo5T delta 722 zcmb7>OHWfl6vuyaAD#C0f^dl@J}MSP;og>tLVas1KCl8lV$zM9(li)TA<;ya{SdP^ z?o3QvRD4wv-5KL2@M9P^#*J`#p^Z!3%$fh0^ZL#C82lXazWw>|2`F>B?LD6wsL%{LVLC@%Gv!m@sF`z$)5m;{lTf(z=Gvo%W>ztBzxKFRXx3I& z3U}^3TzgVmZZVQAjJ?@MeW*(W}a)JBrmS2sL0(_B9QXe zNysVXRZ7BLN1Ur>SeGiV7!M{pL>AE(#-a|>is$TJ6czMTYAKh0OELGkExDc)t_td1 zmT8E!