You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Neo4J中通过单个查询执行多LOAD CSV子查询并利用单个文件生成默认图数据库

How to Initialize a Default Neo4j Graph Database with a Single Cypher File

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 COMMIT doesn't work here because it only supports implicit transactions (queries centered on a single LOAD CSV). Stacking multiple LOAD CSV turns 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-shell to run the file directly:
    cypher-shell -u neo4j -p your_password -f /path/to/your/init_script.cypher
    

Key Takeaways

  • Never stack multiple LOAD CSV statements in one query—this floods memory with all row data at once.
  • Use batch processing (USING PERIODIC COMMIT or CALL { ... } IN TRANSACTIONS) to split large imports into manageable chunks.
  • A single .cypher file can contain all your initialization logic: data cleanup, imports, constraints, relationships, views, and procedures.

内容的提问来源于stack exchange,提问作者Enes Sabi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 23:37:27