如何在Neo4J中通过单个查询执行多LOAD CSV子查询并利用单个文件生成默认图数据库
Let's break down your problem and walk through a solution that mirrors the "single script" workflow you're used to with MySQL.
Why Your Original Query Failed
Your initial approach of stacking multiple LOAD CSV statements in one query caused an OutOfMemoryError because:
- Neo4j loads all rows from every CSV into memory at once when they're in the same query, then attempts to create all nodes in a single transaction. Even if each CSV is small alone, combining them overwhelms memory.
USING PERIODIC COMMITdoesn't work here because it only supports implicit transactions (queries centered on a singleLOAD CSV). Stacking multipleLOAD CSVturns it into an explicit transaction, hence the semantic error.
Step-by-Step Solution for a Single Initialization Script
1. Clear Existing Data (Equivalent to DROP DATABASE)
First, wipe the graph to start fresh (skip this if you don't need a full reset):
// Delete all nodes and their associated relationships MATCH (n) DETACH DELETE n;
DETACH DELETE is critical here—Neo4j requires you to remove relationships before deleting nodes, and this command handles both automatically.
2. Load Data in Batched, Separate Queries
Split each CSV import into its own query block with batch processing to avoid memory overload. For Neo4j 3.x, use USING PERIODIC COMMIT; for Neo4j 4.0+, prefer CALL { ... } IN TRANSACTIONS (more flexible for complex logic).
Example: Load Ingredients
// Batch-import ingredient nodes USING PERIODIC COMMIT 250 LOAD CSV WITH HEADERS FROM 'file:///C:/Users/Enes/CSV_import/ingredients.csv' AS row CREATE (ing:Ingredient { name: row.ingredientName, ingredientName: row.ingredientName });
Example: Load Users (with Data Type Conversion)
// Batch-import user nodes (convert string boolean to actual boolean type) USING PERIODIC COMMIT 250 LOAD CSV WITH HEADERS FROM 'file:///C:/Users/Enes/CSV_import/users.csv' AS row FIELDTERMINATOR ';' CREATE (user:User { name: row.userName, userName: row.userName, userEmail: row.userEmail, userPassword: row.userPassword, enabled: toBoolean(row.enabled) });
Example: Load Recipes (with Numeric Type Conversion)
// Batch-import recipe nodes (convert string numbers to integers) USING PERIODIC COMMIT 250 LOAD CSV WITH HEADERS FROM 'file:///C:/Users/Enes/CSV_import/recipes.csv' AS row FIELDTERMINATOR ';' CREATE (recipe:Recipe { name: row.recipeName, recipeName: row.recipeName, prepTimeInMin: toInteger(row.prepTimeInMin), restTimeInMinutes: toInteger(row.restTimeInMinutes), prepText: row.prepText, people: toInteger(row.people), viewCount: toInteger(row.viewCount), difficultyName: row.difficultyName, mealTypeName: row.mealTimeName, createdByUser: row.createdByUser });
3. Add Constraints & Indexes (For Integrity & Performance)
Add these after importing nodes to enforce data uniqueness and speed up queries:
// Enforce unique user emails CREATE CONSTRAINT user_email_unique FOR (user:User) REQUIRE user.userEmail IS UNIQUE; // Index for fast ingredient lookups CREATE INDEX ingredient_name_index FOR (ing:Ingredient) ON (ing.ingredientName);
4. Create Relationships (If Needed)
If your data has connections (e.g., recipes using ingredients), add a separate query block:
// Batch-create relationships between recipes and ingredients USING PERIODIC COMMIT 250 LOAD CSV WITH HEADERS FROM 'file:///C:/Users/Enes/CSV_import/recipe_ingredients.csv' AS row MATCH (recipe:Recipe {recipeName: row.recipeName}) MATCH (ing:Ingredient {ingredientName: row.ingredientName}) CREATE (recipe)-[:CONTAINS_INGREDIENT]->(ing);
5. Create Views & Procedures
For views (Neo4j Enterprise Edition only) and stored procedures, add these final blocks:
// Create a view for popular recipes CREATE VIEW popularRecipes AS MATCH (r:Recipe) WHERE r.viewCount > 1000 RETURN r.recipeName, r.viewCount, r.difficultyName; // Example stored procedure (requires deployment of custom logic) CREATE PROCEDURE getRecipesByDifficulty(difficulty: String) YIELD recipeName, viewCount MATCH (r:Recipe {difficultyName: difficulty}) RETURN r.recipeName AS recipeName, r.viewCount AS viewCount;
How to Execute the Script
- Neo4j Desktop: Paste the entire script into the query editor and click "Run"—Neo4j will execute each query block in separate transactions automatically.
- Command Line: Use
cypher-shellto run the file directly:cypher-shell -u neo4j -p your_password -f /path/to/your/init_script.cypher
Key Takeaways
- Never stack multiple
LOAD CSVstatements in one query—this floods memory with all row data at once. - Use batch processing (
USING PERIODIC COMMITorCALL { ... } IN TRANSACTIONS) to split large imports into manageable chunks. - A single
.cypherfile can contain all your initialization logic: data cleanup, imports, constraints, relationships, views, and procedures.
内容的提问来源于stack exchange,提问作者Enes Sabi

