Skip to content

Conversation

@khoale88
Copy link
Contributor

@khoale88 khoale88 commented Nov 3, 2025

  • must be in the syntax A EXISTS {MATCH (A)... RETURN ID(A)}

sample:
qry = """
MATCH (A)
where A EXISTS {
MATCH (A) --> (B)
where B EXISTS {
MATCH (B)
where B.age > 40
return ID(B)
}
return ID(A)
}
RETURN ID(A)
"""

@codspeed-hq
Copy link

codspeed-hq bot commented Nov 3, 2025

CodSpeed Performance Report

Merging #83 will not alter performance

Comparing khoale88:subquery (5e62dd0) with master (ff38a9f)

Summary

✅ 81 untouched

@khoale88 khoale88 force-pushed the subquery branch 2 times, most recently from dac2001 to 4b6e8ba Compare November 3, 2025 17:16
@khoale88
Copy link
Contributor Author

khoale88 commented Nov 3, 2025

This will be one of the ambitious PR. In order to support subquery, I restructure the code base a little bit

  • GrandCypherTransformer will remain primarily as a transformer. However, the actual matching logic now is moved to GrandCypherExecutor
  • GrandCypherExecutor contains all the matching logic, but not the transformer/parser
  • The sub query at the moment is achieved by another "nested" GrandCypherExecutor in the where clause.
  • the EXISTS is implement very limited now. The EXISTS will call "nested" executor and compare the result "existings". I will need to take a look on how neo4j supports it and change the implementation later.

In general, I think subquery will have better performance in many case. One case I can think of is

Match p = (A:Node) -[:depend*1..10]->(B:Node {name="BNode") <-[:depend*1..10]- (C:Node)
where p EXISTS {
    (A:Node) -[:version*1..10]->(C:Node)
}
return A, C

I suppose, the subquery only need to search on a subset from the main query via hints. Of course, I haven't reached this stage yet.

P.S. I think the code base needs better concepts, or it will soon go out of control.

@khoale88
Copy link
Contributor Author

khoale88 commented Nov 3, 2025

The logic to enter/exit subquery stack are:

  • when encounter MultiMatch the second time, it's a subquery,
  • When we encounter SubQuery then it's time to back to the parent query.

@j6k4m8
Copy link
Member

j6k4m8 commented Nov 4, 2025

This is so exciting!! And more broadly I'm really excited about your refactor,

P.S. I think the code base needs better concepts, or it will soon go out of control.

This is SO TRUE. I started this repository before I really understood how to think about and organize Lark projects, and... well, I haven't gotten much better since then :) Would love to discuss together and hear what you're thinking, I would love for this to have dramatically less complexity and spaghetti-code than I gave it to start!!

@khoale88 khoale88 force-pushed the subquery branch 2 times, most recently from fa3627f to cc63171 Compare November 4, 2025 15:19
sample:
qry = """
    MATCH (A)
    where A EXISTS {
        MATCH (A) --> (B)
        where B EXISTS {
            MATCH (B)
            where B.age > 40
        }
    }
    RETURN ID(A)
 """
@khoale88
Copy link
Contributor Author

khoale88 commented Nov 4, 2025

I improved

  • the subquery EXISTS, now it doesn't requires a CNAME, and RETURN.
  • The EXISTS works on hints from the direct parent query match
  • GrandCypherExecutor now store parent_executor, and child_executors and _level.

@khoale88
Copy link
Contributor Author

khoale88 commented Nov 4, 2025

I think I just give support for negated edge using subquery

    MATCH (A) --> (B)
    where  NOT EXISTS {
        MATCH (A) -[r:XY]-> (B)
        where r.name = "XY"
        return A, r, B
    }
    RETURN ID(A), ID(B)

However, It doesn't work with node label query, It will take me sometime to debug

    MATCH (A) --> (B)
    where  NOT EXISTS {
        MATCH (A) -[:XY]-> (B)
        return A, r, B
    }
    RETURN ID(A), ID(B)

@khoale88
Copy link
Contributor Author

khoale88 commented Nov 5, 2025

I found the problem, it's the #84
I am able to handle it by double-checking node/edge matches, which are hinted.

now negated edge in subquery works just fine.

- check if node and edge from hints are valid matches
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants