I'm using NodeJS 10.16.2, Neo4j 3.5.6, neo4j-driver v1, Express, EJS
My goal is to create a relationship of either a 1:1 or 1:Many for objects that previously exist in a Neo4j datastore. Example: Create (b:Beer)-[:BREWED_WITH]->(h:Hop). This relationship is created for either 1 beer and 1 hop, or 1 beer and multiple selected hops (the code below will explain more). At this point in time, the 1 Beer to 1 Hop works no problem, but the 1 Beer to Many Hops does not work.
Here are all the necessary code parts...
server.js This code gets the data...
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 This code displays the data in a form...
<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 This code contains the query that posts to the Neo4j database...
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)
};
});
I realize there are many different ways to Create relationships for existing nodes in Neo4j. The above query is the drop dead easiest.
What Works
If I select 1 Beer and 1 Hop from the form and Submit, the relationship is created in Neo4j.
What Doesn't Work
If I select 1 Beer and 2+ Hops from the form and Submit, the relationships are not created in Neo4j. Please note that running this neo4j query
Match (b:Beer {name: 'Disco Wolf'})
Match (h:Hop)
Where h.name IN ['Citra', 'Strata', 'Idaho7']
Create (b)-[:BREWED_WITH]->(h)
Return b,h
directly in the Neo4j Browser works to make the multiple relationships, BUT it does not work from my app.
I have also tried a FOREACH statement with my Neo4j query,
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
it also does not work in my app (but is a viable query in Neo Browser).
In both cases,console.log(hopname);
will show either the 1 hop as a single name: Galaxy, or the multiple hops in an array:
[ 'Citra', 'Strata', 'Idaho7' ].
Any idea how I can get the 1 Beer to Many Hops relationships created?
Many Thanks,
r