flowquery 1.0.21 → 1.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flowquery",
3
- "version": "1.0.21",
3
+ "version": "1.0.22",
4
4
  "description": "A declarative query language for data processing pipelines.",
5
5
  "main": "dist/index.node.js",
6
6
  "types": "dist/index.node.d.ts",
@@ -39,6 +39,36 @@ class Database {
39
39
  public getRelationship(relationship: Relationship): PhysicalRelationship | null {
40
40
  return Database.relationships.get(relationship.type!) || null;
41
41
  }
42
+ public async schema(): Promise<Record<string, any>[]> {
43
+ const result: Record<string, any>[] = [];
44
+
45
+ for (const [label, physical] of Database.nodes) {
46
+ const records = await physical.data();
47
+ const entry: Record<string, any> = { kind: "node", label };
48
+ if (records.length > 0) {
49
+ const { id, ...sample } = records[0];
50
+ if (Object.keys(sample).length > 0) {
51
+ entry.sample = sample;
52
+ }
53
+ }
54
+ result.push(entry);
55
+ }
56
+
57
+ for (const [type, physical] of Database.relationships) {
58
+ const records = await physical.data();
59
+ const entry: Record<string, any> = { kind: "relationship", type };
60
+ if (records.length > 0) {
61
+ const { left_id, right_id, ...sample } = records[0];
62
+ if (Object.keys(sample).length > 0) {
63
+ entry.sample = sample;
64
+ }
65
+ }
66
+ result.push(entry);
67
+ }
68
+
69
+ return result;
70
+ }
71
+
42
72
  public async getData(element: Node | Relationship): Promise<NodeData | RelationshipData> {
43
73
  if (element instanceof Node) {
44
74
  const node = this.getNode(element);
@@ -18,6 +18,7 @@ import "./rand";
18
18
  import "./range";
19
19
  import "./replace";
20
20
  import "./round";
21
+ import "./schema";
21
22
  import "./size";
22
23
  import "./split";
23
24
  import "./stringify";
@@ -0,0 +1,36 @@
1
+ import Database from "../../graph/database";
2
+ import AsyncFunction from "./async_function";
3
+ import { FunctionDef } from "./function_metadata";
4
+
5
+ /**
6
+ * Built-in function that returns the graph schema of the database.
7
+ *
8
+ * Lists all nodes and relationships with their labels/types and a sample
9
+ * of their data (excluding id from nodes, left_id and right_id from relationships).
10
+ *
11
+ * @example
12
+ * ```
13
+ * LOAD FROM schema() AS s RETURN s
14
+ * ```
15
+ */
16
+ @FunctionDef({
17
+ description:
18
+ "Returns the graph schema listing all nodes and relationships with a sample of their data.",
19
+ category: "async",
20
+ parameters: [],
21
+ output: {
22
+ description: "Schema entry with kind, label/type, and optional sample data",
23
+ type: "object",
24
+ },
25
+ examples: ["LOAD FROM schema() AS s RETURN s"],
26
+ })
27
+ class Schema extends AsyncFunction {
28
+ public async *generate(): AsyncGenerator<any> {
29
+ const entries = await Database.getInstance().schema();
30
+ for (const entry of entries) {
31
+ yield entry;
32
+ }
33
+ }
34
+ }
35
+
36
+ export default Schema;
@@ -1460,3 +1460,43 @@ test("Test match with leftward double graph pattern", async () => {
1460
1460
  expect(results[0]).toEqual({ name1: "Person 1", name2: "Person 2", name3: "Person 3" });
1461
1461
  expect(results[1]).toEqual({ name1: "Person 2", name2: "Person 3", name3: "Person 4" });
1462
1462
  });
1463
+
1464
+ test("Test schema() returns nodes and relationships with sample data", async () => {
1465
+ await new Runner(`
1466
+ CREATE VIRTUAL (:Animal) AS {
1467
+ UNWIND [
1468
+ {id: 1, species: 'Cat', legs: 4},
1469
+ {id: 2, species: 'Dog', legs: 4}
1470
+ ] AS record
1471
+ RETURN record.id AS id, record.species AS species, record.legs AS legs
1472
+ }
1473
+ `).run();
1474
+ await new Runner(`
1475
+ CREATE VIRTUAL (:Animal)-[:CHASES]-(:Animal) AS {
1476
+ UNWIND [
1477
+ {left_id: 2, right_id: 1, speed: 'fast'}
1478
+ ] AS record
1479
+ RETURN record.left_id AS left_id, record.right_id AS right_id, record.speed AS speed
1480
+ }
1481
+ `).run();
1482
+
1483
+ const runner = new Runner(
1484
+ "CALL schema() YIELD kind, label, type, sample RETURN kind, label, type, sample"
1485
+ );
1486
+ await runner.run();
1487
+ const results = runner.results;
1488
+
1489
+ const animal = results.find((r: any) => r.kind === "node" && r.label === "Animal");
1490
+ expect(animal).toBeDefined();
1491
+ expect(animal.sample).toBeDefined();
1492
+ expect(animal.sample).not.toHaveProperty("id");
1493
+ expect(animal.sample).toHaveProperty("species");
1494
+ expect(animal.sample).toHaveProperty("legs");
1495
+
1496
+ const chases = results.find((r: any) => r.kind === "relationship" && r.type === "CHASES");
1497
+ expect(chases).toBeDefined();
1498
+ expect(chases.sample).toBeDefined();
1499
+ expect(chases.sample).not.toHaveProperty("left_id");
1500
+ expect(chases.sample).not.toHaveProperty("right_id");
1501
+ expect(chases.sample).toHaveProperty("speed");
1502
+ });