flowquery 1.0.16 → 1.0.17
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/.github/workflows/python-publish.yml +97 -0
- package/dist/compute/runner.d.ts +3 -2
- package/dist/compute/runner.d.ts.map +1 -1
- package/dist/compute/runner.js +7 -7
- package/dist/compute/runner.js.map +1 -1
- package/dist/flowquery.min.js +1 -1
- package/dist/graph/data.d.ts +31 -0
- package/dist/graph/data.d.ts.map +1 -0
- package/dist/graph/data.js +110 -0
- package/dist/graph/data.js.map +1 -0
- package/dist/graph/database.d.ts +20 -0
- package/dist/graph/database.d.ts.map +1 -0
- package/dist/graph/database.js +77 -0
- package/dist/graph/database.js.map +1 -0
- package/dist/graph/hops.d.ts +11 -0
- package/dist/graph/hops.d.ts.map +1 -0
- package/dist/graph/hops.js +25 -0
- package/dist/graph/hops.js.map +1 -0
- package/dist/graph/node.d.ts +35 -0
- package/dist/graph/node.d.ts.map +1 -0
- package/dist/graph/node.js +113 -0
- package/dist/graph/node.js.map +1 -0
- package/dist/graph/node_data.d.ts +11 -0
- package/dist/graph/node_data.d.ts.map +1 -0
- package/dist/graph/node_data.js +20 -0
- package/dist/graph/node_data.js.map +1 -0
- package/dist/graph/node_reference.d.ts +10 -0
- package/dist/graph/node_reference.d.ts.map +1 -0
- package/dist/graph/node_reference.js +52 -0
- package/dist/graph/node_reference.js.map +1 -0
- package/dist/graph/pattern.d.ts +18 -0
- package/dist/graph/pattern.d.ts.map +1 -0
- package/dist/graph/pattern.js +114 -0
- package/dist/graph/pattern.js.map +1 -0
- package/dist/graph/pattern_expression.d.ts +14 -0
- package/dist/graph/pattern_expression.d.ts.map +1 -0
- package/dist/graph/pattern_expression.js +58 -0
- package/dist/graph/pattern_expression.js.map +1 -0
- package/dist/graph/patterns.d.ts +11 -0
- package/dist/graph/patterns.d.ts.map +1 -0
- package/dist/graph/patterns.js +49 -0
- package/dist/graph/patterns.js.map +1 -0
- package/dist/graph/physical_node.d.ts +10 -0
- package/dist/graph/physical_node.d.ts.map +1 -0
- package/dist/graph/physical_node.js +40 -0
- package/dist/graph/physical_node.js.map +1 -0
- package/dist/graph/physical_relationship.d.ts +10 -0
- package/dist/graph/physical_relationship.d.ts.map +1 -0
- package/dist/graph/physical_relationship.js +40 -0
- package/dist/graph/physical_relationship.js.map +1 -0
- package/dist/graph/relationship.d.ts +40 -0
- package/dist/graph/relationship.d.ts.map +1 -0
- package/dist/graph/relationship.js +124 -0
- package/dist/graph/relationship.js.map +1 -0
- package/dist/graph/relationship_data.d.ts +12 -0
- package/dist/graph/relationship_data.d.ts.map +1 -0
- package/dist/graph/relationship_data.js +40 -0
- package/dist/graph/relationship_data.js.map +1 -0
- package/dist/graph/relationship_match_collector.d.ts +19 -0
- package/dist/graph/relationship_match_collector.d.ts.map +1 -0
- package/dist/graph/relationship_match_collector.js +55 -0
- package/dist/graph/relationship_match_collector.js.map +1 -0
- package/dist/graph/relationship_reference.d.ts +8 -0
- package/dist/graph/relationship_reference.d.ts.map +1 -0
- package/dist/graph/relationship_reference.js +37 -0
- package/dist/graph/relationship_reference.js.map +1 -0
- package/dist/parsing/base_parser.d.ts +1 -0
- package/dist/parsing/base_parser.d.ts.map +1 -1
- package/dist/parsing/base_parser.js +4 -1
- package/dist/parsing/base_parser.js.map +1 -1
- package/dist/parsing/context.d.ts +2 -2
- package/dist/parsing/context.js +5 -5
- package/dist/parsing/expressions/boolean.d.ts +8 -0
- package/dist/parsing/expressions/boolean.d.ts.map +1 -0
- package/dist/parsing/expressions/boolean.js +26 -0
- package/dist/parsing/expressions/boolean.js.map +1 -0
- package/dist/parsing/expressions/expression.d.ts +4 -1
- package/dist/parsing/expressions/expression.d.ts.map +1 -1
- package/dist/parsing/expressions/expression.js +15 -8
- package/dist/parsing/expressions/expression.js.map +1 -1
- package/dist/parsing/expressions/operator.d.ts +1 -1
- package/dist/parsing/expressions/operator.d.ts.map +1 -1
- package/dist/parsing/expressions/operator.js.map +1 -1
- package/dist/parsing/functions/function_factory.d.ts +13 -13
- package/dist/parsing/functions/function_factory.d.ts.map +1 -1
- package/dist/parsing/functions/function_factory.js +20 -18
- package/dist/parsing/functions/function_factory.js.map +1 -1
- package/dist/parsing/operations/create_node.d.ts +14 -0
- package/dist/parsing/operations/create_node.d.ts.map +1 -0
- package/dist/parsing/operations/create_node.js +51 -0
- package/dist/parsing/operations/create_node.js.map +1 -0
- package/dist/parsing/operations/create_relationship.d.ts +14 -0
- package/dist/parsing/operations/create_relationship.d.ts.map +1 -0
- package/dist/parsing/operations/create_relationship.js +51 -0
- package/dist/parsing/operations/create_relationship.js.map +1 -0
- package/dist/parsing/operations/match.d.ts +15 -0
- package/dist/parsing/operations/match.d.ts.map +1 -0
- package/dist/parsing/operations/match.js +45 -0
- package/dist/parsing/operations/match.js.map +1 -0
- package/dist/parsing/operations/operation.d.ts +1 -0
- package/dist/parsing/operations/operation.d.ts.map +1 -1
- package/dist/parsing/operations/operation.js +6 -0
- package/dist/parsing/operations/operation.js.map +1 -1
- package/dist/parsing/operations/return.d.ts +1 -0
- package/dist/parsing/operations/return.d.ts.map +1 -1
- package/dist/parsing/operations/return.js +7 -1
- package/dist/parsing/operations/return.js.map +1 -1
- package/dist/parsing/operations/where.d.ts +1 -1
- package/dist/parsing/operations/where.d.ts.map +1 -1
- package/dist/parsing/operations/where.js +4 -0
- package/dist/parsing/operations/where.js.map +1 -1
- package/dist/parsing/parser.d.ts +10 -0
- package/dist/parsing/parser.d.ts.map +1 -1
- package/dist/parsing/parser.js +344 -5
- package/dist/parsing/parser.js.map +1 -1
- package/dist/parsing/token_to_node.d.ts.map +1 -1
- package/dist/parsing/token_to_node.js +7 -0
- package/dist/parsing/token_to_node.js.map +1 -1
- package/dist/tokenization/keyword.d.ts +1 -0
- package/dist/tokenization/keyword.d.ts.map +1 -1
- package/dist/tokenization/keyword.js +1 -0
- package/dist/tokenization/keyword.js.map +1 -1
- package/dist/tokenization/token.d.ts +4 -0
- package/dist/tokenization/token.d.ts.map +1 -1
- package/dist/tokenization/token.js +14 -1
- package/dist/tokenization/token.js.map +1 -1
- package/dist/tokenization/token_type.d.ts +1 -0
- package/dist/tokenization/token_type.d.ts.map +1 -1
- package/dist/tokenization/token_type.js +1 -0
- package/dist/tokenization/token_type.js.map +1 -1
- package/dist/tokenization/tokenizer.d.ts +2 -1
- package/dist/tokenization/tokenizer.d.ts.map +1 -1
- package/dist/tokenization/tokenizer.js +25 -12
- package/dist/tokenization/tokenizer.js.map +1 -1
- package/docs/flowquery.min.js +1 -1
- package/flowquery-py/README.md +166 -0
- package/flowquery-py/pyproject.toml +75 -0
- package/flowquery-py/setup_env.ps1 +92 -0
- package/flowquery-py/setup_env.sh +87 -0
- package/flowquery-py/src/__init__.py +34 -0
- package/flowquery-py/src/__main__.py +10 -0
- package/flowquery-py/src/compute/__init__.py +5 -0
- package/flowquery-py/src/compute/runner.py +60 -0
- package/flowquery-py/src/extensibility.py +52 -0
- package/flowquery-py/src/graph/__init__.py +31 -0
- package/flowquery-py/src/graph/data.py +118 -0
- package/flowquery-py/src/graph/database.py +82 -0
- package/flowquery-py/src/graph/hops.py +43 -0
- package/flowquery-py/src/graph/node.py +112 -0
- package/flowquery-py/src/graph/node_data.py +26 -0
- package/flowquery-py/src/graph/node_reference.py +49 -0
- package/flowquery-py/src/graph/pattern.py +125 -0
- package/flowquery-py/src/graph/pattern_expression.py +62 -0
- package/flowquery-py/src/graph/patterns.py +42 -0
- package/flowquery-py/src/graph/physical_node.py +40 -0
- package/flowquery-py/src/graph/physical_relationship.py +36 -0
- package/flowquery-py/src/graph/relationship.py +135 -0
- package/flowquery-py/src/graph/relationship_data.py +33 -0
- package/flowquery-py/src/graph/relationship_match_collector.py +77 -0
- package/flowquery-py/src/graph/relationship_reference.py +21 -0
- package/flowquery-py/src/io/__init__.py +5 -0
- package/flowquery-py/src/io/command_line.py +67 -0
- package/flowquery-py/src/parsing/__init__.py +17 -0
- package/flowquery-py/src/parsing/alias.py +20 -0
- package/flowquery-py/src/parsing/alias_option.py +11 -0
- package/flowquery-py/src/parsing/ast_node.py +146 -0
- package/flowquery-py/src/parsing/base_parser.py +84 -0
- package/flowquery-py/src/parsing/components/__init__.py +19 -0
- package/flowquery-py/src/parsing/components/csv.py +8 -0
- package/flowquery-py/src/parsing/components/from_.py +10 -0
- package/flowquery-py/src/parsing/components/headers.py +12 -0
- package/flowquery-py/src/parsing/components/json.py +8 -0
- package/flowquery-py/src/parsing/components/null.py +10 -0
- package/flowquery-py/src/parsing/components/post.py +8 -0
- package/flowquery-py/src/parsing/components/text.py +8 -0
- package/flowquery-py/src/parsing/context.py +50 -0
- package/flowquery-py/src/parsing/data_structures/__init__.py +15 -0
- package/flowquery-py/src/parsing/data_structures/associative_array.py +41 -0
- package/flowquery-py/src/parsing/data_structures/json_array.py +30 -0
- package/flowquery-py/src/parsing/data_structures/key_value_pair.py +38 -0
- package/flowquery-py/src/parsing/data_structures/lookup.py +49 -0
- package/flowquery-py/src/parsing/data_structures/range_lookup.py +42 -0
- package/flowquery-py/src/parsing/expressions/__init__.py +57 -0
- package/flowquery-py/src/parsing/expressions/boolean.py +20 -0
- package/flowquery-py/src/parsing/expressions/expression.py +138 -0
- package/flowquery-py/src/parsing/expressions/expression_map.py +26 -0
- package/flowquery-py/src/parsing/expressions/f_string.py +27 -0
- package/flowquery-py/src/parsing/expressions/identifier.py +20 -0
- package/flowquery-py/src/parsing/expressions/number.py +32 -0
- package/flowquery-py/src/parsing/expressions/operator.py +169 -0
- package/flowquery-py/src/parsing/expressions/reference.py +47 -0
- package/flowquery-py/src/parsing/expressions/string.py +27 -0
- package/flowquery-py/src/parsing/functions/__init__.py +75 -0
- package/flowquery-py/src/parsing/functions/aggregate_function.py +60 -0
- package/flowquery-py/src/parsing/functions/async_function.py +62 -0
- package/flowquery-py/src/parsing/functions/avg.py +55 -0
- package/flowquery-py/src/parsing/functions/collect.py +75 -0
- package/flowquery-py/src/parsing/functions/function.py +68 -0
- package/flowquery-py/src/parsing/functions/function_factory.py +173 -0
- package/flowquery-py/src/parsing/functions/function_metadata.py +149 -0
- package/flowquery-py/src/parsing/functions/functions.py +59 -0
- package/flowquery-py/src/parsing/functions/join.py +47 -0
- package/flowquery-py/src/parsing/functions/keys.py +34 -0
- package/flowquery-py/src/parsing/functions/predicate_function.py +46 -0
- package/flowquery-py/src/parsing/functions/predicate_sum.py +47 -0
- package/flowquery-py/src/parsing/functions/rand.py +28 -0
- package/flowquery-py/src/parsing/functions/range_.py +34 -0
- package/flowquery-py/src/parsing/functions/reducer_element.py +15 -0
- package/flowquery-py/src/parsing/functions/replace.py +37 -0
- package/flowquery-py/src/parsing/functions/round_.py +32 -0
- package/flowquery-py/src/parsing/functions/size.py +32 -0
- package/flowquery-py/src/parsing/functions/split.py +47 -0
- package/flowquery-py/src/parsing/functions/stringify.py +47 -0
- package/flowquery-py/src/parsing/functions/sum.py +51 -0
- package/flowquery-py/src/parsing/functions/to_json.py +33 -0
- package/flowquery-py/src/parsing/functions/type_.py +47 -0
- package/flowquery-py/src/parsing/functions/value_holder.py +24 -0
- package/flowquery-py/src/parsing/logic/__init__.py +15 -0
- package/flowquery-py/src/parsing/logic/case.py +29 -0
- package/flowquery-py/src/parsing/logic/else_.py +12 -0
- package/flowquery-py/src/parsing/logic/end.py +8 -0
- package/flowquery-py/src/parsing/logic/then.py +12 -0
- package/flowquery-py/src/parsing/logic/when.py +10 -0
- package/flowquery-py/src/parsing/operations/__init__.py +35 -0
- package/flowquery-py/src/parsing/operations/aggregated_return.py +24 -0
- package/flowquery-py/src/parsing/operations/aggregated_with.py +22 -0
- package/flowquery-py/src/parsing/operations/call.py +74 -0
- package/flowquery-py/src/parsing/operations/create_node.py +34 -0
- package/flowquery-py/src/parsing/operations/create_relationship.py +34 -0
- package/flowquery-py/src/parsing/operations/group_by.py +130 -0
- package/flowquery-py/src/parsing/operations/limit.py +22 -0
- package/flowquery-py/src/parsing/operations/load.py +140 -0
- package/flowquery-py/src/parsing/operations/match.py +29 -0
- package/flowquery-py/src/parsing/operations/operation.py +69 -0
- package/flowquery-py/src/parsing/operations/projection.py +21 -0
- package/flowquery-py/src/parsing/operations/return_op.py +50 -0
- package/flowquery-py/src/parsing/operations/unwind.py +37 -0
- package/flowquery-py/src/parsing/operations/where.py +41 -0
- package/flowquery-py/src/parsing/operations/with_op.py +18 -0
- package/flowquery-py/src/parsing/parser.py +1011 -0
- package/flowquery-py/src/parsing/token_to_node.py +109 -0
- package/flowquery-py/src/tokenization/__init__.py +23 -0
- package/flowquery-py/src/tokenization/keyword.py +48 -0
- package/flowquery-py/src/tokenization/operator.py +29 -0
- package/flowquery-py/src/tokenization/string_walker.py +158 -0
- package/flowquery-py/src/tokenization/symbol.py +19 -0
- package/flowquery-py/src/tokenization/token.py +659 -0
- package/flowquery-py/src/tokenization/token_mapper.py +52 -0
- package/flowquery-py/src/tokenization/token_type.py +21 -0
- package/flowquery-py/src/tokenization/tokenizer.py +214 -0
- package/flowquery-py/src/tokenization/trie.py +124 -0
- package/flowquery-py/src/utils/__init__.py +6 -0
- package/flowquery-py/src/utils/object_utils.py +20 -0
- package/flowquery-py/src/utils/string_utils.py +113 -0
- package/flowquery-py/tests/__init__.py +1 -0
- package/flowquery-py/tests/compute/__init__.py +1 -0
- package/flowquery-py/tests/compute/test_runner.py +1335 -0
- package/flowquery-py/tests/graph/__init__.py +1 -0
- package/flowquery-py/tests/graph/test_create.py +56 -0
- package/flowquery-py/tests/graph/test_data.py +73 -0
- package/flowquery-py/tests/graph/test_match.py +40 -0
- package/flowquery-py/tests/parsing/__init__.py +1 -0
- package/flowquery-py/tests/parsing/test_context.py +34 -0
- package/flowquery-py/tests/parsing/test_expression.py +49 -0
- package/flowquery-py/tests/parsing/test_parser.py +674 -0
- package/flowquery-py/tests/test_extensibility.py +611 -0
- package/flowquery-py/tests/tokenization/__init__.py +1 -0
- package/flowquery-py/tests/tokenization/test_token_mapper.py +60 -0
- package/flowquery-py/tests/tokenization/test_tokenizer.py +164 -0
- package/flowquery-py/tests/tokenization/test_trie.py +30 -0
- package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
- package/misc/apps/RAG/package.json +1 -1
- package/misc/apps/RAG/src/components/AdaptiveCardRenderer.tsx +76 -8
- package/misc/apps/RAG/src/components/index.ts +19 -10
- package/misc/apps/RAG/src/plugins/loaders/MockData.ts +70 -140
- package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +12 -0
- package/package.json +1 -1
- package/src/compute/runner.ts +24 -19
- package/src/graph/data.ts +112 -0
- package/src/graph/database.ts +63 -0
- package/src/graph/hops.ts +22 -0
- package/src/graph/node.ts +99 -0
- package/src/graph/node_data.ts +18 -0
- package/src/graph/node_reference.ts +33 -0
- package/src/graph/pattern.ts +101 -0
- package/src/graph/pattern_expression.ts +37 -0
- package/src/graph/patterns.ts +36 -0
- package/src/graph/physical_node.ts +23 -0
- package/src/graph/physical_relationship.ts +23 -0
- package/src/graph/relationship.ts +116 -0
- package/src/graph/relationship_data.ts +27 -0
- package/src/graph/relationship_match_collector.ts +58 -0
- package/src/graph/relationship_reference.ts +24 -0
- package/src/parsing/base_parser.ts +20 -14
- package/src/parsing/context.ts +14 -14
- package/src/parsing/expressions/boolean.ts +21 -0
- package/src/parsing/expressions/expression.ts +34 -26
- package/src/parsing/expressions/operator.ts +19 -1
- package/src/parsing/functions/function_factory.ts +45 -45
- package/src/parsing/operations/create_node.ts +39 -0
- package/src/parsing/operations/create_relationship.ts +38 -0
- package/src/parsing/operations/match.ts +31 -0
- package/src/parsing/operations/operation.ts +3 -0
- package/src/parsing/operations/return.ts +11 -7
- package/src/parsing/operations/where.ts +10 -6
- package/src/parsing/parser.ts +346 -8
- package/src/parsing/token_to_node.ts +6 -0
- package/src/tokenization/keyword.ts +41 -40
- package/src/tokenization/token.ts +21 -1
- package/src/tokenization/token_type.ts +2 -1
- package/src/tokenization/tokenizer.ts +52 -31
- package/tests/compute/runner.test.ts +654 -0
- package/tests/extensibility.test.ts +97 -93
- package/tests/graph/create.test.ts +36 -0
- package/tests/graph/data.test.ts +58 -0
- package/tests/graph/match.test.ts +29 -0
- package/tests/parsing/parser.test.ts +273 -2
- package/tests/tokenization/tokenizer.test.ts +90 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import Runner from "../../src/compute/runner";
|
|
2
|
+
import Database from "../../src/graph/database";
|
|
3
|
+
import Node from "../../src/graph/node";
|
|
2
4
|
import AsyncFunction from "../../src/parsing/functions/async_function";
|
|
3
5
|
import { FunctionDef } from "../../src/parsing/functions/function_metadata";
|
|
4
6
|
|
|
@@ -636,3 +638,655 @@ test("Test call operation with no yielded expressions", async () => {
|
|
|
636
638
|
const runner = new Runner("CALL calltestfunctionnoobject() RETURN 1");
|
|
637
639
|
}).toThrow("CALL operations must have a YIELD clause unless they are the last operation");
|
|
638
640
|
});
|
|
641
|
+
|
|
642
|
+
test("Test create node operation", async () => {
|
|
643
|
+
const db = Database.getInstance();
|
|
644
|
+
const runner = new Runner(`
|
|
645
|
+
CREATE VIRTUAL (:Person) AS {
|
|
646
|
+
with 1 as x
|
|
647
|
+
RETURN x
|
|
648
|
+
}
|
|
649
|
+
`);
|
|
650
|
+
await runner.run();
|
|
651
|
+
const results = runner.results;
|
|
652
|
+
expect(results.length).toBe(0);
|
|
653
|
+
expect(db.getNode(new Node(null, "Person"))).not.toBeNull();
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
test("Test create node and match operations", async () => {
|
|
657
|
+
const create = new Runner(`
|
|
658
|
+
CREATE VIRTUAL (:Person) AS {
|
|
659
|
+
unwind [
|
|
660
|
+
{id: 1, name: 'Person 1'},
|
|
661
|
+
{id: 2, name: 'Person 2'}
|
|
662
|
+
] as record
|
|
663
|
+
RETURN record.id as id, record.name as name
|
|
664
|
+
}
|
|
665
|
+
`);
|
|
666
|
+
await create.run();
|
|
667
|
+
const match = new Runner("MATCH (n:Person) RETURN n");
|
|
668
|
+
await match.run();
|
|
669
|
+
const results = match.results;
|
|
670
|
+
expect(results.length).toBe(2);
|
|
671
|
+
expect(results[0].n).toBeDefined();
|
|
672
|
+
expect(results[0].n.id).toBe(1);
|
|
673
|
+
expect(results[0].n.name).toBe("Person 1");
|
|
674
|
+
expect(results[1].n).toBeDefined();
|
|
675
|
+
expect(results[1].n.id).toBe(2);
|
|
676
|
+
expect(results[1].n.name).toBe("Person 2");
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
test("Test complex match operation", async () => {
|
|
680
|
+
await new Runner(`
|
|
681
|
+
CREATE VIRTUAL (:Person) AS {
|
|
682
|
+
unwind [
|
|
683
|
+
{id: 1, name: 'Person 1', age: 30},
|
|
684
|
+
{id: 2, name: 'Person 2', age: 25},
|
|
685
|
+
{id: 3, name: 'Person 3', age: 35}
|
|
686
|
+
] as record
|
|
687
|
+
RETURN record.id as id, record.name as name, record.age as age
|
|
688
|
+
}
|
|
689
|
+
`).run();
|
|
690
|
+
const match = new Runner(`
|
|
691
|
+
MATCH (n:Person)
|
|
692
|
+
WHERE n.age > 29
|
|
693
|
+
RETURN n.name AS name, n.age AS age
|
|
694
|
+
`);
|
|
695
|
+
await match.run();
|
|
696
|
+
const results = match.results;
|
|
697
|
+
expect(results.length).toBe(2);
|
|
698
|
+
expect(results[0]).toEqual({ name: "Person 1", age: 30 });
|
|
699
|
+
expect(results[1]).toEqual({ name: "Person 3", age: 35 });
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
test("Test match", async () => {
|
|
703
|
+
await new Runner(`
|
|
704
|
+
CREATE VIRTUAL (:Person) AS {
|
|
705
|
+
unwind [
|
|
706
|
+
{id: 1, name: 'Person 1'},
|
|
707
|
+
{id: 2, name: 'Person 2'}
|
|
708
|
+
] as record
|
|
709
|
+
RETURN record.id as id, record.name as name
|
|
710
|
+
}
|
|
711
|
+
`).run();
|
|
712
|
+
const match = new Runner(`
|
|
713
|
+
MATCH (n:Person)
|
|
714
|
+
RETURN n.name AS name
|
|
715
|
+
`);
|
|
716
|
+
await match.run();
|
|
717
|
+
const results = match.results;
|
|
718
|
+
expect(results.length).toBe(2);
|
|
719
|
+
expect(results[0]).toEqual({ name: "Person 1" });
|
|
720
|
+
expect(results[1]).toEqual({ name: "Person 2" });
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
test("Test match with nested join", async () => {
|
|
724
|
+
await new Runner(`
|
|
725
|
+
CREATE VIRTUAL (:Person) AS {
|
|
726
|
+
unwind [
|
|
727
|
+
{id: 1, name: 'Person 1'},
|
|
728
|
+
{id: 2, name: 'Person 2'}
|
|
729
|
+
] as record
|
|
730
|
+
RETURN record.id as id, record.name as name
|
|
731
|
+
}
|
|
732
|
+
`).run();
|
|
733
|
+
const match = new Runner(`
|
|
734
|
+
MATCH (a:Person), (b:Person)
|
|
735
|
+
WHERE a.id <> b.id
|
|
736
|
+
RETURN a.name AS name1, b.name AS name2
|
|
737
|
+
`);
|
|
738
|
+
await match.run();
|
|
739
|
+
const results = match.results;
|
|
740
|
+
expect(results.length).toBe(2);
|
|
741
|
+
expect(results[0]).toEqual({ name1: "Person 1", name2: "Person 2" });
|
|
742
|
+
expect(results[1]).toEqual({ name1: "Person 2", name2: "Person 1" });
|
|
743
|
+
});
|
|
744
|
+
|
|
745
|
+
test("Test match with graph pattern", async () => {
|
|
746
|
+
await new Runner(`
|
|
747
|
+
CREATE VIRTUAL (:User) AS {
|
|
748
|
+
UNWIND [
|
|
749
|
+
{id: 1, name: 'User 1', manager_id: null},
|
|
750
|
+
{id: 2, name: 'User 2', manager_id: 1},
|
|
751
|
+
{id: 3, name: 'User 3', manager_id: 1},
|
|
752
|
+
{id: 4, name: 'User 4', manager_id: 2}
|
|
753
|
+
] AS record
|
|
754
|
+
RETURN record.id AS id, record.name AS name, record.manager_id AS manager_id
|
|
755
|
+
}
|
|
756
|
+
`).run();
|
|
757
|
+
await new Runner(`
|
|
758
|
+
CREATE VIRTUAL (:User)-[:MANAGED_BY]-(:User) AS {
|
|
759
|
+
UNWIND [
|
|
760
|
+
{id: 1, manager_id: null},
|
|
761
|
+
{id: 2, manager_id: 1},
|
|
762
|
+
{id: 3, manager_id: 1},
|
|
763
|
+
{id: 4, manager_id: 2}
|
|
764
|
+
] AS record
|
|
765
|
+
RETURN record.id AS left_id, record.manager_id AS right_id
|
|
766
|
+
}
|
|
767
|
+
`).run();
|
|
768
|
+
const match = new Runner(`
|
|
769
|
+
MATCH (user:User)-[r:MANAGED_BY]-(manager:User)
|
|
770
|
+
RETURN user.name AS user, manager.name AS manager
|
|
771
|
+
`);
|
|
772
|
+
await match.run();
|
|
773
|
+
const results = match.results;
|
|
774
|
+
expect(results.length).toBe(3);
|
|
775
|
+
expect(results[0]).toEqual({ user: "User 2", manager: "User 1" });
|
|
776
|
+
expect(results[1]).toEqual({ user: "User 3", manager: "User 1" });
|
|
777
|
+
expect(results[2]).toEqual({ user: "User 4", manager: "User 2" });
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
test("Test match with multiple hop graph pattern", async () => {
|
|
781
|
+
await new Runner(`
|
|
782
|
+
CREATE VIRTUAL (:Person) AS {
|
|
783
|
+
unwind [
|
|
784
|
+
{id: 1, name: 'Person 1'},
|
|
785
|
+
{id: 2, name: 'Person 2'},
|
|
786
|
+
{id: 3, name: 'Person 3'},
|
|
787
|
+
{id: 4, name: 'Person 4'}
|
|
788
|
+
] as record
|
|
789
|
+
RETURN record.id as id, record.name as name
|
|
790
|
+
}
|
|
791
|
+
`).run();
|
|
792
|
+
await new Runner(`
|
|
793
|
+
CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
|
|
794
|
+
unwind [
|
|
795
|
+
{left_id: 1, right_id: 2},
|
|
796
|
+
{left_id: 2, right_id: 3}
|
|
797
|
+
] as record
|
|
798
|
+
RETURN record.left_id as left_id, record.right_id as right_id
|
|
799
|
+
}
|
|
800
|
+
`).run();
|
|
801
|
+
const match = new Runner(`
|
|
802
|
+
MATCH (a:Person)-[:KNOWS*]-(c:Person)
|
|
803
|
+
RETURN a.name AS name1, c.name AS name2
|
|
804
|
+
`);
|
|
805
|
+
await match.run();
|
|
806
|
+
const results = match.results;
|
|
807
|
+
expect(results.length).toBe(3);
|
|
808
|
+
expect(results[0]).toEqual({ name1: "Person 1", name2: "Person 2" });
|
|
809
|
+
expect(results[1]).toEqual({ name1: "Person 1", name2: "Person 3" });
|
|
810
|
+
expect(results[2]).toEqual({ name1: "Person 2", name2: "Person 3" });
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
test("Test match with double graph pattern", async () => {
|
|
814
|
+
await new Runner(`
|
|
815
|
+
CREATE VIRTUAL (:Person) AS {
|
|
816
|
+
unwind [
|
|
817
|
+
{id: 1, name: 'Person 1'},
|
|
818
|
+
{id: 2, name: 'Person 2'},
|
|
819
|
+
{id: 3, name: 'Person 3'},
|
|
820
|
+
{id: 4, name: 'Person 4'}
|
|
821
|
+
] as record
|
|
822
|
+
RETURN record.id as id, record.name as name
|
|
823
|
+
}
|
|
824
|
+
`).run();
|
|
825
|
+
await new Runner(`
|
|
826
|
+
CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
|
|
827
|
+
unwind [
|
|
828
|
+
{left_id: 1, right_id: 2},
|
|
829
|
+
{left_id: 2, right_id: 3},
|
|
830
|
+
{left_id: 3, right_id: 4}
|
|
831
|
+
] as record
|
|
832
|
+
RETURN record.left_id as left_id, record.right_id as right_id
|
|
833
|
+
}
|
|
834
|
+
`).run();
|
|
835
|
+
const match = new Runner(`
|
|
836
|
+
MATCH (a:Person)-[:KNOWS]-(b:Person)-[:KNOWS]-(c:Person)
|
|
837
|
+
RETURN a.name AS name1, b.name AS name2, c.name AS name3
|
|
838
|
+
`);
|
|
839
|
+
await match.run();
|
|
840
|
+
const results = match.results;
|
|
841
|
+
expect(results.length).toBe(2);
|
|
842
|
+
expect(results[0]).toEqual({ name1: "Person 1", name2: "Person 2", name3: "Person 3" });
|
|
843
|
+
expect(results[1]).toEqual({ name1: "Person 2", name2: "Person 3", name3: "Person 4" });
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
test("Test match with referenced to previous variable", async () => {
|
|
847
|
+
await new Runner(`
|
|
848
|
+
CREATE VIRTUAL (:Person) AS {
|
|
849
|
+
unwind [
|
|
850
|
+
{id: 1, name: 'Person 1'},
|
|
851
|
+
{id: 2, name: 'Person 2'},
|
|
852
|
+
{id: 3, name: 'Person 3'},
|
|
853
|
+
{id: 4, name: 'Person 4'}
|
|
854
|
+
] as record
|
|
855
|
+
RETURN record.id as id, record.name as name
|
|
856
|
+
}
|
|
857
|
+
`).run();
|
|
858
|
+
await new Runner(`
|
|
859
|
+
CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
|
|
860
|
+
unwind [
|
|
861
|
+
{left_id: 1, right_id: 2},
|
|
862
|
+
{left_id: 2, right_id: 3},
|
|
863
|
+
{left_id: 3, right_id: 4}
|
|
864
|
+
] as record
|
|
865
|
+
RETURN record.left_id as left_id, record.right_id as right_id
|
|
866
|
+
}
|
|
867
|
+
`).run();
|
|
868
|
+
const match = new Runner(`
|
|
869
|
+
MATCH (a:Person)-[:KNOWS]-(b:Person)
|
|
870
|
+
MATCH (b)-[:KNOWS]-(c:Person)
|
|
871
|
+
RETURN a.name AS name1, b.name AS name2, c.name AS name3
|
|
872
|
+
`);
|
|
873
|
+
await match.run();
|
|
874
|
+
const results = match.results;
|
|
875
|
+
expect(results.length).toBe(2);
|
|
876
|
+
expect(results[0]).toEqual({ name1: "Person 1", name2: "Person 2", name3: "Person 3" });
|
|
877
|
+
expect(results[1]).toEqual({ name1: "Person 2", name2: "Person 3", name3: "Person 4" });
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
test("Test match and return full node", async () => {
|
|
881
|
+
await new Runner(`
|
|
882
|
+
CREATE VIRTUAL (:Person) AS {
|
|
883
|
+
unwind [
|
|
884
|
+
{id: 1, name: 'Person 1'},
|
|
885
|
+
{id: 2, name: 'Person 2'}
|
|
886
|
+
] as record
|
|
887
|
+
RETURN record.id as id, record.name as name
|
|
888
|
+
}
|
|
889
|
+
`).run();
|
|
890
|
+
const match = new Runner(`
|
|
891
|
+
MATCH (n:Person)
|
|
892
|
+
RETURN n
|
|
893
|
+
`);
|
|
894
|
+
await match.run();
|
|
895
|
+
const results = match.results;
|
|
896
|
+
expect(results.length).toBe(2);
|
|
897
|
+
expect(results[0].n).toBeDefined();
|
|
898
|
+
expect(results[0].n.id).toBe(1);
|
|
899
|
+
expect(results[0].n.name).toBe("Person 1");
|
|
900
|
+
expect(results[1].n).toBeDefined();
|
|
901
|
+
expect(results[1].n.id).toBe(2);
|
|
902
|
+
expect(results[1].n.name).toBe("Person 2");
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
test("Test return graph pattern", async () => {
|
|
906
|
+
await new Runner(`
|
|
907
|
+
CREATE VIRTUAL (:Person) AS {
|
|
908
|
+
unwind [
|
|
909
|
+
{id: 1, name: 'Person 1'},
|
|
910
|
+
{id: 2, name: 'Person 2'}
|
|
911
|
+
] as record
|
|
912
|
+
RETURN record.id as id, record.name as name
|
|
913
|
+
}
|
|
914
|
+
`).run();
|
|
915
|
+
await new Runner(`
|
|
916
|
+
CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
|
|
917
|
+
unwind [
|
|
918
|
+
{left_id: 1, since: "2020-01-01", right_id: 2}
|
|
919
|
+
] as record
|
|
920
|
+
RETURN record.left_id as left_id, record.since as since, record.right_id as right_id
|
|
921
|
+
}
|
|
922
|
+
`).run();
|
|
923
|
+
const match = new Runner(`
|
|
924
|
+
MATCH p=(:Person)-[:KNOWS]-(:Person)
|
|
925
|
+
RETURN p AS pattern
|
|
926
|
+
`);
|
|
927
|
+
await match.run();
|
|
928
|
+
const results = match.results;
|
|
929
|
+
expect(results.length).toBe(1);
|
|
930
|
+
expect(results[0].pattern).toBeDefined();
|
|
931
|
+
expect(results[0].pattern.length).toBe(3);
|
|
932
|
+
expect(results[0].pattern[0].id).toBe(1);
|
|
933
|
+
expect(results[0].pattern[1].properties.since).toBe("2020-01-01");
|
|
934
|
+
expect(results[0].pattern[2].id).toBe(2);
|
|
935
|
+
});
|
|
936
|
+
|
|
937
|
+
test("Test circular graph pattern", async () => {
|
|
938
|
+
await new Runner(`
|
|
939
|
+
CREATE VIRTUAL (:Person) AS {
|
|
940
|
+
unwind [
|
|
941
|
+
{id: 1, name: 'Person 1'},
|
|
942
|
+
{id: 2, name: 'Person 2'}
|
|
943
|
+
] as record
|
|
944
|
+
RETURN record.id as id, record.name as name
|
|
945
|
+
}
|
|
946
|
+
`).run();
|
|
947
|
+
await new Runner(`
|
|
948
|
+
CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
|
|
949
|
+
unwind [
|
|
950
|
+
{left_id: 1, right_id: 2},
|
|
951
|
+
{left_id: 2, right_id: 1}
|
|
952
|
+
] as record
|
|
953
|
+
RETURN record.left_id as left_id, record.right_id as right_id
|
|
954
|
+
}
|
|
955
|
+
`).run();
|
|
956
|
+
const match = new Runner(`
|
|
957
|
+
MATCH p=(:Person)-[:KNOWS]-(:Person)-[:KNOWS]-(:Person)
|
|
958
|
+
RETURN p AS pattern
|
|
959
|
+
`);
|
|
960
|
+
await match.run();
|
|
961
|
+
const results = match.results;
|
|
962
|
+
expect(results.length).toBe(2);
|
|
963
|
+
expect(results[0].pattern).toBeDefined();
|
|
964
|
+
expect(results[0].pattern.length).toBe(5);
|
|
965
|
+
expect(results[0].pattern[0].id).toBe(1);
|
|
966
|
+
expect(results[0].pattern[1].id).toBeUndefined();
|
|
967
|
+
expect(results[0].pattern[2].id).toBe(2);
|
|
968
|
+
expect(results[0].pattern[3].id).toBeUndefined();
|
|
969
|
+
expect(results[0].pattern[4].id).toBe(1);
|
|
970
|
+
});
|
|
971
|
+
|
|
972
|
+
test("Test circular graph pattern with variable length should throw error", async () => {
|
|
973
|
+
await new Runner(`
|
|
974
|
+
CREATE VIRTUAL (:Person) AS {
|
|
975
|
+
unwind [
|
|
976
|
+
{id: 1, name: 'Person 1'},
|
|
977
|
+
{id: 2, name: 'Person 2'}
|
|
978
|
+
] as record
|
|
979
|
+
RETURN record.id as id, record.name as name
|
|
980
|
+
}
|
|
981
|
+
`).run();
|
|
982
|
+
await new Runner(`
|
|
983
|
+
CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
|
|
984
|
+
unwind [
|
|
985
|
+
{left_id: 1, right_id: 2},
|
|
986
|
+
{left_id: 2, right_id: 1}
|
|
987
|
+
] as record
|
|
988
|
+
RETURN record.left_id as left_id, record.right_id as right_id
|
|
989
|
+
}
|
|
990
|
+
`).run();
|
|
991
|
+
const match = new Runner(`
|
|
992
|
+
MATCH p=(:Person)-[:KNOWS*]-(:Person)
|
|
993
|
+
RETURN p AS pattern
|
|
994
|
+
`);
|
|
995
|
+
await expect(async () => {
|
|
996
|
+
await match.run();
|
|
997
|
+
}).rejects.toThrow("Circular relationship detected");
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
test("Test multi-hop match with variable length relationships", async () => {
|
|
1001
|
+
await new Runner(`
|
|
1002
|
+
CREATE VIRTUAL (:Person) AS {
|
|
1003
|
+
unwind [
|
|
1004
|
+
{id: 1, name: 'Person 1'},
|
|
1005
|
+
{id: 2, name: 'Person 2'},
|
|
1006
|
+
{id: 3, name: 'Person 3'},
|
|
1007
|
+
{id: 4, name: 'Person 4'}
|
|
1008
|
+
] as record
|
|
1009
|
+
RETURN record.id as id, record.name as name
|
|
1010
|
+
}
|
|
1011
|
+
`).run();
|
|
1012
|
+
await new Runner(`
|
|
1013
|
+
CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
|
|
1014
|
+
unwind [
|
|
1015
|
+
{left_id: 1, right_id: 2},
|
|
1016
|
+
{left_id: 2, right_id: 3},
|
|
1017
|
+
{left_id: 3, right_id: 4}
|
|
1018
|
+
] as record
|
|
1019
|
+
RETURN record.left_id as left_id, record.right_id as right_id
|
|
1020
|
+
}
|
|
1021
|
+
`).run();
|
|
1022
|
+
const match = new Runner(`
|
|
1023
|
+
MATCH (a:Person)-[r:KNOWS*0..3]->(b:Person)
|
|
1024
|
+
RETURN a, r, b
|
|
1025
|
+
`);
|
|
1026
|
+
await match.run();
|
|
1027
|
+
const results = match.results;
|
|
1028
|
+
expect(results.length).toBe(6);
|
|
1029
|
+
|
|
1030
|
+
expect(results[0].a.id).toBe(1);
|
|
1031
|
+
expect(results[0].b.id).toBe(2);
|
|
1032
|
+
expect(results[0].r.length).toBe(undefined);
|
|
1033
|
+
expect(results[0].r.startNode.id).toBe(1);
|
|
1034
|
+
expect(results[0].r.endNode.id).toBe(2);
|
|
1035
|
+
|
|
1036
|
+
expect(results[1].a.id).toBe(1);
|
|
1037
|
+
expect(results[1].b.id).toBe(3);
|
|
1038
|
+
expect(results[1].r.length).toBe(2);
|
|
1039
|
+
expect(results[1].r[0].startNode.id).toBe(1);
|
|
1040
|
+
expect(results[1].r[0].endNode.id).toBe(2);
|
|
1041
|
+
expect(results[1].r[1].startNode.id).toBe(2);
|
|
1042
|
+
expect(results[1].r[1].endNode.id).toBe(3);
|
|
1043
|
+
|
|
1044
|
+
expect(results[2].a.id).toBe(1);
|
|
1045
|
+
expect(results[2].b.id).toBe(4);
|
|
1046
|
+
expect(results[2].r.length).toBe(3);
|
|
1047
|
+
expect(results[2].r[0].startNode.id).toBe(1);
|
|
1048
|
+
expect(results[2].r[0].endNode.id).toBe(2);
|
|
1049
|
+
expect(results[2].r[1].startNode.id).toBe(2);
|
|
1050
|
+
expect(results[2].r[1].endNode.id).toBe(3);
|
|
1051
|
+
expect(results[2].r[2].startNode.id).toBe(3);
|
|
1052
|
+
expect(results[2].r[2].endNode.id).toBe(4);
|
|
1053
|
+
|
|
1054
|
+
expect(results[3].a.id).toBe(2);
|
|
1055
|
+
expect(results[3].b.id).toBe(3);
|
|
1056
|
+
expect(results[3].r.length).toBe(undefined);
|
|
1057
|
+
expect(results[3].r.startNode.id).toBe(2);
|
|
1058
|
+
expect(results[3].r.endNode.id).toBe(3);
|
|
1059
|
+
|
|
1060
|
+
expect(results[4].a.id).toBe(2);
|
|
1061
|
+
expect(results[4].b.id).toBe(4);
|
|
1062
|
+
expect(results[4].r.length).toBe(2);
|
|
1063
|
+
expect(results[4].r[0].startNode.id).toBe(2);
|
|
1064
|
+
expect(results[4].r[0].endNode.id).toBe(3);
|
|
1065
|
+
expect(results[4].r[1].startNode.id).toBe(3);
|
|
1066
|
+
expect(results[4].r[1].endNode.id).toBe(4);
|
|
1067
|
+
|
|
1068
|
+
expect(results[5].a.id).toBe(3);
|
|
1069
|
+
expect(results[5].b.id).toBe(4);
|
|
1070
|
+
expect(results[5].r.length).toBe(undefined);
|
|
1071
|
+
expect(results[5].r.startNode.id).toBe(3);
|
|
1072
|
+
expect(results[5].r.endNode.id).toBe(4);
|
|
1073
|
+
});
|
|
1074
|
+
|
|
1075
|
+
test("Test return match pattern with variable length relationships", async () => {
|
|
1076
|
+
await new Runner(`
|
|
1077
|
+
CREATE VIRTUAL (:Person) AS {
|
|
1078
|
+
unwind [
|
|
1079
|
+
{id: 1, name: 'Person 1'},
|
|
1080
|
+
{id: 2, name: 'Person 2'},
|
|
1081
|
+
{id: 3, name: 'Person 3'},
|
|
1082
|
+
{id: 4, name: 'Person 4'}
|
|
1083
|
+
] as record
|
|
1084
|
+
RETURN record.id as id, record.name as name
|
|
1085
|
+
}
|
|
1086
|
+
`).run();
|
|
1087
|
+
await new Runner(`
|
|
1088
|
+
CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
|
|
1089
|
+
unwind [
|
|
1090
|
+
{left_id: 1, right_id: 2},
|
|
1091
|
+
{left_id: 2, right_id: 3},
|
|
1092
|
+
{left_id: 3, right_id: 4}
|
|
1093
|
+
] as record
|
|
1094
|
+
RETURN record.left_id as left_id, record.right_id as right_id
|
|
1095
|
+
}
|
|
1096
|
+
`).run();
|
|
1097
|
+
const match = new Runner(`
|
|
1098
|
+
MATCH p=(a:Person)-[:KNOWS*0..3]->(b:Person)
|
|
1099
|
+
RETURN p AS pattern
|
|
1100
|
+
`);
|
|
1101
|
+
await match.run();
|
|
1102
|
+
const results = match.results;
|
|
1103
|
+
expect(results.length).toBe(6);
|
|
1104
|
+
|
|
1105
|
+
expect(results[0].pattern.length).toBe(3);
|
|
1106
|
+
expect(results[0].pattern[0].id).toBe(1);
|
|
1107
|
+
expect(results[0].pattern[1].startNode.id).toBe(1);
|
|
1108
|
+
expect(results[0].pattern[1].endNode.id).toBe(2);
|
|
1109
|
+
expect(results[0].pattern[2].id).toBe(2);
|
|
1110
|
+
|
|
1111
|
+
expect(results[1].pattern.length).toBe(5);
|
|
1112
|
+
expect(results[1].pattern[0].id).toBe(1);
|
|
1113
|
+
expect(results[1].pattern[1].startNode.id).toBe(1);
|
|
1114
|
+
expect(results[1].pattern[1].endNode.id).toBe(2);
|
|
1115
|
+
expect(results[1].pattern[2].id).toBe(2);
|
|
1116
|
+
expect(results[1].pattern[3].startNode.id).toBe(2);
|
|
1117
|
+
expect(results[1].pattern[3].endNode.id).toBe(3);
|
|
1118
|
+
expect(results[1].pattern[4].id).toBe(3);
|
|
1119
|
+
|
|
1120
|
+
expect(results[2].pattern.length).toBe(7);
|
|
1121
|
+
expect(results[2].pattern[0].id).toBe(1);
|
|
1122
|
+
expect(results[2].pattern[1].startNode.id).toBe(1);
|
|
1123
|
+
expect(results[2].pattern[1].endNode.id).toBe(2);
|
|
1124
|
+
expect(results[2].pattern[2].id).toBe(2);
|
|
1125
|
+
expect(results[2].pattern[3].startNode.id).toBe(2);
|
|
1126
|
+
expect(results[2].pattern[3].endNode.id).toBe(3);
|
|
1127
|
+
expect(results[2].pattern[4].id).toBe(3);
|
|
1128
|
+
expect(results[2].pattern[5].startNode.id).toBe(3);
|
|
1129
|
+
expect(results[2].pattern[5].endNode.id).toBe(4);
|
|
1130
|
+
expect(results[2].pattern[6].id).toBe(4);
|
|
1131
|
+
|
|
1132
|
+
expect(results[3].pattern.length).toBe(3);
|
|
1133
|
+
expect(results[3].pattern[0].id).toBe(2);
|
|
1134
|
+
expect(results[3].pattern[1].startNode.id).toBe(2);
|
|
1135
|
+
expect(results[3].pattern[1].endNode.id).toBe(3);
|
|
1136
|
+
expect(results[3].pattern[2].id).toBe(3);
|
|
1137
|
+
|
|
1138
|
+
expect(results[4].pattern.length).toBe(5);
|
|
1139
|
+
expect(results[4].pattern[0].id).toBe(2);
|
|
1140
|
+
expect(results[4].pattern[1].startNode.id).toBe(2);
|
|
1141
|
+
expect(results[4].pattern[1].endNode.id).toBe(3);
|
|
1142
|
+
expect(results[4].pattern[2].id).toBe(3);
|
|
1143
|
+
expect(results[4].pattern[3].startNode.id).toBe(3);
|
|
1144
|
+
expect(results[4].pattern[3].endNode.id).toBe(4);
|
|
1145
|
+
expect(results[4].pattern[4].id).toBe(4);
|
|
1146
|
+
|
|
1147
|
+
expect(results[5].pattern.length).toBe(3);
|
|
1148
|
+
expect(results[5].pattern[0].id).toBe(3);
|
|
1149
|
+
expect(results[5].pattern[1].startNode.id).toBe(3);
|
|
1150
|
+
expect(results[5].pattern[1].endNode.id).toBe(4);
|
|
1151
|
+
expect(results[5].pattern[2].id).toBe(4);
|
|
1152
|
+
});
|
|
1153
|
+
|
|
1154
|
+
test("Test statement with graph pattern in where clause", async () => {
|
|
1155
|
+
await new Runner(`
|
|
1156
|
+
CREATE VIRTUAL (:Person) AS {
|
|
1157
|
+
unwind [
|
|
1158
|
+
{id: 1, name: 'Person 1'},
|
|
1159
|
+
{id: 2, name: 'Person 2'},
|
|
1160
|
+
{id: 3, name: 'Person 3'},
|
|
1161
|
+
{id: 4, name: 'Person 4'}
|
|
1162
|
+
] as record
|
|
1163
|
+
RETURN record.id as id, record.name as name
|
|
1164
|
+
}
|
|
1165
|
+
`).run();
|
|
1166
|
+
await new Runner(`
|
|
1167
|
+
CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
|
|
1168
|
+
unwind [
|
|
1169
|
+
{left_id: 1, right_id: 2},
|
|
1170
|
+
{left_id: 2, right_id: 3},
|
|
1171
|
+
{left_id: 3, right_id: 4}
|
|
1172
|
+
] as record
|
|
1173
|
+
RETURN record.left_id as left_id, record.right_id as right_id
|
|
1174
|
+
}
|
|
1175
|
+
`).run();
|
|
1176
|
+
// Test positive match
|
|
1177
|
+
const match = new Runner(`
|
|
1178
|
+
MATCH (a:Person), (b:Person)
|
|
1179
|
+
WHERE (a)-[:KNOWS]->(b)
|
|
1180
|
+
RETURN a.name AS name1, b.name AS name2
|
|
1181
|
+
`);
|
|
1182
|
+
await match.run();
|
|
1183
|
+
const results = match.results;
|
|
1184
|
+
expect(results.length).toBe(3);
|
|
1185
|
+
expect(results[0]).toEqual({ name1: "Person 1", name2: "Person 2" });
|
|
1186
|
+
expect(results[1]).toEqual({ name1: "Person 2", name2: "Person 3" });
|
|
1187
|
+
expect(results[2]).toEqual({ name1: "Person 3", name2: "Person 4" });
|
|
1188
|
+
|
|
1189
|
+
// Test negative match
|
|
1190
|
+
const nomatch = new Runner(`
|
|
1191
|
+
MATCH (a:Person), (b:Person)
|
|
1192
|
+
WHERE (a)-[:KNOWS]->(b) <> true
|
|
1193
|
+
RETURN a.name AS name1, b.name AS name2
|
|
1194
|
+
`);
|
|
1195
|
+
await nomatch.run();
|
|
1196
|
+
const noresults = nomatch.results;
|
|
1197
|
+
expect(noresults.length).toBe(13);
|
|
1198
|
+
expect(noresults[0]).toEqual({ name1: "Person 1", name2: "Person 1" });
|
|
1199
|
+
expect(noresults[1]).toEqual({ name1: "Person 1", name2: "Person 3" });
|
|
1200
|
+
expect(noresults[2]).toEqual({ name1: "Person 1", name2: "Person 4" });
|
|
1201
|
+
expect(noresults[3]).toEqual({ name1: "Person 2", name2: "Person 1" });
|
|
1202
|
+
expect(noresults[4]).toEqual({ name1: "Person 2", name2: "Person 2" });
|
|
1203
|
+
expect(noresults[5]).toEqual({ name1: "Person 2", name2: "Person 4" });
|
|
1204
|
+
expect(noresults[6]).toEqual({ name1: "Person 3", name2: "Person 1" });
|
|
1205
|
+
expect(noresults[7]).toEqual({ name1: "Person 3", name2: "Person 2" });
|
|
1206
|
+
expect(noresults[8]).toEqual({ name1: "Person 3", name2: "Person 3" });
|
|
1207
|
+
expect(noresults[9]).toEqual({ name1: "Person 4", name2: "Person 1" });
|
|
1208
|
+
expect(noresults[10]).toEqual({ name1: "Person 4", name2: "Person 2" });
|
|
1209
|
+
expect(noresults[11]).toEqual({ name1: "Person 4", name2: "Person 3" });
|
|
1210
|
+
expect(noresults[12]).toEqual({ name1: "Person 4", name2: "Person 4" });
|
|
1211
|
+
});
|
|
1212
|
+
|
|
1213
|
+
test("Test person who does not know anyone", async () => {
|
|
1214
|
+
await new Runner(`
|
|
1215
|
+
CREATE VIRTUAL (:Person) AS {
|
|
1216
|
+
unwind [
|
|
1217
|
+
{id: 1, name: 'Person 1'},
|
|
1218
|
+
{id: 2, name: 'Person 2'},
|
|
1219
|
+
{id: 3, name: 'Person 3'}
|
|
1220
|
+
] as record
|
|
1221
|
+
RETURN record.id as id, record.name as name
|
|
1222
|
+
}
|
|
1223
|
+
`).run();
|
|
1224
|
+
await new Runner(`
|
|
1225
|
+
CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
|
|
1226
|
+
unwind [
|
|
1227
|
+
{left_id: 1, right_id: 2},
|
|
1228
|
+
{left_id: 2, right_id: 1}
|
|
1229
|
+
] as record
|
|
1230
|
+
RETURN record.left_id as left_id, record.right_id as right_id
|
|
1231
|
+
}
|
|
1232
|
+
`).run();
|
|
1233
|
+
const match = new Runner(`
|
|
1234
|
+
MATCH (a:Person)
|
|
1235
|
+
WHERE NOT (a)-[:KNOWS]->(:Person)
|
|
1236
|
+
RETURN a.name AS name
|
|
1237
|
+
`);
|
|
1238
|
+
await match.run();
|
|
1239
|
+
const results = match.results;
|
|
1240
|
+
expect(results.length).toBe(1);
|
|
1241
|
+
expect(results[0]).toEqual({ name: "Person 3" });
|
|
1242
|
+
});
|
|
1243
|
+
|
|
1244
|
+
test("Test manager chain", async () => {
|
|
1245
|
+
await new Runner(`
|
|
1246
|
+
CREATE VIRTUAL (:Employee) AS {
|
|
1247
|
+
unwind [
|
|
1248
|
+
{id: 1, name: 'Employee 1'},
|
|
1249
|
+
{id: 2, name: 'Employee 2'},
|
|
1250
|
+
{id: 3, name: 'Employee 3'},
|
|
1251
|
+
{id: 4, name: 'Employee 4'}
|
|
1252
|
+
] as record
|
|
1253
|
+
RETURN record.id as id, record.name as name
|
|
1254
|
+
}
|
|
1255
|
+
`).run();
|
|
1256
|
+
await new Runner(`
|
|
1257
|
+
CREATE VIRTUAL (:Employee)-[:MANAGED_BY]-(:Employee) AS {
|
|
1258
|
+
unwind [
|
|
1259
|
+
{left_id: 2, right_id: 1},
|
|
1260
|
+
{left_id: 3, right_id: 2},
|
|
1261
|
+
{left_id: 4, right_id: 2}
|
|
1262
|
+
] as record
|
|
1263
|
+
RETURN record.left_id as left_id, record.right_id as right_id
|
|
1264
|
+
}
|
|
1265
|
+
`).run();
|
|
1266
|
+
const match = new Runner(`
|
|
1267
|
+
MATCH p=(e:Employee)-[:MANAGED_BY*]->(m:Employee)
|
|
1268
|
+
WHERE NOT (m)-[:MANAGED_BY]->(:Employee)
|
|
1269
|
+
RETURN p
|
|
1270
|
+
`);
|
|
1271
|
+
await match.run();
|
|
1272
|
+
const results = match.results;
|
|
1273
|
+
expect(results.length).toBe(2);
|
|
1274
|
+
});
|
|
1275
|
+
|
|
1276
|
+
test("Test equality comparison", async () => {
|
|
1277
|
+
const runner = new Runner(`
|
|
1278
|
+
unwind range(1,10) as i
|
|
1279
|
+
return i=5 as \`isEqual\`, i<>5 as \`isNotEqual\`
|
|
1280
|
+
`);
|
|
1281
|
+
await runner.run();
|
|
1282
|
+
const results = runner.results;
|
|
1283
|
+
expect(results.length).toBe(10);
|
|
1284
|
+
for (let index = 0; index < results.length; index++) {
|
|
1285
|
+
const result = results[index];
|
|
1286
|
+
if (index + 1 === 5) {
|
|
1287
|
+
expect(result).toEqual({ isEqual: 1, isNotEqual: 0 });
|
|
1288
|
+
} else {
|
|
1289
|
+
expect(result).toEqual({ isEqual: 0, isNotEqual: 1 });
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
});
|