cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Searching for all nodes with same property of Match

I am trying to find ALL other Customers who purchased products with ALL the same TYPE properties as C.

MATCH (c:customer{customer_id: '00006413d8573cd20ed7128e53b7b13819fe5cfc2d801fe7fc0f26dd8d65a85a'})-[]->(p:product)
WITH c, COLLECT(DISTINCT p.type) as types
MATCH (nc:customer)-[]->(np:product)
WHERE  all(t IN np.type WHERE t.type in types) 
RETURN DISTINCT c

I am getting this error:

Type mismatch: expected a map but was String("Vest top")

types is an array of Strings ["Vest top", "Pants",....] but I so should be np.type...?

1 ACCEPTED SOLUTION

Yes in deed, the order does matter. Given two sets A and B, the following predicate determines if A is a subset of B:

all(x in A where x in B),

As it tests each element of A to determine if it is in B. B can be larger and the predicate is still true.

Reversing the order determines if B is a subset of A

If you want equality, then add the constraint that the size of each is equal.

Your original post stated ‘other customers that purchased all of the customer’s product types.’ This sounds like other customer’s product types have to be a subset of the customer’s, which the query represents.

In reality, you want the other customers who purchased at least all of the customer’s product types. This implies the customer’s product types needs to be a subset of the other customer’s product types. So yes, you are correct. The query needs to test that each element in the customer’s list is in the other customer’s list.

 MATCH (c:customer{customer_id: '00006413d8573cd20ed7128e53b7b13819fe5cfc2d801fe7fc0f26dd8d65a85a'})-->(p:product)
WITH COLLECT(DISTINCT p.type) as types
MATCH (nc:customer)-->(np:product)
WITH types, nc, collect(np.type) as ntypes
WHERE all(t in types WHERE t in ntypes)
RETURN DISTINCT nc

Btw- the graph on the right of ‘what you got’ doesn’t seem to be a result of the first query, as there are circles representing the other customers that have elements not in the customer’s set. That looks more like the result of the following predicate. The equivalent of ‘do they intersect?’

any(x in ntypes where x in types)

@Cobra thanks for the tip.

View solution in original post

12 REPLIES 12

The value of np.type in the WHERE clause is a scalar; it needs to be a list. The following query should return the other customers who's purchased products all have the same product type as the customer.

MATCH (c:customer{customer_id: '00006413d8573cd20ed7128e53b7b13819fe5cfc2d801fe7fc0f26dd8d65a85a'})-->(p:product)
WITH COLLECT(DISTINCT p.type) as types
MATCH (nc:customer)-->(np:product)
WITH types, nc, collect(np.type) as ntypes
WHERE all(t IN ntypes WHERE t in types)
RETURN DISTINCT nc

Note, the above query allows the customer to have purchased more product types than the other customers. It only restricts the other customers to have their products be within the set of product types defined by the provided customer. If you want the customer and the other customer to have exactly the same set of property types, i.e. no more nor no less, then we can add one additional constraint.

MATCH (c:customer{customer_id: '00006413d8573cd20ed7128e53b7b13819fe5cfc2d801fe7fc0f26dd8d65a85a'})-->(p:product)
WITH COLLECT(DISTINCT p.type) as types
MATCH (nc:customer)-->(np:product)
WITH types, nc, collect(np.type) as ntypes
WHERE size(types) = size(ntypes)
AND all(t IN ntypes WHERE t in types)
RETURN DISTINCT nc

I think that should work.

THANK YOU! This worked great!

Awesome…glad to help.

To be 100% Clear, This is the goal:
3X_c_f_cfad5f6fbabf5f2412494e2f2fa01c80b8feb841.png

I believe that I originally had the WHERE all(t IN ntypes WHERE t in types) in the wrong order. Does this make sense? I believe it should be:

WHERE all(t IN types WHERE t in ntypes)

Hello @aaron.damiano

What is the format of the property type? A string or a list? Can you share an example?

Regards,
Cobra

1 String
"Blouse", "Sweater","Bikini top"

So each Product has only 1 type? The string only represent one type?

YES, each product has 1 type represented by 1 string.

The query of @glilienfield is good so what is the issue? Your first query cannot work since you need to collect types for each customer to then compare them with the one you want.

@glilienfield solved the original issue of the error.
However, when I ran the query I got:
3X_a_b_ab441041addf7579149415db956a17050111f936.png

I reversed the "WHERE all" statement and got the desired answer:

WHERE all(t IN types WHERE t in ntypes )

*I want to make sure that this post's final answer is what I was trying to achieve so that if anyone else reads in the future they get the output they expect.

Oh yeah indeed, let @glilienfield write the final query and you could accept it as an answer.

P.S: @glilienfield, you can use ``` before and after your code to make it easier to read and to copy paste 🙂

Yes in deed, the order does matter. Given two sets A and B, the following predicate determines if A is a subset of B:

all(x in A where x in B),

As it tests each element of A to determine if it is in B. B can be larger and the predicate is still true.

Reversing the order determines if B is a subset of A

If you want equality, then add the constraint that the size of each is equal.

Your original post stated ‘other customers that purchased all of the customer’s product types.’ This sounds like other customer’s product types have to be a subset of the customer’s, which the query represents.

In reality, you want the other customers who purchased at least all of the customer’s product types. This implies the customer’s product types needs to be a subset of the other customer’s product types. So yes, you are correct. The query needs to test that each element in the customer’s list is in the other customer’s list.

 MATCH (c:customer{customer_id: '00006413d8573cd20ed7128e53b7b13819fe5cfc2d801fe7fc0f26dd8d65a85a'})-->(p:product)
WITH COLLECT(DISTINCT p.type) as types
MATCH (nc:customer)-->(np:product)
WITH types, nc, collect(np.type) as ntypes
WHERE all(t in types WHERE t in ntypes)
RETURN DISTINCT nc

Btw- the graph on the right of ‘what you got’ doesn’t seem to be a result of the first query, as there are circles representing the other customers that have elements not in the customer’s set. That looks more like the result of the following predicate. The equivalent of ‘do they intersect?’

any(x in ntypes where x in types)

@Cobra thanks for the tip.