Skip to content

Neo4j import plan

Date: 2026-06-01
CSV source: data/graph_exports/ (regenerated by python3 scripts/refresh_all.py)
Executable templates: graph_queries/neo4j_constraints.cypher, neo4j_import.cypher, analysis_queries.cypher

Neo4j is optional for this project. The same CSVs support pandas, NetworkX, or DuckDB. This plan describes a Community Edition import path when you want Cypher exploration.


Label Source Notes
Person nodes_people.csv person_id key
Resource nodes_resources.csv Facility/program/partner; 78 rows (non-course)
Grant nodes_grants.csv grant_id key
Publication nodes_publications.csv
Output nodes_outputs.csv Respect node include_in_graph on output records
Course Phase 2data/resource_courses.yaml Not in current CSV export
Equipment Phase 2data/resource_equipment.yaml Line items; link to Resource
Unit Derived from prefix on Resource Optional grouping node (CDM, CSH, …)
Topic nodes_topics.csv Canonical research vocabulary; topic_id key

Neo4j type CSV / YAML source Endpoints Property highlights
ABOUT_TOPIC edges_entity_topic.csv Person/Grant/Publication/Output/Course → Topic source (registry, derived, course_theme)
SUBTOPIC_OF edges_topic_parent.csv Topic → Topic Parent hierarchy roll-up
CONNECTED_TO_RESOURCE edges_person_resource.csv Person → Resource relationship, edge_type, evidence_level, include_in_graph, include_in_public_site
PI_ON edges_person_grant.csv Person → Grant role, evidence_level
FUNDED_BY (optional inverse) Grant → Person Mirror of PI_ON if bidirectional traversal needed
SUPPORTS_RESOURCE edges_grant_resource.csv Grant → Resource relationship, evidence_level
AUTHORED edges_person_publication.csv Person → Publication role
DOCUMENTS_RESOURCE edges_publication_resource.csv Publication → Resource High-evidence facility use
CREATED_OUTPUT edges_person_output.csv Person → Output role
OUTPUT_USES_RESOURCE edges_output_resource.csv Output → Resource
COURSE_USES_RESOURCE data/course_resource_links.yaml Course → Resource Phase 2 export
RESOURCE_HAS_EQUIPMENT data/resource_equipment.yaml Resource → Equipment Phase 2 export
AFFILIATED_WITH Subset of person–resource Person → Resource Where relationship=affiliated_faculty or evidence_level=affiliation
ADMINISTERED_BY Subset of person–resource Person → Resource administrator / administers; often excluded from default viz

Mapping note: You may model all person–resource rows as CONNECTED_TO_RESOURCE and filter by relationship + evidence_level, or split weak types into AFFILIATED_WITH / ADMINISTERED_BY at import time for simpler default queries.


3. CSV file → graph mapping

CSV file Graph element
nodes_people.csv (:Person)
nodes_resources.csv (:Resource)
nodes_grants.csv (:Grant)
nodes_publications.csv (:Publication)
nodes_outputs.csv (:Output)
edges_person_resource.csv (Person)-[:CONNECTED_TO_RESOURCE]->(Resource)
edges_person_grant.csv (Person)-[:PI_ON]->(Grant)
edges_grant_resource.csv (Grant)-[:SUPPORTS_RESOURCE]->(Resource)
edges_person_publication.csv (Person)-[:AUTHORED]->(Publication)
edges_publication_resource.csv (Publication)-[:DOCUMENTS_RESOURCE]->(Resource)
edges_person_output.csv (Person)-[:CREATED_OUTPUT]->(Output)
edges_output_resource.csv (Output)-[:OUTPUT_USES_RESOURCE]->(Resource)

Not yet exported to CSV: course links, equipment lines, facility–facility links (data/course_resource_links.yaml, resource_equipment.yaml, resource Markdown). Add nodes_courses.csv / edges_course_resource.csv in a future export_graph_tables.py extension before importing those relationship types.


4. Edge types excluded from default visualizations

Apply these filters in browser apps and default Cypher (WHERE clauses):

Pattern Reason
include_in_graph = 'false' Curated exclusion (weak evidence, UNI-001 anchors, courses)
resource_id = 'UNI-001' on any technical edge ORS administrative hub — not a collaboration node
relationship = 'grant_pi' AND resource_id = 'UNI-001' Must stay graph-excluded per person_link_rules.py
evidence_level IN ['excluded', 'topical', 'administrative'] Weak or narrative-only
evidence_level = 'affiliation' Unless user opts in to “show weak ties”
Broad administrator to non-operational resources Associate provost / ORS roles

Default viz profile: include_in_graph = 'true' AND evidence_level IN ['direct'] OR (direct + high confidence affiliation after manual review).


5. Suggested constraints

CREATE CONSTRAINT person_id IF NOT EXISTS FOR (p:Person) REQUIRE p.person_id IS UNIQUE;
CREATE CONSTRAINT resource_id IF NOT EXISTS FOR (r:Resource) REQUIRE r.resource_id IS UNIQUE;
CREATE CONSTRAINT grant_id IF NOT EXISTS FOR (g:Grant) REQUIRE g.grant_id IS UNIQUE;
CREATE CONSTRAINT publication_id IF NOT EXISTS FOR (p:Publication) REQUIRE p.publication_id IS UNIQUE;
CREATE CONSTRAINT output_id IF NOT EXISTS FOR (o:Output) REQUIRE o.output_id IS UNIQUE;

See graph_queries/neo4j_constraints.cypher for the full template.


6. Suggested indexes

Index Purpose
Person(person_id) Lookup, merge on import
Resource(resource_id), Resource(prefix) Unit filters
Grant(grant_id) Award lookup
Publication(publication_id), Output(output_id) Layer joins
Relationship include_in_graph Fast default subgraph
Relationship evidence_level Weak-edge audits

Relationship properties are indexed in Neo4j 5+ via relationship key syntax where supported; otherwise filter after MATCH with property predicates (templates use WHERE).


7. Starter LOAD CSV import

Prerequisites:

  1. Run python3 scripts/refresh_all.py to refresh data/graph_exports/.
  2. Copy CSVs to Neo4j import/ directory or set file:/// URLs in neo4j_import.cypher.
  3. Run constraints first (neo4j_constraints.cypher).
  4. Run neo4j_import.cypher.

Import templates load all rows but set properties so queries can filter include_in_graph. Alternative: pre-filter CSVs in Python before import.


8. Starter analysis queries

Included in graph_queries/analysis_queries.cypher:

  • Top resource hubs excluding UNI-001
  • People connected to multiple resource prefixes (cross-unit)
  • Grants linking people and resources (2-hop)
  • Publications/resources with strong evidence
  • Outputs/resources with strong evidence
  • Resources with equipment but no people (requires equipment export or external join)
  • People with grants but no publications or outputs
  • Resources with courses but no people (phase 2)
  • Cross-unit bridges
  • Weak-edge audit
  • False-hub audit (UNI-001, high-degree administrative)

9. Validation after import

Compare Neo4j counts to full-refresh-report.md:

Metric Expected (2026-06-01 baseline)
Person nodes 115
Resource nodes 78
Grant nodes 33
Publication nodes 34
Output nodes 18
CONNECTED_TO_RESOURCE (include_in_graph=true) 174
PI_ON (graph) 33
SUPPORTS_RESOURCE (graph) 9

Mismatch indicates stale CSVs or import filter errors—not necessarily wrong YAML.


10. Security

  • Do not load local-only grant PDFs into Neo4j without access controls.
  • Graph DB with internal evidence should not be exposed on the public MkDocs site.
  • Align with ragmap-and-graph-analysis-plan.md §7.