Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用NodeJS驱动程序在Neo4j中链接查询,同时在新属性中合并一些数据?_Javascript_Node.js_Neo4j - Fatal编程技术网

Javascript 如何使用NodeJS驱动程序在Neo4j中链接查询,同时在新属性中合并一些数据?

Javascript 如何使用NodeJS驱动程序在Neo4j中链接查询,同时在新属性中合并一些数据?,javascript,node.js,neo4j,Javascript,Node.js,Neo4j,我有一个Javascript对象格式的标记元素列表,我正在为NodeJS项目编写导入函数。列表中可能存在这些元素的重复项,因为该列表是来自不同来源的列表的组合 示例列表(这是test.json的内容): [ //0 - first time this element appears on the list { name : "Name 1", identifier : "string0001", added_date :

我有一个Javascript对象格式的标记元素列表,我正在为NodeJS项目编写导入函数。列表中可能存在这些元素的重复项,因为该列表是来自不同来源的列表的组合

示例列表(这是test.json的内容):

[
    //0 - first time this element appears on the list
    {
        name       : "Name 1",
        identifier : "string0001",
        added_date : "1437013195",
        tags       : ["tag1", "tag2"]
    },
    //1 - same as 0 but the added_date is different and the name is different, an additional tag3 is present
    {
        name       : "Name 2",
        identifier : "string0001",
        added_date : "1437082145",
        tags       : ["tag1", "tag3"]
    },
    //3 - a second unique element but it uses the same tags as 0
    {
        name       : "Name 3",
        identifier : "string0002",
        added_date : "1358426363",
        tags       : ["tag1", "tag2"]
    },
    //4 - third unique element with a new tag tag4
    {
        name       : "Name 4",
        identifier : "string0003",
        added_date : "1422912783",
        tags       : ["tag1", "tag4"]
    },
    // 5 - same element as 4, it was added before 4, it's tagged less than 4
    {
        name       : "Name 4",
        identifier : "string0003",
        added_date : "1358426363",
        tags       : ["tag1"]
    }
]
var neo4j = require('neo4j-driver').v1;

// Create a driver instance, for the user neo4j with password neo4j.
// It should be enough to have a single driver per database per application.
var driver = neo4j.driver("bolt://localhost:7687", neo4j.auth.basic("neo4j", "123456"));

// Register a callback to know if driver creation was successful:
driver.onCompleted = function () {
    // proceed with using the driver, it was successfully instantiated
    console.log('successfully connected');
};

// Register a callback to know if driver creation failed.
// This could happen due to wrong credentials or database unavailability:
driver.onError = function (error) {
    console.log('Driver instantiation failed', error);
};

// Create a session to run Cypher statements in.
// Note: Always make sure to close sessions when you are done using them!
var session = driver.session();
//console.log(session);

var test = require('./test.json');
for ( var element in test ) {

    if (test.hasOwnProperty(element)) {
        var obj = test[element];
        var element_object = {name:'', identifier:'',add_date:''};
        var tags;
        for ( var prop in obj ) {
            if (obj.hasOwnProperty(prop)) {
                //console.log('obj.' + prop + ' = ' + obj[prop]);
                if (prop === 'tags') {
                    tags = obj[prop];
                } else {
                    element_object[prop] = obj[prop].replace(/["']/g, "\\\"");
                }
            }
        }
        console.log('gonna create this element', JSON.stringify(element_object));
        console.log('tagged by', tags);

        var q = 'MERGE (element:Element {identifier:"'+element_object.identifier+'", name:"'+element_object.name+'", add_date:"'+element_object.add_date+'"})\n';
        var q2 = '';
        var q3 = '';
        for(var i=0; i<tags.length;i++){
            q2+= 'MERGE(tag'+i+':Tag {name:"'+tags[i]+'"})\n';
            q3+= 'MERGE(element)-[:TAGGED_WITH]->(tag'+i+')\n';
        }
        q += q2;
        q += q3;
        q += ";";



        console.log('query:', q);


        session
            .run(q)
            .then( function(result) {
                console.log('added element:',result);
                driver.close();
            })
            .catch( function(error) {
                console.log(error);
                // Close the driver when application exits
                driver.close();
            })

    }
}
这里的唯一标识符是属性
标识符
,不在乎名称是否不同。在element
0
1
的情况下,我希望数据库中有一个
:element
节点

我将有两个节点:

[
    //0 - first time this element appears on the list
    {
        name       : "Name 1",
        identifier : "string0001",
        added_date : "1437013195",
        tags       : ["tag1", "tag2"]
    },
    //1 - same as 0 but the added_date is different and the name is different, an additional tag3 is present
    {
        name       : "Name 2",
        identifier : "string0001",
        added_date : "1437082145",
        tags       : ["tag1", "tag3"]
    },
    //3 - a second unique element but it uses the same tags as 0
    {
        name       : "Name 3",
        identifier : "string0002",
        added_date : "1358426363",
        tags       : ["tag1", "tag2"]
    },
    //4 - third unique element with a new tag tag4
    {
        name       : "Name 4",
        identifier : "string0003",
        added_date : "1422912783",
        tags       : ["tag1", "tag4"]
    },
    // 5 - same element as 4, it was added before 4, it's tagged less than 4
    {
        name       : "Name 4",
        identifier : "string0003",
        added_date : "1358426363",
        tags       : ["tag1"]
    }
]
var neo4j = require('neo4j-driver').v1;

// Create a driver instance, for the user neo4j with password neo4j.
// It should be enough to have a single driver per database per application.
var driver = neo4j.driver("bolt://localhost:7687", neo4j.auth.basic("neo4j", "123456"));

// Register a callback to know if driver creation was successful:
driver.onCompleted = function () {
    // proceed with using the driver, it was successfully instantiated
    console.log('successfully connected');
};

// Register a callback to know if driver creation failed.
// This could happen due to wrong credentials or database unavailability:
driver.onError = function (error) {
    console.log('Driver instantiation failed', error);
};

// Create a session to run Cypher statements in.
// Note: Always make sure to close sessions when you are done using them!
var session = driver.session();
//console.log(session);

var test = require('./test.json');
for ( var element in test ) {

    if (test.hasOwnProperty(element)) {
        var obj = test[element];
        var element_object = {name:'', identifier:'',add_date:''};
        var tags;
        for ( var prop in obj ) {
            if (obj.hasOwnProperty(prop)) {
                //console.log('obj.' + prop + ' = ' + obj[prop]);
                if (prop === 'tags') {
                    tags = obj[prop];
                } else {
                    element_object[prop] = obj[prop].replace(/["']/g, "\\\"");
                }
            }
        }
        console.log('gonna create this element', JSON.stringify(element_object));
        console.log('tagged by', tags);

        var q = 'MERGE (element:Element {identifier:"'+element_object.identifier+'", name:"'+element_object.name+'", add_date:"'+element_object.add_date+'"})\n';
        var q2 = '';
        var q3 = '';
        for(var i=0; i<tags.length;i++){
            q2+= 'MERGE(tag'+i+':Tag {name:"'+tags[i]+'"})\n';
            q3+= 'MERGE(element)-[:TAGGED_WITH]->(tag'+i+')\n';
        }
        q += q2;
        q += q3;
        q += ";";



        console.log('query:', q);


        session
            .run(q)
            .then( function(result) {
                console.log('added element:',result);
                driver.close();
            })
            .catch( function(error) {
                console.log(error);
                // Close the driver when application exits
                driver.close();
            })

    }
}
  • 元素
    包含
    名称
    标识符
    添加日期
  • 具有标记名称的标记
  • 我的关系是:
    元素
    s被
    标记为
    标签
到目前为止,我下面可怕的小脚本创建了一个由3个查询组成的查询,这些查询首先创建
元素
,然后创建
标记
,然后将
元素
关联到
标记
,并执行它

我的脚本没有做的是:

[
    //0 - first time this element appears on the list
    {
        name       : "Name 1",
        identifier : "string0001",
        added_date : "1437013195",
        tags       : ["tag1", "tag2"]
    },
    //1 - same as 0 but the added_date is different and the name is different, an additional tag3 is present
    {
        name       : "Name 2",
        identifier : "string0001",
        added_date : "1437082145",
        tags       : ["tag1", "tag3"]
    },
    //3 - a second unique element but it uses the same tags as 0
    {
        name       : "Name 3",
        identifier : "string0002",
        added_date : "1358426363",
        tags       : ["tag1", "tag2"]
    },
    //4 - third unique element with a new tag tag4
    {
        name       : "Name 4",
        identifier : "string0003",
        added_date : "1422912783",
        tags       : ["tag1", "tag4"]
    },
    // 5 - same element as 4, it was added before 4, it's tagged less than 4
    {
        name       : "Name 4",
        identifier : "string0003",
        added_date : "1358426363",
        tags       : ["tag1"]
    }
]
var neo4j = require('neo4j-driver').v1;

// Create a driver instance, for the user neo4j with password neo4j.
// It should be enough to have a single driver per database per application.
var driver = neo4j.driver("bolt://localhost:7687", neo4j.auth.basic("neo4j", "123456"));

// Register a callback to know if driver creation was successful:
driver.onCompleted = function () {
    // proceed with using the driver, it was successfully instantiated
    console.log('successfully connected');
};

// Register a callback to know if driver creation failed.
// This could happen due to wrong credentials or database unavailability:
driver.onError = function (error) {
    console.log('Driver instantiation failed', error);
};

// Create a session to run Cypher statements in.
// Note: Always make sure to close sessions when you are done using them!
var session = driver.session();
//console.log(session);

var test = require('./test.json');
for ( var element in test ) {

    if (test.hasOwnProperty(element)) {
        var obj = test[element];
        var element_object = {name:'', identifier:'',add_date:''};
        var tags;
        for ( var prop in obj ) {
            if (obj.hasOwnProperty(prop)) {
                //console.log('obj.' + prop + ' = ' + obj[prop]);
                if (prop === 'tags') {
                    tags = obj[prop];
                } else {
                    element_object[prop] = obj[prop].replace(/["']/g, "\\\"");
                }
            }
        }
        console.log('gonna create this element', JSON.stringify(element_object));
        console.log('tagged by', tags);

        var q = 'MERGE (element:Element {identifier:"'+element_object.identifier+'", name:"'+element_object.name+'", add_date:"'+element_object.add_date+'"})\n';
        var q2 = '';
        var q3 = '';
        for(var i=0; i<tags.length;i++){
            q2+= 'MERGE(tag'+i+':Tag {name:"'+tags[i]+'"})\n';
            q3+= 'MERGE(element)-[:TAGGED_WITH]->(tag'+i+')\n';
        }
        q += q2;
        q += q3;
        q += ";";



        console.log('query:', q);


        session
            .run(q)
            .then( function(result) {
                console.log('added element:',result);
                driver.close();
            })
            .catch( function(error) {
                console.log(error);
                // Close the driver when application exits
                driver.close();
            })

    }
}
  • 合并
    元素
    仅使用标识符,它使用所有三个属性
    名称
    标识符
    添加日期
  • 它不会记录同一标识符是否有多个名称(例如,元素
    0
    1
    有两个不同的名称,并且可以存储一个名称数组:
    {name:“name 2”,标识符:“string0001”,添加的日期:“14370195”,所有名称:[“name 1”,“name 2”]}
    )。这并不是很重要,当我知道如何正确地链接查询时,我会处理这个问题
  • 同样,added_date属性也可以被合并:
    {name:“name 2”,identifier:“string0001”,added_date:“1437013195”,all_name:[“name 1”,“name 2”],all_added_dates:[“1437013195”,“1437082145”}
    一旦我学会了正确的链接,我将再次解决这个问题
  • 它不会捕获每个步骤中的错误
我的代码是:

[
    //0 - first time this element appears on the list
    {
        name       : "Name 1",
        identifier : "string0001",
        added_date : "1437013195",
        tags       : ["tag1", "tag2"]
    },
    //1 - same as 0 but the added_date is different and the name is different, an additional tag3 is present
    {
        name       : "Name 2",
        identifier : "string0001",
        added_date : "1437082145",
        tags       : ["tag1", "tag3"]
    },
    //3 - a second unique element but it uses the same tags as 0
    {
        name       : "Name 3",
        identifier : "string0002",
        added_date : "1358426363",
        tags       : ["tag1", "tag2"]
    },
    //4 - third unique element with a new tag tag4
    {
        name       : "Name 4",
        identifier : "string0003",
        added_date : "1422912783",
        tags       : ["tag1", "tag4"]
    },
    // 5 - same element as 4, it was added before 4, it's tagged less than 4
    {
        name       : "Name 4",
        identifier : "string0003",
        added_date : "1358426363",
        tags       : ["tag1"]
    }
]
var neo4j = require('neo4j-driver').v1;

// Create a driver instance, for the user neo4j with password neo4j.
// It should be enough to have a single driver per database per application.
var driver = neo4j.driver("bolt://localhost:7687", neo4j.auth.basic("neo4j", "123456"));

// Register a callback to know if driver creation was successful:
driver.onCompleted = function () {
    // proceed with using the driver, it was successfully instantiated
    console.log('successfully connected');
};

// Register a callback to know if driver creation failed.
// This could happen due to wrong credentials or database unavailability:
driver.onError = function (error) {
    console.log('Driver instantiation failed', error);
};

// Create a session to run Cypher statements in.
// Note: Always make sure to close sessions when you are done using them!
var session = driver.session();
//console.log(session);

var test = require('./test.json');
for ( var element in test ) {

    if (test.hasOwnProperty(element)) {
        var obj = test[element];
        var element_object = {name:'', identifier:'',add_date:''};
        var tags;
        for ( var prop in obj ) {
            if (obj.hasOwnProperty(prop)) {
                //console.log('obj.' + prop + ' = ' + obj[prop]);
                if (prop === 'tags') {
                    tags = obj[prop];
                } else {
                    element_object[prop] = obj[prop].replace(/["']/g, "\\\"");
                }
            }
        }
        console.log('gonna create this element', JSON.stringify(element_object));
        console.log('tagged by', tags);

        var q = 'MERGE (element:Element {identifier:"'+element_object.identifier+'", name:"'+element_object.name+'", add_date:"'+element_object.add_date+'"})\n';
        var q2 = '';
        var q3 = '';
        for(var i=0; i<tags.length;i++){
            q2+= 'MERGE(tag'+i+':Tag {name:"'+tags[i]+'"})\n';
            q3+= 'MERGE(element)-[:TAGGED_WITH]->(tag'+i+')\n';
        }
        q += q2;
        q += q3;
        q += ";";



        console.log('query:', q);


        session
            .run(q)
            .then( function(result) {
                console.log('added element:',result);
                driver.close();
            })
            .catch( function(error) {
                console.log(error);
                // Close the driver when application exits
                driver.close();
            })

    }
}
在我进行增强以支持所有名称和所有添加日期之后,它可能会如下所示:

[
    {
        name                      : "Name 2", //took the newest name in terms of added_date
        identifier                : "string0001",
        added_date                : "1437082145", //took the greatest added_date
        all_added_dates_and_names : [{'1437013195' : 'Name 1', '1437082145' : 'Name 2'}],
        tags                      : ["tag1", "tag2", "tag3"]
    },
    {
        name       : "Name 3",
        identifier : "string0002",
        added_date : "1358426363",
        tags       : ["tag1", "tag2"]
    },
    {
        name                      : "Name 4",
        identifier                : "string0003",
        added_date                : "1422912783", //took the greatest added_date
        all_added_dates_and_names : [{'1422912783' : 'Name 4', '1358426363' : 'Name 4'}],
        tags                      : ["tag1", "tag4"]
    }

]
我一直在研究这些,以找出最佳实践:

  • (让我知道这是否好,或者是否有更好的)
  • 我在这里很困惑
  • 我在这里查过了
我的期望与以下示例类似:


但是我希望它能够捕获每个步骤中的错误,并在for循环中添加想要参数化的add。

有一些复杂情况需要进行一些更改

第一个是您的迭代方法。这通常不适用于Cypher,也不建议使用字符串连接来构造查询。相反,我建议将输入集合参数化,并在查询中使用UNWIND将集合解压到行中,以便一次处理整个JSON

第二个复杂问题是您的all_added_dates_和_names属性。Neo4j当前不允许映射类型属性,也不允许映射类型属性集合。剩下的选项是将地图转换为字符串,或将每个添加的名称转换为具有附加日期属性的连接节点

您还需要尽可能轻松地构造查询,因为您需要使用集合联合函数

这里有一个应该可以使用的查询,不过您需要将
替换为。。。作为json
参考传入的json参数,
将$json作为行展开

with [
    {
        name       : "Name 1",
        identifier : "string0001",
        added_date : "1437013195",
        tags       : ["tag1", "tag2"]
    },
    {
        name       : "Name 2",
        identifier : "string0001",
        added_date : "1437082145",
        tags       : ["tag1", "tag3"]
    },
    {
        name       : "Name 3",
        identifier : "string0002",
        added_date : "1358426363",
        tags       : ["tag1", "tag2"]
    },
    {
        name       : "Name 4",
        identifier : "string0003",
        added_date : "1422912783",
        tags       : ["tag1", "tag4"]
    },
    {
        name       : "Name 4",
        identifier : "string0003",
        added_date : "1358426363",
        tags       : ["tag1"]
    }
] as json 

unwind json as row
with row.identifier as identifier, max(toInt(row.added_date)) as latestDate, 
 collect({date:toInt(row.added_date), name:row.name}) as allDatesAndNames, collect(row.tags) as allTags
// now union all collections of tags per entry with the same identifier
with identifier, latestDate, allDatesAndNames,
 reduce(tagSet = head(allTags), tags in allTags | apoc.coll.union(tagSet, tags)) as allTags
// now get the latest name corresponding with latest date
with identifier, latestDate, allDatesAndNames, allTags,
 head([entry in allDatesAndNames where entry.date = latestDate | entry.name]) as latestName
// data pre-processed, now start the merge
merge (el:Element{identifier:identifier})
set el.added_date = latestDate, el.name = latestName
foreach (entry in allDatesAndNames | 
 merge (el)-[:NAME_CHANGE]->(:NameChange{date:entry.date, name:entry.name}))
foreach (tagName in allTags | 
 merge (tag:Tag{name:tagName}) 
 merge (el)-[:TAGGED_WITH]->(tag))

如果在添加日期和名称时需要考虑图形中的日期和名称比您要添加的任何内容都要新,则可能只需要合并:NameChange节点(忽略查询中处理latestDate或latestName的任何部分),然后在最后找到带有最新日期的:NameChange节点,并从该节点设置date_added和name属性。

如果我创建
:NameChange
节点,如何使用Javascript+Cypher编写它?虽然我很感激被介绍给APOC程序——我确实看到了潜力,但我正在尝试使用JavaScript方法。迭代算法对于这个项目来说不是一个大问题,因为它会运行几次,数据也不会很大。我的首要任务是更加熟悉JS驱动程序。