Javascript 使用node.js在neo4j中导入CSV

Javascript 使用node.js在neo4j中导入CSV,javascript,node.js,neo4j,Javascript,Node.js,Neo4j,我正在尝试使用node.js将csv文件导入neo4j。我必须将数据插入多个集合/表格,因此我必须使用node.js脚本插入数据。但我的问题是,在插入csv数据时无法防止数据重复 CSV数据示例: name ------------- Afghanistan Afghanistan Aland Albania Albania Bangladesh Bangladesh index.js cp = require('child_process'); child = cp.fork(__dirna

我正在尝试使用node.js将
csv
文件导入
neo4j
。我必须将数据插入多个
集合/表格
,因此我必须使用node.js脚本插入数据。但我的问题是,在插入csv数据时无法防止数据重复

CSV数据示例:

name
-------------
Afghanistan
Afghanistan
Aland
Albania
Albania
Bangladesh
Bangladesh
index.js

cp = require('child_process');
child = cp.fork(__dirname + "/background-import-csv-file.js");
child.on('message', function(msg) {
    console.log("background-insert-process said : ", msg);
});
file = path.resolve(__dirname, `./file/simplemaps.csv`);
child.send(file);
后台导入csv文件.js
中,我用两种不同的方式编写代码

基于第一个承诺的
后台导入csv文件.js
):

/collection/country.js

  Q = require('q');
  Country = function Country(neo) {
    this.country = "Country";  this.neo = neo;
  };

  Country.prototype.find = function find(filters) {
     query = `MATCH (a:Country  { name: '${filters.name}' } )  RETURN {country:properties(a)}`;
     return this.neo.run(query, filters).then(resp => resp);
  }

  Country.prototype.create = function create(data) {
    query = `CREATE (ax:Country  { name: '${data.name}' } )  RETURN ax `;
    return this.neo.run(query, {}).then(resp => resp[0].properties).catch(err => err)
   }

   Country.prototype.insert = function insert(country) {
      filter = { name: country.name };
      return Q(this.find(filter))
        .then(resp => resp.length > 0 ? Q.resolve({ msg: `country: [${country.name}] is already exist` }) : Q.resolve(this.create(country))  )
    .then(resp => resp)
    .catch(e => Q.reject(e));
   }

   module.exports = Country;
 EventEmitter = require('events').EventEmitter;
 util = require('util');

 Country = function Country(neo) {
   this.neo = neo;  EventEmitter.call(this);
 };
 util.inherits(Country, EventEmitter);

 Country.prototype.find = function find(filters) {
    query = `MATCH (a:Country  { name: '${filters.name}' } )  RETURN {country:properties(a)}`;
    return this.neo.run(query, {}).then(resp => this.emit('find', resp));
 }

 Country.prototype.create = function create(data) {
    query = `CREATE (ax:Country  { name: '${data.name}' } )  RETURN ax `;
    return this.neo.run(query, {}).then(resp => this.emit('create', resp[0].properties)).catch(err =>  err)
 }
/common/driver.js

neo4j = require('neo4j-driver').v1;
function DB() {
   this.driver = neo4j.driver();   this.session = this.driver.session();
}

DB.prototype.run = function run(query, data) {
    return this.session.run(query, data)
    .then(response => response.records.map(
            record => record._fields[0] ?
            record._fields.length ? record._fields[0] : {} : {}
        ) ).catch(err => new Error(err) );
}

module.exports = DB;
当我在终端中运行
index.js
时,在数据库中,我有2个
阿富汗
,1个
阿兰
,2个
阿尔巴尼亚
和2个
孟加拉国
。但我的数据库中需要1个
阿富汗
、1个
阿拉德
、1个
阿尔巴尼亚
和1个
孟加拉国
。当我分析代码时,发现在插入数据之前,我正在检查数据(
Country.prototype.find=function find(filters)
)是否已经存在,但它总是返回空结果。这就是它插入多个数据的原因。若我再次运行
index.js
,则不会将新数据插入数据库。为了解决这个问题,我尝试了以下
CQL

  MERGE (c:Country  { name: '${data.name}' } )  RETURN c
它插入的是唯一的数据,但它占用了很多时间。然后我编写了以下代码:

事件驱动(
后台导入csv文件.js
):

/collection/country.js

  Q = require('q');
  Country = function Country(neo) {
    this.country = "Country";  this.neo = neo;
  };

  Country.prototype.find = function find(filters) {
     query = `MATCH (a:Country  { name: '${filters.name}' } )  RETURN {country:properties(a)}`;
     return this.neo.run(query, filters).then(resp => resp);
  }

  Country.prototype.create = function create(data) {
    query = `CREATE (ax:Country  { name: '${data.name}' } )  RETURN ax `;
    return this.neo.run(query, {}).then(resp => resp[0].properties).catch(err => err)
   }

   Country.prototype.insert = function insert(country) {
      filter = { name: country.name };
      return Q(this.find(filter))
        .then(resp => resp.length > 0 ? Q.resolve({ msg: `country: [${country.name}] is already exist` }) : Q.resolve(this.create(country))  )
    .then(resp => resp)
    .catch(e => Q.reject(e));
   }

   module.exports = Country;
 EventEmitter = require('events').EventEmitter;
 util = require('util');

 Country = function Country(neo) {
   this.neo = neo;  EventEmitter.call(this);
 };
 util.inherits(Country, EventEmitter);

 Country.prototype.find = function find(filters) {
    query = `MATCH (a:Country  { name: '${filters.name}' } )  RETURN {country:properties(a)}`;
    return this.neo.run(query, {}).then(resp => this.emit('find', resp));
 }

 Country.prototype.create = function create(data) {
    query = `CREATE (ax:Country  { name: '${data.name}' } )  RETURN ax `;
    return this.neo.run(query, {}).then(resp => this.emit('create', resp[0].properties)).catch(err =>  err)
 }
这一次,它显示了相同的结果。我错过了什么?任何建议都会很有帮助


注意:我使用
fastcvs
进行csv解析,使用
Q
进行承诺

实际上,我可以想象以下解决方案:

  • 使用编程语言(如node.js)修改CSV文件本身,以删除同名的重复行
  • 添加neo4j
    对(c:Country)断言c.name创建约束是唯一的
  • 涉及中间件,如队列,以防止重复项,为此,您需要定义自己的消息结构和重复算法

  • 上图。

    我的问题是,在
    csv
    文件解析中,它非常快(事件驱动),不需要等待就可以将数据插入数据库。因此,我必须暂停文件解析,然后恢复它

    我使用以下代码解决问题:

    基于承诺(后台导入csv文件.js):

    cp = require('child_process');
    csv = require('fast-csv');
    Q = require('q');
    DB = require("./common/driver");
    Country = require('./collection/country');
    
    process.on("message", (file) => {
      stream = fs.createReadStream(file);
      csvstream = csv
        .fromStream(stream, { headers: true })
        .on("data", function(data) {
           csvstream.pause();  // pause the csv file parsing
           countryData = { "name": data.name };
           neo = new DB();
           country = new Country(neo);
           country.insert(countryData)
             .then(resp => {
                 process.send(resp.msg);
                 neo.close();
                 return csvstream.resume(); // after completing db process, resume 
             })
             .catch(err => {
                 process.send(err);
                 return csvstream.resume();  // if failed, then resume 
              });
        })
        .on("end", () => process.send("file read complete") );
     });
    
    “勒贝尔”是什么意思?我看不出一个明显的原因,为什么不能用一个简单的密码查询来实现这一点。