Skip to content

Commit

Permalink
feat(interactive): Support optional expand in GIE Runtime (#4213)
Browse files Browse the repository at this point in the history
<!--
Thanks for your contribution! please review
https://github.com/alibaba/GraphScope/blob/main/CONTRIBUTING.md before
opening an issue.
-->

## What do these changes do?

<!-- Please give a short brief about these changes. -->

As titled. Support optional edge expand, and support dealing with null
value in expand, getv, unfold.

## Related issue number

<!-- Are there any issues opened that will be resolved by merging this
change? -->

#3668
  • Loading branch information
BingqingLyu authored Sep 19, 2024
1 parent b6d413c commit 36313cf
Show file tree
Hide file tree
Showing 9 changed files with 530 additions and 58 deletions.
8 changes: 8 additions & 0 deletions docs/interactive_engine/neo4j/supported_cypher.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ MATCH (a) -[]-> () -[]-> (b) # second MATCH clause
RETURN a, b;
```

Besides, we support `OPTIONAL MATCH`. For example,
the following query can be supported:
```Cypher
MATCH (a) -[]-> (b)
Optional MATCH (b) -[]-> (c)
RETURN a, b, c;
```

| Keyword | Comments | Supported | Todo
|:---|---|:---:|:---|
| MATCH | only one Match clause is allowed | <input type="checkbox" disabled checked /> |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,14 @@ public static QueryContext get_simple_match_query_16_test() {
List<String> expected = Arrays.asList("Record<{$f0: 325593}>");
return new QueryContext(query, expected);
}

public static QueryContext get_simple_match_query_17_test() {
String query =
"MATCH (person:PERSON {id: 26388279067534})<-[:HASCREATOR]-(message: POST |"
+ " COMMENT)\n"
+ "OPTIONAL MATCH (message: POST | COMMENT)<-[like:LIKES]-(liker:PERSON)\n"
+ " Return count(person);";
List<String> expected = Arrays.asList("Record<{$f0: 851}>");
return new QueryContext(query, expected);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ public void run_simple_match_16_test() {
Assert.assertEquals(testQuery.getExpectedResult().toString(), result.list().toString());
}

@Test
public void run_simple_match_17_test() {
assumeTrue("pegasus".equals(System.getenv("ENGINE_TYPE")));
QueryContext testQuery = SimpleMatchQueries.get_simple_match_query_17_test();
Result result = session.run(testQuery.getQuery());
Assert.assertEquals(testQuery.getExpectedResult().toString(), result.list().toString());
}

@AfterClass
public static void afterClass() {
if (session != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl GraphPath {
let entry = entry.into();
let id = entry.id();
GraphPath::SimpleEndV((entry, vec![id], 1))
},
}
pb::path_expand::PathOpt::Trail => GraphPath::TrailAllPath(vec![entry.into()]),
},
pb::path_expand::ResultOpt::AllV | pb::path_expand::ResultOpt::AllVE => match path_opt {
Expand Down Expand Up @@ -167,21 +167,27 @@ impl GraphPath {

pub fn get_path_start(&self) -> Option<&VertexOrEdge> {
match self {
GraphPath::AllPath(ref p) | GraphPath::SimpleAllPath(ref p) | GraphPath::TrailAllPath(ref p) => p.first(),
GraphPath::AllPath(ref p)
| GraphPath::SimpleAllPath(ref p)
| GraphPath::TrailAllPath(ref p) => p.first(),
GraphPath::EndV(_) | GraphPath::SimpleEndV(_) => None,
}
}

pub fn get_path_end(&self) -> &VertexOrEdge {
match self {
GraphPath::AllPath(ref p) | GraphPath::SimpleAllPath(ref p) | GraphPath::TrailAllPath(ref p) => p.last().unwrap(),
GraphPath::AllPath(ref p)
| GraphPath::SimpleAllPath(ref p)
| GraphPath::TrailAllPath(ref p) => p.last().unwrap(),
GraphPath::EndV((ref e, _)) | GraphPath::SimpleEndV((ref e, _, _)) => e,
}
}

pub fn get_path_end_mut(&mut self) -> &mut VertexOrEdge {
match self {
GraphPath::AllPath(ref mut p) | GraphPath::SimpleAllPath(ref mut p) | GraphPath::TrailAllPath(ref mut p) => p.last_mut().unwrap(),
GraphPath::AllPath(ref mut p)
| GraphPath::SimpleAllPath(ref mut p)
| GraphPath::TrailAllPath(ref mut p) => p.last_mut().unwrap(),
GraphPath::EndV((ref mut e, _)) | GraphPath::SimpleEndV((ref mut e, _, _)) => e,
}
}
Expand Down Expand Up @@ -233,15 +239,19 @@ impl GraphPath {
// pop the last element from the path, and return the element.
pub fn pop(&mut self) -> Option<VertexOrEdge> {
match self {
GraphPath::AllPath(ref mut p) | GraphPath::SimpleAllPath(ref mut p) | GraphPath::TrailAllPath(ref mut p) => p.pop(),
GraphPath::AllPath(ref mut p)
| GraphPath::SimpleAllPath(ref mut p)
| GraphPath::TrailAllPath(ref mut p) => p.pop(),
GraphPath::EndV(_) | GraphPath::SimpleEndV(_) => None,
}
}

// reverse the path.
pub fn reverse(&mut self) {
match self {
GraphPath::AllPath(ref mut p) | GraphPath::SimpleAllPath(ref mut p) | GraphPath::TrailAllPath(ref mut p) => {
GraphPath::AllPath(ref mut p)
| GraphPath::SimpleAllPath(ref mut p)
| GraphPath::TrailAllPath(ref mut p) => {
p.reverse();
}
GraphPath::EndV(_) | GraphPath::SimpleEndV(_) => {}
Expand All @@ -251,15 +261,19 @@ impl GraphPath {
// get the element ids in the path, including both vertices and edges.
pub fn get_elem_ids(&self) -> Vec<ID> {
match self {
GraphPath::AllPath(p) | GraphPath::SimpleAllPath(p) | GraphPath::TrailAllPath(p) => p.iter().map(|e| e.id()).collect(),
GraphPath::AllPath(p) | GraphPath::SimpleAllPath(p) | GraphPath::TrailAllPath(p) => {
p.iter().map(|e| e.id()).collect()
}
GraphPath::EndV((e, _)) | GraphPath::SimpleEndV((e, _, _)) => vec![e.id()],
}
}

// get the element labels in the path, including both vertices and edges.
pub fn get_elem_labels(&self) -> Vec<Option<LabelId>> {
match self {
GraphPath::AllPath(p) | GraphPath::SimpleAllPath(p) | GraphPath::TrailAllPath(p) => p.iter().map(|e| e.label()).collect(),
GraphPath::AllPath(p) | GraphPath::SimpleAllPath(p) | GraphPath::TrailAllPath(p) => {
p.iter().map(|e| e.label()).collect()
}
GraphPath::EndV((e, _)) | GraphPath::SimpleEndV((e, _, _)) => vec![e.label()],
}
}
Expand Down Expand Up @@ -409,10 +423,10 @@ impl PartialEq for GraphPath {
| (GraphPath::AllPath(p1), GraphPath::SimpleAllPath(p2))
| (GraphPath::AllPath(p1), GraphPath::TrailAllPath(p2))
| (GraphPath::SimpleAllPath(p1), GraphPath::AllPath(p2))
| (GraphPath::SimpleAllPath(p1), GraphPath::SimpleAllPath(p2))
| (GraphPath::SimpleAllPath(p1), GraphPath::TrailAllPath(p2))
| (GraphPath::TrailAllPath(p1), GraphPath::AllPath(p2))
| (GraphPath::TrailAllPath(p1), GraphPath::SimpleAllPath(p2))
| (GraphPath::SimpleAllPath(p1), GraphPath::SimpleAllPath(p2))
| (GraphPath::SimpleAllPath(p1), GraphPath::TrailAllPath(p2))
| (GraphPath::TrailAllPath(p1), GraphPath::AllPath(p2))
| (GraphPath::TrailAllPath(p1), GraphPath::SimpleAllPath(p2))
| (GraphPath::TrailAllPath(p1), GraphPath::TrailAllPath(p2)) => p1.eq(p2),
(GraphPath::EndV((p1, _)), GraphPath::EndV((p2, _)))
| (GraphPath::EndV((p1, _)), GraphPath::SimpleEndV((p2, _, _)))
Expand Down Expand Up @@ -571,7 +585,9 @@ impl TryFrom<result_pb::GraphPath> for GraphPath {
impl Hash for GraphPath {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
GraphPath::AllPath(p) | GraphPath::SimpleAllPath(p) | GraphPath::TrailAllPath(p) => p.hash(state),
GraphPath::AllPath(p) | GraphPath::SimpleAllPath(p) | GraphPath::TrailAllPath(p) => {
p.hash(state)
}
GraphPath::EndV((e, _)) | GraphPath::SimpleEndV((e, _, _)) => e.hash(state),
}
}
Expand Down
Loading

0 comments on commit 36313cf

Please sign in to comment.