0
votes

I'm trying to do some basic similarity search in a neo4j database. It looks something like this:

begin
create (_1:`Article` {`name`:"Bow", `weight`:"20"})
create (_2:`Article` {`name`:"Shield", `weight`:"30"})
create (_3:`Article` {`name`:"Knife", `weight`:"40"})
create (_4:`Article` {`name`:"Sword", `weight`:"50"})
create (_5:`Article` {`name`:"Helmet", `weight`:"15"})
create (_6:`Order` {`customer`:"Peter"})
create (_7:`Order` {`customer`:"Paul"})
create (_8:`Order` {`customer`:"Mary"})
create (_9:`Accessory` {`name`:"Arrow",`type`:"optional", `weight`:"2"})
create _6-[:`CONTAINS` {`timestamp`:"1413204480"}]->_1
create _6-[:`CONTAINS` {`timestamp`:"1413204480"}]->_2
create _6-[:`CONTAINS` {`timestamp`:"1413204480"}]->_3
create _7-[:`CONTAINS` {`timestamp`:"1413204480"}]->_1
create _7-[:`CONTAINS` {`timestamp`:"1413204480"}]->_4
create _8-[:`CONTAINS` {`timestamp`:"1413204480"}]->_5
create _9-[:`BELONGS_TO` {`timestamp`:"1413204480"}]->_1
;
commit

Pretty pointless database, I know. Sole reason for it is this post.

When a new order comes in, I need to find out, whether or not similar orders have already been placed. Similar means: existing or new customer and same products. The hard part is: I need the sum of the weight of all (directly or indirectly) contained nodes.

Here's what I have:

START n=node(*)
MATCH p1 = (a:Order)-[*]->n, p2 = (b:Order)-[*]->m
WHERE a<>b AND n.name = m.name
RETURN reduce (sum="", x in p2 | sum+x.weight) limit 25;

However, it seems that p2 is not the right thing to aggregate across. Cypher expects a collection and not a path.

Truly sorry for this newbie post, but rest assured: I am a very grateful newbie. Thanks! rene

1
you can just use reduce(sum=0, x IN nodes(p2) | sum + x.weight)Michael Hunger
You should probably also use relationship-types in your paths and not unbounded paths.Michael Hunger
Hi Michael, relationship types are on the to-do list for my project. And paths will in the end be no longer than maybe 5 or so. At this stage, I don't really care about the path lenghts, I just want to get this sum straight.rene
where oh where is the documentation for the reduce function?Monica Heddneck

1 Answers

2
votes

In your query, it looks like you are pretending that p2 is the path of you new order. I presume that in your actual query you will be binding b to a specific node. Also, your timestamps and weights should have numeric values (without the quotes).

This query will return the total weight of the "new" path. Is this what you wanted?

MATCH p1 =(a:Order)-[*]->n, p2 =(b:Order)-[*]->m
WHERE a<>b AND n.name = m.name
WITH p2, collect(m) AS ms
RETURN reduce(sum=0, x IN ms | sum+x.weight)
LIMIT 25;

By the way, START n=node(*) is superfluous. It is the same as using an unbound n.

See this console.