Skip to content

Question on MATCH query (cartesian product) #249

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
andrija78 opened this issue Nov 22, 2018 · 5 comments
Closed

Question on MATCH query (cartesian product) #249

andrija78 opened this issue Nov 22, 2018 · 5 comments
Assignees
Labels

Comments

@andrija78
Copy link

Hi,

I'm testing some MATCH queries, and found weird behavior with Cartesian product.
Am I doing something wrong, my understanding is wrong, or is this a bug?

BTW - I'm testing this since multiple match statements are not supported yet - something like:

MATCH (a:person {name:"name A"})
MATCH (b:city {name:"city 1"})
CREATE (a)-[:visited]->(:b)

I have a simple graph: 4 persons, 3 cities. Persons A, B and C visited 2 cities. Person D visited all 3 cities.

CREATE (:person{name:'name A', last_name:'last A'})
CREATE (:person{name:'name B', last_name:'last B'})
CREATE (:person{name:'name C', last_name:'last C'})
CREATE (:person{name:'name D', last_name:'last D'})

CREATE (:city{name:'city 1', country:'country 1'})
CREATE (:city{name:'city 2', country:'country 2'})
CREATE (:city{name:'city 3', country:'country 3'})


MATCH (a:person), (b:city) WHERE (a.name = 'name A' AND b.name='city 1') CREATE (a)-[:visited]->(b)
MATCH (a:person), (b:city) WHERE (a.name = 'name A' AND b.name='city 2') CREATE (a)-[:visited]->(b)


MATCH (a:person), (b:city) WHERE (a.name = 'name B' AND b.name='city 1') CREATE (a)-[:visited]->(b)
MATCH (a:person), (b:city) WHERE (a.name = 'name B' AND b.name='city 3') CREATE (a)-[:visited]->(b)


MATCH (a:person), (b:city) WHERE (a.name = 'name C' AND b.name='city 2') CREATE (a)-[:visited]->(b)
MATCH (a:person), (b:city) WHERE (a.name = 'name C' AND b.name='city 3') CREATE (a)-[:visited]->(b)

MATCH (a:person), (b:city) WHERE (a.name = 'name D' AND b.name='city 1') CREATE (a)-[:visited]->(b)
MATCH (a:person), (b:city) WHERE (a.name = 'name D' AND b.name='city 2') CREATE (a)-[:visited]->(b)
MATCH (a:person), (b:city) WHERE (a.name = 'name D' AND b.name='city 3') CREATE (a)-[:visited]->(b)

These 2 queries have a result that does not look correct:

Here I'm expecting to get all 12 visits, joined with 3 cities - 36 rows in total.
But only person D gets cartesian right with all 3 cities; persons A, B and C only get matched with city 1.
MATCH (a:person)-[:visited]->(b:city), (c:city) return a,b,c
[last A, name A, country 1, city 1, country 1, city 1]
[last A, name A, country 2, city 2, country 1, city 1]

[last B, name B, country 1, city 1, country 1, city 1]
[last B, name B, country 3, city 3, country 1, city 1]

[last C, name C, country 2, city 2, country 1, city 1]
[last C, name C, country 3, city 3, country 1, city 1]

[last D, name D, country 1, city 1, country 1, city 1]
[last D, name D, country 2, city 2, country 1, city 1]
[last D, name D, country 3, city 3, country 1, city 1]
[last D, name D, country 1, city 1, country 2, city 2]
[last D, name D, country 2, city 2, country 2, city 2]
[last D, name D, country 3, city 3, country 2, city 2]
[last D, name D, country 1, city 1, country 3, city 3]
[last D, name D, country 2, city 2, country 3, city 3]
[last D, name D, country 3, city 3, country 3, city 3]

Similarly, when applying additional filter:
MATCH (a:person)-[:visited]->(b:city), (c:city) where b.name=c.name return a,b,c
[last A, name A, country 1, city 1, country 1, city 1]
[last B, name B, country 1, city 1, country 1, city 1]
[last D, name D, country 1, city 1, country 1, city 1]
[last B, name B, country 3, city 3, country 3, city 3]
[last C, name C, country 3, city 3, country 3, city 3]
[last D, name D, country 3, city 3, country 3, city 3]

@swilly22
Copy link
Contributor

Hi @andrija78
You're right RedisGraph behaviour isn't correct here, and it seems like indeed it is a problem with the cartesian product.

But one think to notice, this graph contains 9 edges, and so each edge will appear 4 times and so I would expect 27 results,

when reversing the order: MATCH (c:city), (a:person)-[:visited]->(b:city) return a,b,c
we do get the expected result-set.

Thank you for reporting!

@swilly22 swilly22 self-assigned this Nov 25, 2018
@swilly22 swilly22 added the bug label Nov 25, 2018
@andrija78
Copy link
Author

You are right; 27 rows are expected. I ran a different test before, I mixed up the numbers.

When can we expect support for multiple MATCH queries - so I can avoid Cartesian product like this:

MATCH (a:person {name:"name A"})
MATCH (b:city {name:"city 1"})
CREATE (a)-[:visited]->(:b)

@swilly22
Copy link
Contributor

I'm not sure exactly when multiple MATCH clauses will be supported, as we're finalising our roadmap these days, I can say that this is defiantly on the roadmap, I think it wouldn't take too long to implement,
But please notice that multiple MATCH clauses translate into Cartesian product when there's no shared entity between the two, executing:

MATCH (a:person {name:"name A"})
MATCH (b:city {name:"city 1"})

Is the as executing:

MATCH (a:person {name:"name A"}), (b:city {name:"city 1"})

Unless I'm missing something,
I'll update here with a better estimation, as soon as out roadmap is finalised.

@swilly22
Copy link
Contributor

@andrija78 just pushed a fix, could you please verify.

@andrija78
Copy link
Author

This was fast! Thanks!
Got the right results:

MATCH (a:person)-[:visited]->(b:city), (c:city) return a,b,c
[last A, name A, country 1, city 1, country 1, city 1]
[last A, name A, country 2, city 2, country 1, city 1]
[last B, name B, country 1, city 1, country 1, city 1]
[last B, name B, country 3, city 3, country 1, city 1]
[last C, name C, country 2, city 2, country 1, city 1]
[last C, name C, country 3, city 3, country 1, city 1]
[last D, name D, country 1, city 1, country 1, city 1]
[last D, name D, country 2, city 2, country 1, city 1]
[last D, name D, country 3, city 3, country 1, city 1]
[last A, name A, country 1, city 1, country 2, city 2]
[last A, name A, country 2, city 2, country 2, city 2]
[last B, name B, country 1, city 1, country 2, city 2]
[last B, name B, country 3, city 3, country 2, city 2]
[last C, name C, country 2, city 2, country 2, city 2]
[last C, name C, country 3, city 3, country 2, city 2]
[last D, name D, country 1, city 1, country 2, city 2]
[last D, name D, country 2, city 2, country 2, city 2]
[last D, name D, country 3, city 3, country 2, city 2]
[last A, name A, country 1, city 1, country 3, city 3]
[last A, name A, country 2, city 2, country 3, city 3]
[last B, name B, country 1, city 1, country 3, city 3]
[last B, name B, country 3, city 3, country 3, city 3]
[last C, name C, country 2, city 2, country 3, city 3]
[last C, name C, country 3, city 3, country 3, city 3]
[last D, name D, country 1, city 1, country 3, city 3]
[last D, name D, country 2, city 2, country 3, city 3]
[last D, name D, country 3, city 3, country 3, city 3]

MATCH (a:person)-[:visited]->(b:city), (c:city) where b.name=c.name return a,b,c
[last A, name A, country 1, city 1, country 1, city 1]
[last B, name B, country 1, city 1, country 1, city 1]
[last D, name D, country 1, city 1, country 1, city 1]
[last A, name A, country 2, city 2, country 2, city 2]
[last C, name C, country 2, city 2, country 2, city 2]
[last D, name D, country 2, city 2, country 2, city 2]
[last B, name B, country 3, city 3, country 3, city 3]
[last C, name C, country 3, city 3, country 3, city 3]
[last D, name D, country 3, city 3, country 3, city 3]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants