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

Apache-age浏览器端无需本地路径加载CSV生成图的替代方案咨询

Apache-age浏览器端上传CSV生成图的解决方案

因为浏览器出于安全限制无法提供本地文件路径,无法直接使用load_labels_from_file函数,以下是几种可行的替代方案:

方案1:后端中转临时文件

浏览器读取CSV内容后发送给后端,后端将内容写入服务器临时文件,再调用load_labels_from_file完成导入,导入后删除临时文件。

前端JS示例(读取并上传CSV内容)

// 绑定文件上传控件的change事件
document.getElementById('csv-upload').addEventListener('change', async (e) => {
  const file = e.target.files[0];
  if (!file) return;

  const reader = new FileReader();
  reader.onload = async (event) => {
    const csvContent = event.target.result;
    // 发送CSV内容到后端接口
    const response = await fetch('/api/upload-csv', {
      method: 'POST',
      headers: { 'Content-Type': 'text/csv' },
      body: csvContent
    });
    const result = await response.json();
    console.log('导入状态:', result);
  };
  reader.readAsText(file);
});

后端处理示例(Node.js + PostgreSQL)

const express = require('express');
const fs = require('fs').promises;
const path = require('path');
const { Pool } = require('pg');

const app = express();
app.use(express.text({ type: 'text/csv' }));

// 配置PostgreSQL连接(需启用Apache-age扩展)
const pool = new Pool({
  user: 'your-db-user',
  host: 'your-db-host',
  database: 'your-db-name',
  password: 'your-db-password',
  port: 5432
});

app.post('/api/upload-csv', async (req, res) => {
  const csvContent = req.body;
  const tempFilePath = path.join(__dirname, 'temp_upload.csv');

  try {
    // 写入临时文件
    await fs.writeFile(tempFilePath, csvContent);
    // 执行Apache-age导入查询
    await pool.query(`
      SELECT load_labels_from_file('your-graph-name', 'your-label-name', '${tempFilePath}', false);
    `);
    res.json({ success: true, msg: 'CSV导入完成' });
  } catch (err) {
    res.status(500).json({ success: false, error: err.message });
  } finally {
    // 清理临时文件
    try { await fs.unlink(tempFilePath); }
    catch (cleanErr) { console.error('临时文件清理失败:', cleanErr); }
  }
});

app.listen(3000, () => console.log('服务启动在3000端口'));

方案2:前端解析CSV生成批量Cypher语句

前端用JS解析CSV内容,将每行数据转换为创建节点/边的Cypher语句,批量发送给后端执行,无需服务器创建临时文件。

前端JS示例(使用Papa Parse解析CSV)

// 引入Papa Parse库(可通过CDN:<script src="https://cdn.jsdelivr.net/npm/papaparse@5.4.1/papaparse.min.js"></script>)
document.getElementById('csv-upload').addEventListener('change', async (e) => {
  const file = e.target.files[0];
  if (!file) return;

  Papa.parse(file, {
    header: true, // 假设CSV首行为表头
    complete: async (results) => {
      // 转换CSV数据为节点数组
      const nodeData = results.data.map(row => ({
        name: row.username,
        age: parseInt(row.user_age),
        email: row.user_email
      }));

      // 生成批量创建节点的Cypher(用UNWIND提升效率)
      const cypherQuery = `
        UNWIND $nodes AS node
        CREATE (u:User {name: node.name, age: node.age, email: node.email})
        RETURN u
      `;

      // 发送Cypher查询到后端
      const response = await fetch('/api/run-cypher', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ query: cypherQuery, params: { nodes: nodeData } })
      });
      const result = await response.json();
      console.log('节点创建结果:', result);
    }
  });
});

后端执行Cypher示例

app.post('/api/run-cypher', async (req, res) => {
  const { query, params } = req.body;
  try {
    // 执行Cypher查询(Apache-age兼容PostgreSQL驱动)
    const dbResult = await pool.query(`
      SELECT * FROM cypher('your-graph-name', $$ ${query} $$, $1) AS (u agtype)
    `, [params]);
    res.json({ success: true, data: dbResult.rows });
  } catch (err) {
    res.status(500).json({ success: false, error: err.message });
  }
});

方案3:PostgreSQL COPY导入临时表再转图

借助PostgreSQL的COPY命令将CSV导入临时表,再通过Cypher从临时表创建图节点/边,适合大数据量场景,效率更高。

后端处理示例

app.post('/api/upload-csv', async (req, res) => {
  const csvContent = req.body;
  const client = await pool.connect();

  try {
    await client.query('BEGIN');
    // 创建与CSV结构匹配的临时表
    await client.query(`
      CREATE TEMP TABLE temp_user_data (
        username VARCHAR,
        user_age INT,
        user_email VARCHAR
      ) ON COMMIT DROP;
    `);
    // 用COPY从标准输入导入CSV数据
    await client.query('COPY temp_user_data FROM STDIN WITH (FORMAT CSV, HEADER)', {
      rowMode: 'array',
      input: csvContent
    });
    // 从临时表创建Apache-age节点
    await client.query(`
      SELECT * FROM cypher('your-graph-name', $$
        MATCH (t:temp_user_data)
        CREATE (u:User {name: t.username, age: t.user_age, email: t.user_email})
      $$) AS (u agtype);
    `);
    await client.query('COMMIT');
    res.json({ success: true, msg: 'CSV导入完成' });
  } catch (err) {
    await client.query('ROLLBACK');
    res.status(500).json({ success: false, error: err.message });
  } finally {
    client.release();
  }
});

内容的提问来源于stack exchange,提问作者Kamlesh Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 03:27:45