Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,31 @@ describe("Gremlin > edgesSchemaTemplate", () => {

expect(normalize(template)).toBe(
normalize(`
g.E()
.project("route", "contain")
g.V().limit(1)
.project(
"route",
"contain"
)
.by(V().bothE("route").limit(1))
.by(V().bothE("contain").limit(1))
.limit(1)
`),
);
});

it("Should deduplicate labels from multi-label types", () => {
const template = edgesSchemaTemplate({ types: ["a::b", "b::c"] });

expect(normalize(template)).toBe(
normalize(`
g.V().limit(1)
.project(
"a",
"b",
"c"
)
.by(V().bothE("a").limit(1))
.by(V().bothE("b").limit(1))
.by(V().bothE("c").limit(1))
`),
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,31 @@ import { query } from "@/utils";
* Given a set of edge types, it returns a Gremlin template that contains
* one sample of each edge type.
*
* @example
* types = ["route", "contain"]
* Uses g.V().limit(1) as a dummy anchor because each .by() modulator runs an
* independent global V() sub-traversal that doesn't depend on the anchor value.
* This also avoids Neptune DFE falling back to non-native execution for g.E().
*
* g.E()
* .project("route","contain")
* .by(V().bothE("route").limit(1))
* .by(V().bothE("contain").limit(1))
* .limit(1)
* @example
* edgesSchemaTemplate({ types: ["route", "contain"] })
* // Returns:
* // g.V().limit(1)
* // .project(
* // "route",
* // "contain"
* // )
* // .by(V().bothE("route").limit(1))
* // .by(V().bothE("contain").limit(1))
*/
export default function edgesSchemaTemplate({ types }: { types: string[] }) {
// Labels with quotes
const labels = uniq(types.flatMap(type => type.split("::"))).map(
label => `"${label}"`,
);

return query`
g.E()
.project(${labels.join(", ")})
g.V().limit(1)
.project(
${labels.join(",\n ")}
)
${labels.map(label => `.by(V().bothE(${label}).limit(1))`).join("\n ")}
.limit(1)
`;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,31 @@ describe("Gremlin > verticesSchemaTemplate", () => {

expect(normalize(template)).toBe(
normalize(`
g.V().union(
__.hasLabel("airport").limit(1),
__.hasLabel("country").limit(1)
)
.fold()
.project("airport", "country")
.by(unfold().hasLabel("airport"))
.by(unfold().hasLabel("country"))
g.V().limit(1)
.project(
"airport",
"country"
)
.by(V().hasLabel("airport").limit(1))
.by(V().hasLabel("country").limit(1))
`),
);
});

it("Should deduplicate labels from multi-label types", () => {
const template = verticesSchemaTemplate({ types: ["a::b", "b::c"] });

expect(normalize(template)).toBe(
normalize(`
g.V().limit(1)
.project(
"a",
"b",
"c"
)
.by(V().hasLabel("a").limit(1))
.by(V().hasLabel("b").limit(1))
.by(V().hasLabel("c").limit(1))
`),
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,31 @@ import { query } from "@/utils";
* Given a set of nodes labels, it returns a Gremlin template that contains
* one sample of each node label.
*
* @example
* types = ["airport", "country"]
* Uses g.V().limit(1) as a dummy anchor because each .by() modulator runs an
* independent global V() sub-traversal that doesn't depend on the anchor value.
* This also avoids Neptune DFE falling back to non-native execution.
*
* g.V()
* .union(
* __.hasLabel("airport").limit(1),
* __.hasLabel("country").limit(1)
* )
* .fold()
* .project(
* "airport", "country"
* )
* .by(unfold().hasLabel("airport"))
* .by(unfold().hasLabel("country"))
* @example
* verticesSchemaTemplate({ types: ["airport", "country"] })
* // Returns:
* // g.V().limit(1)
* // .project(
* // "airport",
* // "country"
* // )
* // .by(V().hasLabel("airport").limit(1))
* // .by(V().hasLabel("country").limit(1))
*/
export default function verticesSchemaTemplate({ types }: { types: string[] }) {
// Labels with quotes
const labels = uniq(types.flatMap(type => type.split("::"))).map(
label => `"${label}"`,
);

return query`
g.V()
.union(
${labels.map(label => `__.hasLabel(${label}).limit(1)`).join(",\n ")}
)
.fold()
g.V().limit(1)
.project(
${labels.join(",\n ")}
)
${labels.map(label => `.by(unfold().hasLabel(${label}))`).join("\n ")}
`;
${labels.map(label => `.by(V().hasLabel(${label}).limit(1))`).join("\n ")}
`;
}
Loading