Skip to content

Commit 96d5093

Browse files
[GIE Compiler] Parse Label Id to Name in label Operator (#2928)
<!-- Thanks for your contribution! please review https://github.com/alibaba/GraphScope/blob/main/CONTRIBUTING.md before opening an issue. --> ## What do these changes do? as titled. <!-- Please give a short brief about these changes. --> ## Related issue number <!-- Are there any issues opened that will be resolved by merging this change? --> Fixes #2777 Co-authored-by: Longbin Lai <[email protected]>
1 parent 34b3650 commit 96d5093

File tree

10 files changed

+466
-182
lines changed

10 files changed

+466
-182
lines changed

interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/InterOpCollectionBuilder.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ public InterOpCollection build() throws OpArgIllegalException, UnsupportedStepEx
7373
|| Utils.equalClass(step, MeanGlobalStep.class)) {
7474
opList.add(StepTransformFactory.AGGREGATE_STEP.apply(step));
7575
} else if (Utils.equalClass(step, PropertiesStep.class)
76-
|| Utils.equalClass(step, PropertyMapStep.class)) {
76+
|| Utils.equalClass(step, PropertyMapStep.class)
77+
|| Utils.equalClass(step, LabelStep.class)
78+
|| Utils.equalClass(step, IdStep.class)) {
7779
opList.add(StepTransformFactory.VALUES_STEP.apply(step));
7880
} else if (Utils.equalClass(step, IsStep.class)) {
7981
opList.add(StepTransformFactory.IS_STEP.apply(step));
@@ -135,10 +137,6 @@ public InterOpCollection build() throws OpArgIllegalException, UnsupportedStepEx
135137
opList.add(StepTransformFactory.SUBGRAPH_STEP.apply(step));
136138
} else if (Utils.equalClass(step, IdentityStep.class)) {
137139
opList.add(StepTransformFactory.IDENTITY_STEP.apply(step));
138-
} else if (Utils.equalClass(step, IdStep.class)) {
139-
opList.add(StepTransformFactory.ID_STEP.apply(step));
140-
} else if (Utils.equalClass(step, LabelStep.class)) {
141-
opList.add(StepTransformFactory.LABEL_STEP.apply(step));
142140
} else if (Utils.equalClass(step, ConstantStep.class)) {
143141
opList.add(StepTransformFactory.CONSTANT_STEP.apply(step));
144142
} else {

interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/suite/standard/IrGremlinQueryTest.java

+89-1
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,16 @@
2626
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
2727
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
2828
import org.apache.tinkerpop.gremlin.structure.Column;
29+
import org.apache.tinkerpop.gremlin.structure.Edge;
30+
import org.apache.tinkerpop.gremlin.structure.T;
2931
import org.apache.tinkerpop.gremlin.structure.Vertex;
3032
import org.junit.Assert;
3133
import org.junit.Test;
3234

33-
import java.util.*;
35+
import java.util.Arrays;
36+
import java.util.Collections;
37+
import java.util.List;
38+
import java.util.Map;
3439

3540
public abstract class IrGremlinQueryTest extends AbstractGremlinProcessTest {
3641

@@ -55,6 +60,16 @@ public abstract class IrGremlinQueryTest extends AbstractGremlinProcessTest {
5560
public abstract Traversal<Vertex, Object>
5661
get_g_V_matchXa_out_b__b_in_cX_select_c_out_dedup_values();
5762

63+
public abstract Traversal<Vertex, String> get_g_V_has_name_marko_label();
64+
65+
public abstract Traversal<Vertex, Object> get_g_V_has_name_marko_select_by_T_label();
66+
67+
public abstract Traversal<Vertex, Object> get_g_V_has_name_marko_select_by_label();
68+
69+
public abstract Traversal<Edge, String> get_g_E_has_weight_0_5_f_label();
70+
71+
public abstract Traversal<Vertex, Map<String, Object>> get_g_V_a_out_b_select_a_b_by_label_id();
72+
5873
@LoadGraphWith(LoadGraphWith.GraphData.MODERN)
5974
@Test
6075
public void g_V_group_by_by_dedup_count_test() {
@@ -211,6 +226,47 @@ public void g_V_matchXa_out_b__b_in_cX_select_c_out_dedup_values() {
211226
Assert.assertEquals(2, counter);
212227
}
213228

229+
@LoadGraphWith(LoadGraphWith.GraphData.MODERN)
230+
@Test
231+
public void g_V_has_name_marko_label() {
232+
final Traversal<Vertex, String> traversal = get_g_V_has_name_marko_label();
233+
printTraversalForm(traversal);
234+
Assert.assertEquals("person", traversal.next());
235+
}
236+
237+
@LoadGraphWith(LoadGraphWith.GraphData.MODERN)
238+
@Test
239+
public void g_E_has_weight_0_5_f_label() {
240+
final Traversal<Edge, String> traversal = get_g_E_has_weight_0_5_f_label();
241+
printTraversalForm(traversal);
242+
Assert.assertEquals("knows", traversal.next());
243+
}
244+
245+
@LoadGraphWith(LoadGraphWith.GraphData.MODERN)
246+
@Test
247+
public void g_V_has_name_marko_select_by_T_label() {
248+
final Traversal<Vertex, Object> traversal = get_g_V_has_name_marko_select_by_T_label();
249+
printTraversalForm(traversal);
250+
Assert.assertEquals("person", traversal.next());
251+
}
252+
253+
@LoadGraphWith(LoadGraphWith.GraphData.MODERN)
254+
@Test
255+
public void g_V_has_name_marko_select_by_label() {
256+
final Traversal<Vertex, Object> traversal = get_g_V_has_name_marko_select_by_label();
257+
printTraversalForm(traversal);
258+
Assert.assertEquals("person", traversal.next());
259+
}
260+
261+
@LoadGraphWith(LoadGraphWith.GraphData.MODERN)
262+
@Test
263+
public void g_V_a_out_b_select_a_b_by_label_id() {
264+
final Traversal<Vertex, Map<String, Object>> traversal =
265+
get_g_V_a_out_b_select_a_b_by_label_id();
266+
printTraversalForm(traversal);
267+
Assert.assertEquals("{a=person, b=lop}", traversal.next().toString());
268+
}
269+
214270
public static class Traversals extends IrGremlinQueryTest {
215271

216272
@Override
@@ -271,5 +327,37 @@ public Traversal<Vertex, Object> get_g_V_matchXa_knows_b__b_created_cX_select_c_
271327
.dedup()
272328
.values("name");
273329
}
330+
331+
@Override
332+
public Traversal<Vertex, String> get_g_V_has_name_marko_label() {
333+
return g.V().has("name", "marko").label();
334+
}
335+
336+
@Override
337+
public Traversal<Vertex, Object> get_g_V_has_name_marko_select_by_T_label() {
338+
return g.V().has("name", "marko").as("a").select("a").by(T.label);
339+
}
340+
341+
@Override
342+
public Traversal<Vertex, Object> get_g_V_has_name_marko_select_by_label() {
343+
return g.V().has("name", "marko").as("a").select("a").by(__.label());
344+
}
345+
346+
@Override
347+
public Traversal<Edge, String> get_g_E_has_weight_0_5_f_label() {
348+
return g.E().has("weight", 0.5f).label();
349+
}
350+
351+
@Override
352+
public Traversal<Vertex, Map<String, Object>> get_g_V_a_out_b_select_a_b_by_label_id() {
353+
return g.V().has("name", "marko")
354+
.as("a")
355+
.out()
356+
.has("name", "lop")
357+
.as("b")
358+
.select("a", "b")
359+
.by(label())
360+
.by("name");
361+
}
274362
}
275363
}

interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/result/GremlinResultAnalyzer.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ public static GremlinResultParser analyze(Traversal traversal) {
5959
|| Utils.equalClass(step, IdStep.class)
6060
|| Utils.equalClass(step, LabelStep.class)
6161
|| Utils.equalClass(step, ConstantStep.class)) {
62-
parserType = GremlinResultParserFactory.PROJECT_VALUE;
62+
parserType = ProjectResultParser.create(step);
6363
} else if (Utils.equalClass(step, GroupCountStep.class)
6464
|| Utils.equalClass(step, GroupStep.class)) {
6565
parserType = GroupResultParser.create(step);
6666
} else if (Utils.equalClass(step, UnionStep.class)) {
67-
parserType = GremlinResultParserFactory.UNION;
67+
parserType = UnionResultParser.create(step);
6868
} else if (Utils.equalClass(step, SubgraphStep.class)) {
6969
parserType = GremlinResultParserFactory.SUBGRAPH;
7070
} else if (Utils.equalClass(step, HasStep.class)

interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/result/GremlinResultParserFactory.java

+1-150
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,14 @@
1616

1717
package com.alibaba.graphscope.gremlin.result;
1818

19-
import com.alibaba.graphscope.common.jna.type.FfiKeyType;
20-
import com.alibaba.graphscope.gaia.proto.Common;
2119
import com.alibaba.graphscope.gaia.proto.IrResult;
2220
import com.alibaba.graphscope.gremlin.exception.GremlinResultParserException;
23-
import com.alibaba.graphscope.gremlin.transform.alias.AliasManager;
2421

2522
import org.apache.tinkerpop.gremlin.structure.Element;
2623
import org.slf4j.Logger;
2724
import org.slf4j.LoggerFactory;
2825

29-
import java.util.Collections;
30-
import java.util.HashMap;
3126
import java.util.List;
32-
import java.util.Map;
3327

3428
public enum GremlinResultParserFactory implements GremlinResultParser {
3529
GRAPH_ELEMENT {
@@ -44,158 +38,15 @@ public Object parseFrom(IrResult.Results results) {
4438
return graphElement;
4539
}
4640
},
41+
4742
SINGLE_VALUE {
4843
@Override
4944
public Object parseFrom(IrResult.Results results) {
5045
IrResult.Entry entry = ParserUtils.getHeadEntry(results);
5146
return ParserUtils.parseEntry(entry);
5247
}
5348
},
54-
PROJECT_VALUE {
55-
// values("name") -> key: head, value: "marko"
56-
// valueMap("name") -> key: head, value: {name, "marko"}
57-
// select("a").by("name") -> key: head, value: "marko"
58-
// select("a", "b").by("name") -> key: a, value: "marko"; key: b, value: "josh"
59-
// select("a", "b").by(valueMap("name")) -> key: a, value: {name, "marko"}; key: b, value:
60-
// {name, "josh"}
61-
@Override
62-
public Object parseFrom(IrResult.Results results) {
63-
logger.debug("{}", results);
64-
IrResult.Record record = results.getRecord();
65-
logger.debug("{}", record);
66-
Map<String, Object> projectResult = new HashMap<>();
67-
record.getColumnsList()
68-
.forEach(
69-
column -> {
70-
String tag = getColumnKeyAsResultKey(column.getNameOrId());
71-
Object parseEntry = ParserUtils.parseEntry(column.getEntry());
72-
if (parseEntry instanceof Map) {
73-
Map projectTags = (Map) parseEntry;
74-
// return empty Map if none properties
75-
Map tagEntry =
76-
(Map)
77-
projectResult.computeIfAbsent(
78-
tag, k1 -> new HashMap<>());
79-
projectTags.forEach(
80-
(k, v) -> {
81-
if (!(v instanceof EmptyValue)) {
82-
String nameOrId = null;
83-
if (k
84-
instanceof
85-
List) { // valueMap("name") -> Map<["",
86-
// "name"], value>
87-
nameOrId = (String) ((List) k).get(1);
88-
} else if (k
89-
instanceof
90-
String) { // valueMap() -> Map<"name",
91-
// value>
92-
nameOrId = (String) k;
93-
} else if (k
94-
instanceof
95-
Number) { // valueMap() -> Map<1, value>
96-
nameOrId = String.valueOf(k);
97-
}
98-
if (nameOrId == null || nameOrId.isEmpty()) {
99-
throw new GremlinResultParserException(
100-
"map value should have property"
101-
+ " key");
102-
}
103-
String property = getPropertyName(nameOrId);
104-
tagEntry.put(
105-
property, Collections.singletonList(v));
106-
}
107-
});
108-
} else {
109-
if (!(parseEntry instanceof EmptyValue)) {
110-
projectResult.put(tag, parseEntry);
111-
}
112-
}
113-
});
114-
if (projectResult.isEmpty()) {
115-
return EmptyValue.INSTANCE;
116-
} else if (projectResult.size() == 1) {
117-
return projectResult.entrySet().iterator().next().getValue();
118-
} else {
119-
return projectResult;
120-
}
121-
}
12249

123-
// a_1 -> a, i.e. g.V().as("a").select("a")
124-
// name_1 -> name, i.e. g.V().values("name")
125-
// a_name_1 -> a, i.e. g.V().as("a").select("a").by("name")
126-
private String getColumnKeyAsResultKey(Common.NameOrId columnKey) {
127-
if (columnKey.getItemCase() == Common.NameOrId.ItemCase.ITEM_NOT_SET) {
128-
return "";
129-
}
130-
switch (columnKey.getItemCase()) {
131-
case ITEM_NOT_SET:
132-
return "";
133-
case NAME:
134-
String key = columnKey.getName();
135-
return AliasManager.getPrefix(key);
136-
case ID:
137-
return String.valueOf(columnKey.getId());
138-
default:
139-
throw new GremlinResultParserException(columnKey.getItemCase() + " is invalid");
140-
}
141-
}
142-
143-
// propertyId is in String format, i.e. "1"
144-
private String getPropertyName(String nameOrId) {
145-
Common.NameOrId.Builder builder = Common.NameOrId.newBuilder();
146-
if (nameOrId.matches("^[0-9]+$")) {
147-
builder.setId(Integer.valueOf(nameOrId));
148-
} else {
149-
builder.setName(nameOrId);
150-
}
151-
return ParserUtils.getKeyName(builder.build(), FfiKeyType.Column);
152-
}
153-
},
154-
UNION {
155-
@Override
156-
public Object parseFrom(IrResult.Results results) {
157-
GremlinResultParser resultParser = inferFromIrResults(results);
158-
return resultParser.parseFrom(results);
159-
}
160-
161-
// try to infer from the results
162-
private GremlinResultParser inferFromIrResults(IrResult.Results results) {
163-
int columns = results.getRecord().getColumnsList().size();
164-
logger.debug("result is {}", results);
165-
if (columns == 1) {
166-
IrResult.Entry entry = ParserUtils.getHeadEntry(results);
167-
switch (entry.getInnerCase()) {
168-
case ELEMENT:
169-
IrResult.Element element = entry.getElement();
170-
if (element.getInnerCase() == IrResult.Element.InnerCase.VERTEX
171-
|| element.getInnerCase() == IrResult.Element.InnerCase.EDGE
172-
|| element.getInnerCase()
173-
== IrResult.Element.InnerCase.GRAPH_PATH) {
174-
return GRAPH_ELEMENT;
175-
} else if (element.getInnerCase() == IrResult.Element.InnerCase.OBJECT) {
176-
Common.Value value = element.getObject();
177-
if (value.getItemCase()
178-
== Common.Value.ItemCase.PAIR_ARRAY) { // project
179-
return PROJECT_VALUE;
180-
} else { // simple type
181-
return SINGLE_VALUE;
182-
}
183-
} else {
184-
throw new GremlinResultParserException(
185-
element.getInnerCase() + " is invalid");
186-
}
187-
case COLLECTION: // path()
188-
default:
189-
throw new GremlinResultParserException(
190-
entry.getInnerCase() + " is unsupported yet");
191-
}
192-
} else if (columns > 1) { // project or group
193-
return PROJECT_VALUE;
194-
} else {
195-
throw new GremlinResultParserException("columns should not be empty");
196-
}
197-
}
198-
},
19950
SUBGRAPH {
20051
@Override
20152
public Object parseFrom(IrResult.Results results) {

0 commit comments

Comments
 (0)