Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
03-29-2022 11:30 AM
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...?
Solved! Go to Solution.
03-30-2022 04:39 AM
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.
03-29-2022 12:15 PM
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.
03-29-2022 01:17 PM
THANK YOU! This worked great!
03-29-2022 01:23 PM
Awesome…glad to help.
03-30-2022 02:15 AM
To be 100% Clear, This is the goal:
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)
03-30-2022 02:23 AM
Hello @aaron.damiano
What is the format of the property type
? A string or a list? Can you share an example?
Regards,
Cobra
03-30-2022 02:26 AM
1 String
"Blouse", "Sweater","Bikini top"
03-30-2022 02:28 AM
So each Product has only 1 type? The string only represent one type?
03-30-2022 02:32 AM
YES, each product has 1 type represented by 1 string.
03-30-2022 02:35 AM
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.
03-30-2022 02:44 AM
@glilienfield solved the original issue of the error.
However, when I ran the query I got:
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.
03-30-2022 02:51 AM
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 🙂
03-30-2022 04:39 AM
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.
All the sessions of the conference are now available online