【问题标题】:Neo4j NodeJS - Create Optional 1 to Many Relationships for Existing NodesNeo4j NodeJS - 为现有节点创建可选的一对多关系
【发布时间】:2020-09-10 05:11:11
【问题描述】:

我正在使用 NodeJS 10.16.2、Neo4j 3.5.6、neo4j-driver v1、Express、EJS

我的目标是为之前存在于 Neo4j 数据存储中的对象创建 1:1 或 1:Many 的关系。示例:创建 (b:Beer)-[:BREWED_WITH]->(h:Hop)。这种关系是针对 1 杯啤酒和 1 杯啤酒花,或 1 杯啤酒和多个选定的啤酒花酒花创建的(下面的代码将进行更多说明)。此时,1 Beer to 1 Hop 没有问题,但 1 Beer to Many Hop 不起作用。

这里是所有必要的代码部分...

server.js 此代码获取数据...

app.get('/', async (req, res) => {
  try { 
    //paring this Beer example down from its usual
    const beerResult = await session.run(`MATCH (b:Beer) RETURN b`); 
    const beerArr = beerResult.records.map(({_fields}) => {
      return {name:_fields[0]};
    });

    const hopResult = await session.run('MATCH(h:Hop) RETURN h Order By h.name ASC');
    const hopArr = hopResult.records.map(({_fields}) => {
      const {identity, properties} = _fields[0];
      return {id: identity.low, name: properties.name};
    });

    res.render('index', {
      beer: beerArr,
      hop:hopArr
    });
  } catch(e) {
    console.log("Something went wrong", e)
  }
});

index.ejs 此代码以表格形式显示数据...

     <h2>Beer->Hop</h2>
          <form  method="post" action="/beerhop/add">
               <label>Beer Name</label><br>
               <select class="form-control" type="text" name="beername">
                    <% beer.forEach(function(beer){ %>
                         <option><%= beer.name %></option>
                    <% }) %>
               </select><br>

               <label>Hop Name</label><br>
               <select class="form-control" type="text" name="hopname" multiple>
                    <% hop.forEach(function(hop){ %>
                         <option><%= hop.name %></option>
                    <% }) %>
                </select><br>                
                <input class="button" type="submit" value="Submit">
          </form>

server.js 此代码包含发布到 Neo4j 数据库的查询...

app.post('/beerhop/add',async (req, res) => {
  const {beername, hopname} = req.body;
  try {
    const result = await session.run(`Match (b:Beer {name: $beernameParam})
                                      Match (h:Hop {name: $hopnameParam})
                                      Create (h)<-[r:BREWED_WITH]-(b)
                                      Return h.name,b.name`, 
                                      {hopnameParam:hopname, beernameParam:beername});
    if (result) {
      res.redirect('/');
      console.log(hopname);
      session.close()
    }
  } catch (e) {
    console.log("Something went wrong", e)
  };
});

我意识到在 Neo4j 中为现有节点创建关系有很多不同的方法。上面的查询是最简单的。

什么有效

如果我从表单中选择 1 Beer 和 1 Hop 并提交,则关系在 Neo4j 中创建。

什么不起作用

如果我从表单中选择 1 Beer 和 2+ Hops 并提交,则不会在 Neo4j 中创建关系。 请注意,运行这个 neo4j 查询

Match (b:Beer {name: 'Disco Wolf'})
Match (h:Hop)
Where h.name IN ['Citra', 'Strata', 'Idaho7']
Create (b)-[:BREWED_WITH]->(h)
Return b,h

直接在 Neo4j 浏览器中可以建立多个关系,但它不适用于我的应用程序。

我还用我的 Neo4j 查询尝试了 FOREACH 语句,

Match (b:Beer {name: $beernameParam}), (h:Hop {name: $hopnameParam})
With b as beer, collect(h) AS hops
FOREACH (hop IN hops | Create (beer)-[:BREWED_WITH]->(hop))
Return beer,hops

它在我的应用程序中也不起作用(但在 Neo 浏览器中是一个可行的查询)。

在这两种情况下,console.log(hopname); 都会将 1 跃点显示为单个名称:Galaxy,或者将多个跃点显示为数组: [ 'Citra', 'Strata', 'Idaho7' ].

知道如何创建 1 Beer to Many Hops 关系吗?

非常感谢,

r

【问题讨论】:

    标签: node.js express neo4j


    【解决方案1】:

    您可以确保始终将一个 列表 跃点名称传递给查询:

    ...
    const result = await session.run(`MATCH (b:Beer), (h:Hop)
                                      WHERE b.name = $beername AND h.name IN $hopnames
                                      CREATE (h)<-[r:BREWED_WITH]-(b)
                                      RETURN h.name, b.name`, 
                                      {hopnames: Array.isArray(hopname) ? hopname : [hopname], beername: beername});
    ...
    

    顺便说一句,您可能希望使用MERGE 而不是CREATE 以避免创建重复关系。

    【讨论】:

    猜你喜欢
    • 2016-05-01
    • 1970-01-01
    • 2014-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-25
    相关资源
    最近更新 更多