Skip to content

Commit 7ab506f

Browse files
authored
Enhanced query logic (#848)
* Fetch vertex details for fragments * Fix tests * Update changelog
1 parent bd9ff7d commit 7ab506f

11 files changed

+361
-133
lines changed

Changelog.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
([#826](https://github.com/aws/graph-explorer/pull/826),
99
[#840](https://github.com/aws/graph-explorer/pull/840))
1010
- **Added** query editor for Gremlin connections
11-
([#853](https://github.com/aws/graph-explorer/pull/853),
11+
([#848](https://github.com/aws/graph-explorer/pull/848),
12+
[#853](https://github.com/aws/graph-explorer/pull/853),
1213
[#850](https://github.com/aws/graph-explorer/pull/850),
1314
[#843](https://github.com/aws/graph-explorer/pull/843),
1415
[#842](https://github.com/aws/graph-explorer/pull/842),

packages/graph-explorer/src/connector/gremlin/mappers/mapResults.test.ts

+13
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,21 @@ describe("mapResults", () => {
9191

9292
it("should remove duplicate vertices", () => {
9393
const edge = createRandomEdge(createRandomVertex(), createRandomVertex());
94+
const sourceFragment = createVertex({
95+
id: edge.source,
96+
types: edge.sourceTypes,
97+
});
98+
const targetFragment = createVertex({
99+
id: edge.target,
100+
types: edge.targetTypes,
101+
});
94102
const gEdge = createGEdge(edge);
95103
const gList = createGList([gEdge, gEdge]);
96104
const results = mapResults(gList);
97105
expect(results).toEqual(
98106
toMappedQueryResults({
99107
edges: [edge],
108+
vertices: [sourceFragment, targetFragment],
100109
})
101110
);
102111
});
@@ -149,6 +158,10 @@ describe("mapResults", () => {
149158
},
150159
}),
151160
],
161+
vertices: [
162+
createVertex({ id: "2", types: ["Person"] }),
163+
createVertex({ id: "1", types: ["Person"] }),
164+
],
152165
})
153166
);
154167
});

packages/graph-explorer/src/connector/gremlin/mappers/mapResults.ts

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Vertex, Edge, toNodeMap, toEdgeMap } from "@/core";
1+
import { Vertex, Edge, toNodeMap, toEdgeMap, createVertex } from "@/core";
22
import { GAnyValue } from "../types";
33
import mapApiEdge from "./mapApiEdge";
44
import mapApiVertex from "./mapApiVertex";
@@ -11,8 +11,26 @@ export function mapResults(data: GAnyValue) {
1111
const vertexMap = toNodeMap(
1212
values.filter(e => "vertex" in e).map(e => e.vertex)
1313
);
14+
1415
const edgeMap = toEdgeMap(values.filter(e => "edge" in e).map(e => e.edge));
1516

17+
// Add fragment vertices from the edges if they are missing
18+
for (const edge of edgeMap.values()) {
19+
if (!vertexMap.has(edge.source)) {
20+
vertexMap.set(
21+
edge.source,
22+
createVertex({ id: edge.source, types: edge.sourceTypes })
23+
);
24+
}
25+
26+
if (!vertexMap.has(edge.target)) {
27+
vertexMap.set(
28+
edge.target,
29+
createVertex({ id: edge.target, types: edge.targetTypes })
30+
);
31+
}
32+
}
33+
1634
const vertices = vertexMap.values().toArray();
1735
const edges = edgeMap.values().toArray();
1836

packages/graph-explorer/src/hooks/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ export { default as usePrevious } from "./usePrevious";
1111
export { default as useTranslations } from "./useTranslations";
1212
export * from "./useEdgeDetailsQuery";
1313
export * from "./useVertexDetailsQuery";
14+
export * from "./useDisplayVertexFromFragment";

packages/graph-explorer/src/hooks/useAddToGraph.test.ts

+88-6
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,24 @@ import {
2121
VertexTypeConfig,
2222
} from "@/core";
2323
import { waitFor } from "@testing-library/react";
24+
import { useMaterializeVertices } from "./useMaterializeVertices";
25+
import { cloneDeep } from "lodash";
26+
27+
vi.mock("./useMaterializeVertices", () => ({
28+
useMaterializeVertices: vi.fn(),
29+
}));
30+
31+
beforeEach(() => {
32+
vi.resetAllMocks();
33+
});
2434

2535
test("should add one node", async () => {
2636
const vertex = createRandomVertex();
2737

38+
vi.mocked(useMaterializeVertices).mockReturnValue(() =>
39+
Promise.resolve(toNodeMap([vertex]))
40+
);
41+
2842
const { result } = renderHookWithRecoilRoot(() => {
2943
const callback = useAddToGraph();
3044
const vertices = useRecoilValue(nodesAtom);
@@ -43,11 +57,43 @@ test("should add one node", async () => {
4357
});
4458
});
4559

60+
test("should materialize fragment vertices", async () => {
61+
const vertex = createRandomVertex();
62+
const clonedVertex = cloneDeep(vertex);
63+
vertex.__isFragment = true;
64+
vertex.attributes = {};
65+
66+
vi.mocked(useMaterializeVertices).mockReturnValue(() =>
67+
Promise.resolve(toNodeMap([clonedVertex]))
68+
);
69+
70+
const { result } = renderHookWithRecoilRoot(() => {
71+
const callback = useAddToGraph();
72+
const vertices = useRecoilValue(nodesAtom);
73+
const edges = useRecoilValue(edgesAtom);
74+
75+
return { callback, vertices, edges };
76+
});
77+
78+
act(() => {
79+
result.current.callback({ vertices: [vertex] });
80+
});
81+
82+
await waitFor(() => {
83+
const actual = result.current.vertices.get(vertex.id);
84+
expect(actual).toEqual(clonedVertex);
85+
});
86+
});
87+
4688
test("should add one edge", async () => {
4789
const node1 = createRandomVertex();
4890
const node2 = createRandomVertex();
4991
const edge = createRandomEdge(node1, node2);
5092

93+
vi.mocked(useMaterializeVertices).mockReturnValue(() =>
94+
Promise.resolve(toNodeMap([node1, node2]))
95+
);
96+
5197
const { result } = renderHookWithRecoilRoot(
5298
() => {
5399
const callback = useAddToGraph();
@@ -74,6 +120,10 @@ test("should add one edge", async () => {
74120
test("should add multiple nodes and edges", async () => {
75121
const randomEntities = createRandomEntities();
76122

123+
vi.mocked(useMaterializeVertices).mockReturnValue(() =>
124+
Promise.resolve(randomEntities.nodes)
125+
);
126+
77127
const { result } = renderHookWithRecoilRoot(() => {
78128
const callback = useAddToGraph();
79129
const vertices = useRecoilValue(nodesAtom);
@@ -105,6 +155,10 @@ test("should update schema when adding a node", async () => {
105155
const expectedVertexType = extractConfigFromEntity(vertex);
106156
const dbState = new DbState();
107157

158+
vi.mocked(useMaterializeVertices).mockReturnValue(() =>
159+
Promise.resolve(toNodeMap([vertex]))
160+
);
161+
108162
const { result } = renderHookWithRecoilRoot(
109163
() => {
110164
const callback = useAddToGraph();
@@ -136,6 +190,10 @@ test("should update schema when adding a node with no label", async () => {
136190
const expectedVertexType = extractConfigFromEntity(vertex);
137191
const dbState = new DbState();
138192

193+
vi.mocked(useMaterializeVertices).mockReturnValue(() =>
194+
Promise.resolve(toNodeMap([vertex]))
195+
);
196+
139197
const { result } = renderHookWithRecoilRoot(
140198
() => {
141199
const callback = useAddToGraph();
@@ -169,6 +227,10 @@ test("should update schema when adding an edge", async () => {
169227
dbState.addVertexToGraph(node1);
170228
dbState.addVertexToGraph(node2);
171229

230+
vi.mocked(useMaterializeVertices).mockReturnValue(() =>
231+
Promise.resolve(toNodeMap([node1, node2]))
232+
);
233+
172234
const { result } = renderHookWithRecoilRoot(
173235
() => {
174236
const callback = useAddToGraph();
@@ -205,6 +267,10 @@ test("should add missing attributes to the schema when adding a node", async ()
205267
};
206268
dbState.activeSchema.vertices.push(initialVtConfig);
207269

270+
vi.mocked(useMaterializeVertices).mockReturnValue(() =>
271+
Promise.resolve(toNodeMap([vertex]))
272+
);
273+
208274
const { result } = renderHookWithRecoilRoot(
209275
() => {
210276
const callback = useAddToGraph();
@@ -245,6 +311,10 @@ test("should add missing attributes to the schema when adding an edge", async ()
245311
};
246312
dbState.activeSchema.edges.push(initialEtConfig);
247313

314+
vi.mocked(useMaterializeVertices).mockReturnValue(() =>
315+
Promise.resolve(toNodeMap([node1, node2]))
316+
);
317+
248318
const { result } = renderHookWithRecoilRoot(
249319
() => {
250320
const callback = useAddToGraph();
@@ -270,8 +340,13 @@ test("should add missing attributes to the schema when adding an edge", async ()
270340
});
271341

272342
test("should update graph storage when adding a node", async () => {
343+
const vertex = createRandomVertex();
273344
const dbState = new DbState();
274345

346+
vi.mocked(useMaterializeVertices).mockReturnValue(() =>
347+
Promise.resolve(toNodeMap([vertex]))
348+
);
349+
275350
const { result } = renderHookWithRecoilRoot(
276351
() => {
277352
const callback = useAddToGraph();
@@ -281,7 +356,6 @@ test("should update graph storage when adding a node", async () => {
281356
snapshot => dbState.applyTo(snapshot)
282357
);
283358

284-
const vertex = createRandomVertex();
285359
act(() => {
286360
result.current.callback({ vertices: [vertex] });
287361
});
@@ -305,6 +379,10 @@ test("should update graph storage when adding an edge", async () => {
305379
dbState.addVertexToGraph(node1);
306380
dbState.addVertexToGraph(node2);
307381

382+
vi.mocked(useMaterializeVertices).mockReturnValue(() =>
383+
Promise.resolve(toNodeMap([node1, node2]))
384+
);
385+
308386
const { result } = renderHookWithRecoilRoot(
309387
() => {
310388
const callback = useAddToGraph();
@@ -329,8 +407,17 @@ test("should update graph storage when adding an edge", async () => {
329407
});
330408

331409
test("should ignore blank nodes when updating graph storage", async () => {
410+
const vertex = createRandomVertexForRdf();
411+
const blankNode = createRandomVertexForRdf();
412+
blankNode.__isBlank = true;
413+
const edge = createRandomEdge(vertex, blankNode);
414+
332415
const dbState = new DbState();
333416

417+
vi.mocked(useMaterializeVertices).mockReturnValue(() =>
418+
Promise.resolve(toNodeMap([vertex, blankNode]))
419+
);
420+
334421
const { result } = renderHookWithRecoilRoot(
335422
() => {
336423
const callback = useAddToGraph();
@@ -340,11 +427,6 @@ test("should ignore blank nodes when updating graph storage", async () => {
340427
snapshot => dbState.applyTo(snapshot)
341428
);
342429

343-
const vertex = createRandomVertexForRdf();
344-
const blankNode = createRandomVertexForRdf();
345-
blankNode.__isBlank = true;
346-
const edge = createRandomEdge(vertex, blankNode);
347-
348430
act(() => {
349431
result.current.callback({ vertices: [vertex, blankNode], edges: [edge] });
350432
});

0 commit comments

Comments
 (0)