From 71290315cf04ee4d8028ac239791711a34b70b9d Mon Sep 17 00:00:00 2001 From: Tomaz Bratanic Date: Wed, 4 Oct 2023 18:54:37 +0200 Subject: [PATCH] Add optional Cypher validation tool (#11078) LLMs have trouble with consistently getting the relationship direction accurately. That's why I organized a competition how to best and most simple to fix it based on the existing schema as a post-processing step. https://github.com/tomasonjo/cypher-direction-competition I am adding the winner's code in this PR: https://github.com/sakusaku-rich/cypher-direction-competition --- .../more/graph/graph_cypher_qa.ipynb | 80 ++- .../langchain/chains/graph_qa/cypher.py | 23 +- .../langchain/chains/graph_qa/cypher_utils.py | 248 +++++++++ .../tests/unit_tests/chains/test_graph_qa.py | 33 ++ .../unit_tests/data/cypher_corrector.csv | 508 ++++++++++++++++++ 5 files changed, 890 insertions(+), 2 deletions(-) create mode 100644 libs/langchain/langchain/chains/graph_qa/cypher_utils.py create mode 100644 libs/langchain/tests/unit_tests/data/cypher_corrector.csv diff --git a/docs/extras/use_cases/more/graph/graph_cypher_qa.ipynb b/docs/extras/use_cases/more/graph/graph_cypher_qa.ipynb index 11f8cefc83..2a49e7b033 100644 --- a/docs/extras/use_cases/more/graph/graph_cypher_qa.ipynb +++ b/docs/extras/use_cases/more/graph/graph_cypher_qa.ipynb @@ -48,7 +48,16 @@ "execution_count": 2, "id": "0928915d", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/tomaz/neo4j/langchain/libs/langchain/langchain/graphs/neo4j_graph.py:52: ExperimentalWarning: The configuration may change in the future.\n", + " self._driver.verify_connectivity()\n" + ] + } + ], "source": [ "graph = Neo4jGraph(\n", " url=\"bolt://localhost:7687\", username=\"neo4j\", password=\"pleaseletmein\"\n", @@ -558,6 +567,75 @@ "# Inspect graph schema\n", "print(chain.graph_schema)" ] + }, + { + "cell_type": "markdown", + "id": "f0202e88-d700-40ed-aef9-0c969c7bf951", + "metadata": {}, + "source": [ + "# Validate generated Cypher statements\n", + "You can use the `validate_cypher` parameter to validate and correct relationship directions in generated Cypher statements" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "53665d03-7afd-433c-bdd5-750127bfb152", + "metadata": {}, + "outputs": [], + "source": [ + "chain = GraphCypherQAChain.from_llm(\n", + " llm=ChatOpenAI(temperature=0, model=\"gpt-3.5-turbo\"),\n", + " graph=graph,\n", + " verbose=True,\n", + " validate_cypher=True\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "19e1a591-9c10-4d7b-aa36-a5e1b778a97b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (a:Actor)-[:ACTED_IN]->(m:Movie {name: 'Top Gun'})\n", + "RETURN a.name\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'a.name': 'Tom Cruise'}, {'a.name': 'Val Kilmer'}, {'a.name': 'Anthony Edwards'}, {'a.name': 'Meg Ryan'}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'Tom Cruise, Val Kilmer, Anthony Edwards, and Meg Ryan played in Top Gun.'" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"Who played in Top Gun?\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3fa3f3d5-f7e7-4ca9-8f07-ca22b897f192", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/libs/langchain/langchain/chains/graph_qa/cypher.py b/libs/langchain/langchain/chains/graph_qa/cypher.py index bb2dcb0d9e..dd2a4cbb8f 100644 --- a/libs/langchain/langchain/chains/graph_qa/cypher.py +++ b/libs/langchain/langchain/chains/graph_qa/cypher.py @@ -6,6 +6,7 @@ from typing import Any, Dict, List, Optional from langchain.callbacks.manager import CallbackManagerForChainRun from langchain.chains.base import Chain +from langchain.chains.graph_qa.cypher_utils import CypherQueryCorrector, Schema from langchain.chains.graph_qa.prompts import CYPHER_GENERATION_PROMPT, CYPHER_QA_PROMPT from langchain.chains.llm import LLMChain from langchain.graphs.neo4j_graph import Neo4jGraph @@ -90,6 +91,8 @@ class GraphCypherQAChain(Chain): """Whether or not to return the intermediate steps along with the final answer.""" return_direct: bool = False """Whether or not to return the result of querying the graph directly.""" + cypher_query_corrector: Optional[CypherQueryCorrector] = None + """Optional cypher validation tool""" @property def input_keys(self) -> List[str]: @@ -123,6 +126,7 @@ class GraphCypherQAChain(Chain): qa_llm: Optional[BaseLanguageModel] = None, exclude_types: List[str] = [], include_types: List[str] = [], + validate_cypher: bool = False, **kwargs: Any, ) -> GraphCypherQAChain: """Initialize from LLM.""" @@ -150,10 +154,19 @@ class GraphCypherQAChain(Chain): kwargs["graph"].structured_schema, include_types, exclude_types ) + cypher_query_corrector = None + if validate_cypher: + corrector_schema = [ + Schema(el["start"], el["type"], el["end"]) + for el in kwargs["graph"].structured_schema.get("relationships") + ] + cypher_query_corrector = CypherQueryCorrector(corrector_schema) + return cls( graph_schema=graph_schema, qa_chain=qa_chain, cypher_generation_chain=cypher_generation_chain, + cypher_query_corrector=cypher_query_corrector, **kwargs, ) @@ -176,6 +189,10 @@ class GraphCypherQAChain(Chain): # Extract Cypher code if it is wrapped in backticks generated_cypher = extract_cypher(generated_cypher) + # Correct Cypher query if enabled + if self.cypher_query_corrector: + generated_cypher = self.cypher_query_corrector(generated_cypher) + _run_manager.on_text("Generated Cypher:", end="\n", verbose=self.verbose) _run_manager.on_text( generated_cypher, color="green", end="\n", verbose=self.verbose @@ -184,7 +201,11 @@ class GraphCypherQAChain(Chain): intermediate_steps.append({"query": generated_cypher}) # Retrieve and limit the number of results - context = self.graph.query(generated_cypher)[: self.top_k] + # Generated Cypher be null if query corrector identifies invalid schema + if generated_cypher: + context = self.graph.query(generated_cypher)[: self.top_k] + else: + context = [] if self.return_direct: final_result = context diff --git a/libs/langchain/langchain/chains/graph_qa/cypher_utils.py b/libs/langchain/langchain/chains/graph_qa/cypher_utils.py new file mode 100644 index 0000000000..ee39985088 --- /dev/null +++ b/libs/langchain/langchain/chains/graph_qa/cypher_utils.py @@ -0,0 +1,248 @@ +import re +from collections import namedtuple +from typing import Any, Dict, List, Optional, Tuple + +Schema = namedtuple("Schema", ["left_node", "relation", "right_node"]) + + +class CypherQueryCorrector: + """ + Used to correct relationship direction in generated Cypher statements. + This code is copied from the winner's submission to the Cypher competition: + https://github.com/sakusaku-rich/cypher-direction-competition + """ + + property_pattern = re.compile(r"\{.+?\}") + node_pattern = re.compile(r"\(.+?\)") + path_pattern = re.compile(r"\(.*\).*-.*-.*\(.*\)") + node_relation_node_pattern = re.compile( + r"(\()+(?P[^()]*?)\)(?P.*?)\((?P[^()]*?)(\))+" + ) + relation_type_pattern = re.compile(r":(?P.+?)?(\{.+\})?]") + + def __init__(self, schemas: List[Schema]): + """ + Args: + schemas: list of schemas + """ + self.schemas = schemas + + def clean_node(self, node: str) -> str: + """ + Args: + node: node in string format + + """ + node = re.sub(self.property_pattern, "", node) + node = node.replace("(", "") + node = node.replace(")", "") + node = node.strip() + return node + + def detect_node_variables(self, query: str) -> Dict[str, List[str]]: + """ + Args: + query: cypher query + """ + nodes = re.findall(self.node_pattern, query) + nodes = [self.clean_node(node) for node in nodes] + res: Dict[str, Any] = {} + for node in nodes: + parts = node.split(":") + if parts == "": + continue + variable = parts[0] + if variable not in res: + res[variable] = [] + res[variable] += parts[1:] + return res + + def extract_paths(self, query: str) -> "List[str]": + """ + Args: + query: cypher query + """ + return re.findall(self.path_pattern, query) + + def judge_direction(self, relation: str) -> str: + """ + Args: + relation: relation in string format + """ + direction = "BIDIRECTIONAL" + if relation[0] == "<": + direction = "INCOMING" + if relation[-1] == ">": + direction = "OUTGOING" + return direction + + def extract_node_variable(self, part: str) -> Optional[str]: + """ + Args: + part: node in string format + """ + part = part.lstrip("(").rstrip(")") + idx = part.find(":") + if idx != -1: + part = part[:idx] + return None if part == "" else part + + def detect_labels( + self, str_node: str, node_variable_dict: Dict[str, Any] + ) -> List[str]: + """ + Args: + str_node: node in string format + node_variable_dict: dictionary of node variables + """ + splitted_node = str_node.split(":") + variable = splitted_node[0] + labels = [] + if variable in node_variable_dict: + labels = node_variable_dict[variable] + elif variable == "" and len(splitted_node) > 1: + labels = splitted_node[1:] + return labels + + def verify_schema( + self, + from_node_labels: List[str], + relation_types: List[str], + to_node_labels: List[str], + ) -> bool: + """ + Args: + from_node_labels: labels of the from node + relation_type: type of the relation + to_node_labels: labels of the to node + """ + valid_schemas = self.schemas + if from_node_labels != []: + from_node_labels = [label.strip("`") for label in from_node_labels] + valid_schemas = [ + schema for schema in valid_schemas if schema[0] in from_node_labels + ] + if to_node_labels != []: + to_node_labels = [label.strip("`") for label in to_node_labels] + valid_schemas = [ + schema for schema in valid_schemas if schema[2] in to_node_labels + ] + if relation_types != []: + relation_types = [type.strip("`") for type in relation_types] + valid_schemas = [ + schema for schema in valid_schemas if schema[1] in relation_types + ] + return valid_schemas != [] + + def detect_relation_types(self, str_relation: str) -> Tuple[str, List[str]]: + """ + Args: + str_relation: relation in string format + """ + relation_direction = self.judge_direction(str_relation) + relation_type = self.relation_type_pattern.search(str_relation) + if relation_type is None or relation_type.group("relation_type") is None: + return relation_direction, [] + relation_types = [ + t.strip().strip("!") + for t in relation_type.group("relation_type").split("|") + ] + return relation_direction, relation_types + + def correct_query(self, query: str) -> str: + """ + Args: + query: cypher query + """ + node_variable_dict = self.detect_node_variables(query) + paths = self.extract_paths(query) + for path in paths: + original_path = path + start_idx = 0 + while start_idx < len(path): + match_res = re.match(self.node_relation_node_pattern, path[start_idx:]) + if match_res is None: + break + start_idx += match_res.start() + match_dict = match_res.groupdict() + left_node_labels = self.detect_labels( + match_dict["left_node"], node_variable_dict + ) + right_node_labels = self.detect_labels( + match_dict["right_node"], node_variable_dict + ) + end_idx = ( + start_idx + + 4 + + len(match_dict["left_node"]) + + len(match_dict["relation"]) + + len(match_dict["right_node"]) + ) + original_partial_path = original_path[start_idx : end_idx + 1] + relation_direction, relation_types = self.detect_relation_types( + match_dict["relation"] + ) + + if relation_types != [] and "".join(relation_types).find("*") != -1: + start_idx += ( + len(match_dict["left_node"]) + len(match_dict["relation"]) + 2 + ) + continue + + if relation_direction == "OUTGOING": + is_legal = self.verify_schema( + left_node_labels, relation_types, right_node_labels + ) + if not is_legal: + is_legal = self.verify_schema( + right_node_labels, relation_types, left_node_labels + ) + if is_legal: + corrected_relation = "<" + match_dict["relation"][:-1] + corrected_partial_path = original_partial_path.replace( + match_dict["relation"], corrected_relation + ) + query = query.replace( + original_partial_path, corrected_partial_path + ) + else: + return "" + elif relation_direction == "INCOMING": + is_legal = self.verify_schema( + right_node_labels, relation_types, left_node_labels + ) + if not is_legal: + is_legal = self.verify_schema( + left_node_labels, relation_types, right_node_labels + ) + if is_legal: + corrected_relation = match_dict["relation"][1:] + ">" + corrected_partial_path = original_partial_path.replace( + match_dict["relation"], corrected_relation + ) + query = query.replace( + original_partial_path, corrected_partial_path + ) + else: + return "" + else: + is_legal = self.verify_schema( + left_node_labels, relation_types, right_node_labels + ) + is_legal |= self.verify_schema( + right_node_labels, relation_types, left_node_labels + ) + if not is_legal: + return "" + + start_idx += ( + len(match_dict["left_node"]) + len(match_dict["relation"]) + 2 + ) + return query + + def __call__(self, query: str) -> str: + """Correct the query to make it valid. If + Args: + query: cypher query + """ + return self.correct_query(query) diff --git a/libs/langchain/tests/unit_tests/chains/test_graph_qa.py b/libs/langchain/tests/unit_tests/chains/test_graph_qa.py index 6c97a2edbb..ed4fe9feb6 100644 --- a/libs/langchain/tests/unit_tests/chains/test_graph_qa.py +++ b/libs/langchain/tests/unit_tests/chains/test_graph_qa.py @@ -1,4 +1,9 @@ +from typing import List + +import pandas as pd + from langchain.chains.graph_qa.cypher import construct_schema, extract_cypher +from langchain.chains.graph_qa.cypher_utils import CypherQueryCorrector, Schema def test_no_backticks() -> None: @@ -117,3 +122,31 @@ def test_include_types3() -> None: "['(:Actor)-[:ACTED_IN]->(:Movie)']" ) assert output == expected_schema + + +def test_validating_cypher_statements() -> None: + cypher_file = "tests/unit_tests/data/cypher_corrector.csv" + examples = pd.read_csv(cypher_file) + examples.fillna("", inplace=True) + for _, row in examples.iterrows(): + schema = load_schemas(row["schema"]) + corrector = CypherQueryCorrector(schema) + assert corrector(row["statement"]) == row["correct_query"] + + +def load_schemas(str_schemas: str) -> List[Schema]: + """ + Args: + str_schemas: string of schemas + """ + values = str_schemas.replace("(", "").replace(")", "").split(",") + schemas = [] + for i in range(len(values) // 3): + schemas.append( + Schema( + values[i * 3].strip(), + values[i * 3 + 1].strip(), + values[i * 3 + 2].strip(), + ) + ) + return schemas diff --git a/libs/langchain/tests/unit_tests/data/cypher_corrector.csv b/libs/langchain/tests/unit_tests/data/cypher_corrector.csv new file mode 100644 index 0000000000..b9739c7ffd --- /dev/null +++ b/libs/langchain/tests/unit_tests/data/cypher_corrector.csv @@ -0,0 +1,508 @@ +"statement","schema","correct_query" +"MATCH (p:Person)-[:KNOWS]->(:Person) RETURN p, count(*) AS count","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person)-[:KNOWS]->(:Person) RETURN p, count(*) AS count" +"MATCH (p:Person)<-[:KNOWS]-(:Person) RETURN p, count(*) AS count","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person)<-[:KNOWS]-(:Person) RETURN p, count(*) AS count" +"MATCH (p:Person {id:""Foo""})<-[:WORKS_AT]-(o:Organization) RETURN o.name AS name","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person {id:""Foo""})-[:WORKS_AT]->(o:Organization) RETURN o.name AS name" +"MATCH (o:Organization)-[:WORKS_AT]->(p:Person {id:""Foo""}) RETURN o.name AS name","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (o:Organization)<-[:WORKS_AT]-(p:Person {id:""Foo""}) RETURN o.name AS name" +"MATCH (o:Organization {name:""Bar""})-[:WORKS_AT]->(p:Person {id:""Foo""}) RETURN o.name AS name","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (o:Organization {name:""Bar""})<-[:WORKS_AT]-(p:Person {id:""Foo""}) RETURN o.name AS name" +"MATCH (o:Organization)-[:WORKS_AT]->(p:Person {id:""Foo""})-[:WORKS_AT]->(o1:Organization) RETURN o.name AS name","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (o:Organization)<-[:WORKS_AT]-(p:Person {id:""Foo""})-[:WORKS_AT]->(o1:Organization) RETURN o.name AS name" +"MATCH (o:`Organization` {name:""Foo""})-[:WORKS_AT]->(p:Person {id:""Foo""})-[:WORKS_AT]-(o1:Organization {name:""b""}) +WHERE id(o) > id(o1) +RETURN o.name AS name","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (o:`Organization` {name:""Foo""})<-[:WORKS_AT]-(p:Person {id:""Foo""})-[:WORKS_AT]-(o1:Organization {name:""b""}) +WHERE id(o) > id(o1) +RETURN o.name AS name" +"MATCH (p:Person) +RETURN p, + [(p)-[:WORKS_AT]->(o:Organization) | o.name] AS op","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person) +RETURN p, + [(p)-[:WORKS_AT]->(o:Organization) | o.name] AS op" +"MATCH (p:Person) +RETURN p, + [(p)<-[:WORKS_AT]-(o:Organization) | o.name] AS op","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person) +RETURN p, + [(p)-[:WORKS_AT]->(o:Organization) | o.name] AS op" +"MATCH (p:Person {name:""John""}) MATCH (p)-[:WORKS_AT]->(:Organization) RETURN p, count(*)","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person {name:""John""}) MATCH (p)-[:WORKS_AT]->(:Organization) RETURN p, count(*)" +"MATCH (p:Person) MATCH (p)<-[:WORKS_AT]-(:Organization) RETURN p, count(*)","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person) MATCH (p)-[:WORKS_AT]->(:Organization) RETURN p, count(*)" +"MATCH (p:Person), (p)<-[:WORKS_AT]-(:Organization) RETURN p, count(*)","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person), (p)-[:WORKS_AT]->(:Organization) RETURN p, count(*)" +"MATCH (o:Organization)-[:WORKS_AT]->(p:Person {id:""Foo""})-[:WORKS_AT]->(o1:Organization) +WHERE id(o) < id(o1) RETURN o.name AS name","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (o:Organization)<-[:WORKS_AT]-(p:Person {id:""Foo""})-[:WORKS_AT]->(o1:Organization) +WHERE id(o) < id(o1) RETURN o.name AS name" +"MATCH (o:Organization)-[:WORKS_AT]-(p:Person {id:""Foo""})-[:WORKS_AT]-(o1:Organization) +WHERE id(o) < id(o1) RETURN o.name AS name","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (o:Organization)-[:WORKS_AT]-(p:Person {id:""Foo""})-[:WORKS_AT]-(o1:Organization) +WHERE id(o) < id(o1) RETURN o.name AS name" +"MATCH (p:Person)--(:Organization)--(p1:Person) +RETURN p1","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person)--(:Organization)--(p1:Person) +RETURN p1" +"MATCH (p:Person)<--(:Organization)--(p1:Person) +RETURN p1","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person)-->(:Organization)--(p1:Person) +RETURN p1" +"MATCH (p:Person)<-[r]-(:Organization)--(p1:Person) +RETURN p1, r","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person)-[r]->(:Organization)--(p1:Person) +RETURN p1, r" +"MATCH (person:Person) +CALL { + WITH person + MATCH (person)-->(o:Organization) + RETURN o LIMIT 3 +} +RETURN person, o","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (person:Person) +CALL { + WITH person + MATCH (person)-->(o:Organization) + RETURN o LIMIT 3 +} +RETURN person, o" +"MATCH (person:Person) +CALL { + WITH person + MATCH (person)<--(o:Organization) + RETURN o LIMIT 3 +} +RETURN person, o","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (person:Person) +CALL { + WITH person + MATCH (person)-->(o:Organization) + RETURN o LIMIT 3 +} +RETURN person, o" +"MATCH (person:Person) +CALL { + WITH person + MATCH (person)-[:KNOWS]->(o:Organization) + RETURN o LIMIT 3 +} +RETURN person, o","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)", +"MATCH (person:Person) +CALL { + WITH person + MATCH (person)<-[:WORKS_AT|INVESTOR]-(o:Organization) + RETURN o LIMIT 3 +} +RETURN person, o","(Person, KNOWS, Person), (Person, WORKS_AT, Organization), (Person, INVESTOR, Organization)","MATCH (person:Person) +CALL { + WITH person + MATCH (person)-[:WORKS_AT|INVESTOR]->(o:Organization) + RETURN o LIMIT 3 +} +RETURN person, o" +"MATCH (p:Person) +WHERE EXISTS { (p)<-[:KNOWS]-()} +RETURN p","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person) +WHERE EXISTS { (p)<-[:KNOWS]-()} +RETURN p" +"MATCH (p:Person) +WHERE EXISTS { (p)-[:KNOWS]->()} +RETURN p","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person) +WHERE EXISTS { (p)-[:KNOWS]->()} +RETURN p" +"MATCH (p:Person) +WHERE EXISTS { (p)<-[:WORKS_AT]-()} +RETURN p","(Person, KNOWS, Person), (Person, WORKS_AT, Organization)","MATCH (p:Person) +WHERE EXISTS { (p)-[:WORKS_AT]->()} +RETURN p" +"MATCH (p:Person)-[:ACTED_IN]->(m:Movie) +WHERE p.name = 'Tom Hanks' +AND m.year = 2013 +RETURN m.title","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN]->(m:Movie) +WHERE p.name = 'Tom Hanks' +AND m.year = 2013 +RETURN m.title" +"MATCH (p:Person)-[:ACTED_IN]-(m:Movie) +WHERE p.name = 'Tom Hanks' +AND m.year = 2013 +RETURN m.title","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN]-(m:Movie) +WHERE p.name = 'Tom Hanks' +AND m.year = 2013 +RETURN m.title" +"MATCH (p:Person)<-[:ACTED_IN]-(m:Movie) +WHERE p.name = 'Tom Hanks' +AND m.year = 2013 +RETURN m.title","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN]->(m:Movie) +WHERE p.name = 'Tom Hanks' +AND m.year = 2013 +RETURN m.title" +"MATCH (p:Person)-[:ACTED_IN]->(m:Movie) +WHERE p.name <> 'Tom Hanks' +AND m.title = 'Captain Phillips' +RETURN p.name","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN]->(m:Movie) +WHERE p.name <> 'Tom Hanks' +AND m.title = 'Captain Phillips' +RETURN p.name" +"MATCH (p:Person)-[:ACTED_IN]->(m:Movie) +WHERE p.name <> 'Tom Hanks' +AND m.title = 'Captain Phillips' +AND m.year > 2019 +AND m.year < 2030 +RETURN p.name","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN]->(m:Movie) +WHERE p.name <> 'Tom Hanks' +AND m.title = 'Captain Phillips' +AND m.year > 2019 +AND m.year < 2030 +RETURN p.name" +"MATCH (p:Person)<-[:ACTED_IN]-(m:Movie) +WHERE p.name <> 'Tom Hanks' +AND m.title = 'Captain Phillips' +AND m.year > 2019 +AND m.year < 2030 +RETURN p.name","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN]->(m:Movie) +WHERE p.name <> 'Tom Hanks' +AND m.title = 'Captain Phillips' +AND m.year > 2019 +AND m.year < 2030 +RETURN p.name" +"MATCH (p:Person)<-[:FOLLOWS]-(m:Movie) +WHERE p.name <> 'Tom Hanks' +AND m.title = 'Captain Phillips' +AND m.year > 2019 +AND m.year < 2030 +RETURN p.name","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)", +"MATCH (p:Person)-[:`ACTED_IN`]->(m:Movie)<-[:DIRECTED]-(p) +WHERE p.born.year > 1960 +RETURN p.name, p.born, labels(p), m.title","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:`ACTED_IN`]->(m:Movie)<-[:DIRECTED]-(p) +WHERE p.born.year > 1960 +RETURN p.name, p.born, labels(p), m.title" +"MATCH (p:Person)-[:ACTED_IN]-(m:Movie)<-[:DIRECTED]-(p) +WHERE p.born.year > 1960 +RETURN p.name, p.born, labels(p), m.title","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN]-(m:Movie)<-[:DIRECTED]-(p) +WHERE p.born.year > 1960 +RETURN p.name, p.born, labels(p), m.title" +"MATCH (p:Person)-[:ACTED_IN]-(m:Movie)-[:DIRECTED]->(p) +WHERE p.born.year > 1960 +RETURN p.name, p.born, labels(p), m.title","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN]-(m:Movie)<-[:DIRECTED]-(p) +WHERE p.born.year > 1960 +RETURN p.name, p.born, labels(p), m.title" +"MATCH (p:`Person`)<-[r]-(m:Movie) +WHERE p.name = 'Tom Hanks' +RETURN m.title AS movie, type(r) AS relationshipType","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:`Person`)-[r]->(m:Movie) +WHERE p.name = 'Tom Hanks' +RETURN m.title AS movie, type(r) AS relationshipType" +"MATCH (d:Person)-[:DIRECTED]->(m:Movie)-[:IN_GENRE]->(g:Genre) +WHERE m.year = 2000 AND g.name = ""Horror"" +RETURN d.name","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (d:Person)-[:DIRECTED]->(m:Movie)-[:IN_GENRE]->(g:Genre) +WHERE m.year = 2000 AND g.name = ""Horror"" +RETURN d.name" +"MATCH (d:Person)-[:DIRECTED]->(m:Movie)<--(g:Genre) +WHERE m.year = 2000 AND g.name = ""Horror"" +RETURN d.name","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (d:Person)-[:DIRECTED]->(m:Movie)-->(g:Genre) +WHERE m.year = 2000 AND g.name = ""Horror"" +RETURN d.name" +"MATCH (d:Person)<--(m:Movie)<--(g:Genre) +WHERE m.year = 2000 AND g.name = ""Horror"" +RETURN d.name","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (d:Person)-->(m:Movie)-->(g:Genre) +WHERE m.year = 2000 AND g.name = ""Horror"" +RETURN d.name" +"MATCH (d:Person)-[:DIRECTED]-(m:Movie)<-[:IN_GENRE]-(g:Genre) +WHERE m.year = 2000 AND g.name = ""Horror"" +RETURN d.name","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (d:Person)-[:DIRECTED]-(m:Movie)-[:IN_GENRE]->(g:Genre) +WHERE m.year = 2000 AND g.name = ""Horror"" +RETURN d.name" +"MATCH (p:Person)-[:ACTED_IN]->(m:Movie) +WHERE p.name = 'Tom Hanks' +AND exists {(p)-[:DIRECTED]->(m)} +RETURN p.name, labels(p), m.title","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN]->(m:Movie) +WHERE p.name = 'Tom Hanks' +AND exists {(p)-[:DIRECTED]->(m)} +RETURN p.name, labels(p), m.title" +"MATCH (p:Person)-[:ACTED_IN]->(m:Movie) +WHERE p.name = 'Tom Hanks' +AND exists {(p)<-[:DIRECTED]-(m)} +RETURN p.name, labels(p), m.title","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN]->(m:Movie) +WHERE p.name = 'Tom Hanks' +AND exists {(p)-[:DIRECTED]->(m)} +RETURN p.name, labels(p), m.title" +"MATCH (a:Person)-[:ACTED_IN]->(m:Movie) +WHERE m.year > 2000 +MATCH (m)<-[:DIRECTED]-(d:Person) +RETURN a.name, m.title, d.name","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (a:Person)-[:ACTED_IN]->(m:Movie) +WHERE m.year > 2000 +MATCH (m)<-[:DIRECTED]-(d:Person) +RETURN a.name, m.title, d.name" +"MATCH (a:Person)-[:ACTED_IN]-(m:Movie) +WHERE m.year > 2000 +MATCH (m)-[:DIRECTED]->(d:Person) +RETURN a.name, m.title, d.name","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (a:Person)-[:ACTED_IN]-(m:Movie) +WHERE m.year > 2000 +MATCH (m)<-[:DIRECTED]-(d:Person) +RETURN a.name, m.title, d.name" +"MATCH (m:Movie) WHERE m.title = ""Kiss Me Deadly"" +MATCH (m)-[:IN_GENRE]-(g:Genre)-[:IN_GENRE]->(rec:Movie) +MATCH (m)-[:ACTED_IN]->(a:Person)-[:ACTED_IN]-(rec) +RETURN rec.title, a.name","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (m:Movie) WHERE m.title = ""Kiss Me Deadly"" +MATCH (m)-[:IN_GENRE]-(g:Genre)<-[:IN_GENRE]-(rec:Movie) +MATCH (m)<-[:ACTED_IN]-(a:Person)-[:ACTED_IN]-(rec) +RETURN rec.title, a.name" +"MATCH (p:Person)-[:ACTED_IN]->(m:Movie), +(coActors:Person)-[:ACTED_IN]->(m) +WHERE p.name = 'Eminem' +RETURN m.title AS movie ,collect(coActors.name) AS coActors","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN]->(m:Movie), +(coActors:Person)-[:ACTED_IN]->(m) +WHERE p.name = 'Eminem' +RETURN m.title AS movie ,collect(coActors.name) AS coActors" +"MATCH (p:Person)<-[:ACTED_IN]-(m:Movie), +(coActors:Person)-[:ACTED_IN]->(m) +WHERE p.name = 'Eminem' +RETURN m.title AS movie ,collect(coActors.name) AS coActors","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN]->(m:Movie), +(coActors:Person)-[:ACTED_IN]->(m) +WHERE p.name = 'Eminem' +RETURN m.title AS movie ,collect(coActors.name) AS coActors" +"MATCH p = ((person:Person)<-[]-(movie:Movie)) +WHERE person.name = 'Walt Disney' +RETURN p","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH p = ((person:Person)-[]->(movie:Movie)) +WHERE person.name = 'Walt Disney' +RETURN p" +"MATCH p = ((person:Person)<-[:DIRECTED]-(movie:Movie)) +WHERE person.name = 'Walt Disney' +RETURN p","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH p = ((person:Person)-[:DIRECTED]->(movie:Movie)) +WHERE person.name = 'Walt Disney' +RETURN p" +"MATCH p = shortestPath((p1:Person)-[*]-(p2:Person)) +WHERE p1.name = ""Eminem"" +AND p2.name = ""Charlton Heston"" +RETURN p","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH p = shortestPath((p1:Person)-[*]-(p2:Person)) +WHERE p1.name = ""Eminem"" +AND p2.name = ""Charlton Heston"" +RETURN p" +"MATCH p = ((person:Person)-[:DIRECTED*]->(:Person)) +WHERE person.name = 'Walt Disney' +RETURN p","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH p = ((person:Person)-[:DIRECTED*]->(:Person)) +WHERE person.name = 'Walt Disney' +RETURN p" +"MATCH p = ((person:Person)-[:DIRECTED*1..4]->(:Person)) +WHERE person.name = 'Walt Disney' +RETURN p","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH p = ((person:Person)-[:DIRECTED*1..4]->(:Person)) +WHERE person.name = 'Walt Disney' +RETURN p" +"MATCH (p:Person {name: 'Eminem'})-[:ACTED_IN*2]-(others:Person) +RETURN others.name","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person {name: 'Eminem'})-[:ACTED_IN*2]-(others:Person) +RETURN others.name" +"MATCH (u:User {name: ""Misty Williams""})-[r:RATED]->(:Movie) +WITH u, avg(r.rating) AS average +MATCH (u)-[r:RATED]->(m:Movie) +WHERE r.rating > average +RETURN average , m.title AS movie, +r.rating as rating +ORDER BY rating DESC","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (User, RATED, Movie)","MATCH (u:User {name: ""Misty Williams""})-[r:RATED]->(:Movie) +WITH u, avg(r.rating) AS average +MATCH (u)-[r:RATED]->(m:Movie) +WHERE r.rating > average +RETURN average , m.title AS movie, +r.rating as rating +ORDER BY rating DESC" +"MATCH (u:User {name: ""Misty Williams""})-[r:RATED]->(:Movie) +WITH u, avg(r.rating) AS average +MATCH (u)<-[r:RATED]-(m:Movie) +WHERE r.rating > average +RETURN average , m.title AS movie, +r.rating as rating +ORDER BY rating DESC","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (User, RATED, Movie)","MATCH (u:User {name: ""Misty Williams""})-[r:RATED]->(:Movie) +WITH u, avg(r.rating) AS average +MATCH (u)-[r:RATED]->(m:Movie) +WHERE r.rating > average +RETURN average , m.title AS movie, +r.rating as rating +ORDER BY rating DESC" +"MATCH (p:`Person`) +WHERE p.born.year = 1980 +WITH p LIMIT 3 +MATCH (p)<-[:ACTED_IN]-(m:Movie) +WITH p, collect(m.title) AS movies +RETURN p.name AS actor, movies","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:`Person`) +WHERE p.born.year = 1980 +WITH p LIMIT 3 +MATCH (p)-[:ACTED_IN]->(m:Movie) +WITH p, collect(m.title) AS movies +RETURN p.name AS actor, movies" +"MATCH (p:Person) +WHERE p.born.year = 1980 +WITH p LIMIT 3 +MATCH (p)-[:ACTED_IN]->(m:Movie)<-[:IN_GENRE]-(g) +WITH p, collect(DISTINCT g.name) AS genres +RETURN p.name AS actor, genres","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person) +WHERE p.born.year = 1980 +WITH p LIMIT 3 +MATCH (p)-[:ACTED_IN]->(m:Movie)-[:IN_GENRE]->(g) +WITH p, collect(DISTINCT g.name) AS genres +RETURN p.name AS actor, genres" +"CALL { + MATCH (m:Movie) WHERE m.year = 2000 + RETURN m ORDER BY m.imdbRating DESC LIMIT 10 +} +MATCH (:User)-[r:RATED]->(m) +RETURN m.title, avg(r.rating)","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (User, RATED, Movie)","CALL { + MATCH (m:Movie) WHERE m.year = 2000 + RETURN m ORDER BY m.imdbRating DESC LIMIT 10 +} +MATCH (:User)-[r:RATED]->(m) +RETURN m.title, avg(r.rating)" +"CALL { + MATCH (m:Movie) WHERE m.year = 2000 + RETURN m ORDER BY m.imdbRating DESC LIMIT 10 +} +MATCH (:User)<-[r:RATED]-(m) +RETURN m.title, avg(r.rating)","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (User, RATED, Movie)","CALL { + MATCH (m:Movie) WHERE m.year = 2000 + RETURN m ORDER BY m.imdbRating DESC LIMIT 10 +} +MATCH (:User)-[r:RATED]->(m) +RETURN m.title, avg(r.rating)" +"MATCH (m:Movie) +CALL { + WITH m + MATCH (m)-[r:RATED]->(u) + WHERE r.rating = 5 + RETURN count(u) AS numReviews +} +RETURN m.title, numReviews +ORDER BY numReviews DESC","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (m:Movie) +CALL { + WITH m + MATCH (m)<-[r:RATED]-(u) + WHERE r.rating = 5 + RETURN count(u) AS numReviews +} +RETURN m.title, numReviews +ORDER BY numReviews DESC" +"MATCH (p:Person) +WITH p LIMIT 100 +CALL { + WITH p + OPTIONAL MATCH (p)<-[:ACTED_IN]-(m) + RETURN m.title + "": "" + ""Actor"" AS work +UNION + WITH p + OPTIONAL MATCH (p)-[:DIRECTED]->(m:Movie) + RETURN m.title+ "": "" + ""Director"" AS work +} +RETURN p.name, collect(work)","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person) +WITH p LIMIT 100 +CALL { + WITH p + OPTIONAL MATCH (p)-[:ACTED_IN]->(m) + RETURN m.title + "": "" + ""Actor"" AS work +UNION + WITH p + OPTIONAL MATCH (p)-[:DIRECTED]->(m:Movie) + RETURN m.title+ "": "" + ""Director"" AS work +} +RETURN p.name, collect(work)" +"MATCH (p:Person)<-[:ACTED_IN {role:""Neo""}]-(m:Movie) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p, m","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN {role:""Neo""}]->(m:Movie) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p, m" +"MATCH (p:Person)<-[:ACTED_IN {role:""Neo""}]-(m) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN {role:""Neo""}]->(m) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p" +"MATCH (p:Person)-[:ACTED_IN {role:""Neo""}]->(m:Movie) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p, m","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:ACTED_IN {role:""Neo""}]->(m:Movie) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p, m" +"MATCH (wallstreet:Movie {title: 'Wall Street'})-[:ACTED_IN {role:""Foo""}]->(actor) +RETURN actor.name","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (wallstreet:Movie {title: 'Wall Street'})<-[:ACTED_IN {role:""Foo""}]-(actor) +RETURN actor.name" +"MATCH (p:Person)<-[:`ACTED_IN` {role:""Neo""}]-(m:Movie) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p, m","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:`ACTED_IN` {role:""Neo""}]->(m:Movie) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p, m" +"MATCH (p:`Person`)<-[:`ACTED_IN` {role:""Neo""}]-(m:Movie) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p, m","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:`Person`)-[:`ACTED_IN` {role:""Neo""}]->(m:Movie) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p, m" +"MATCH (p:`Person`)<-[:`ACTED_IN` {role:""Neo""}]-(m) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p, m","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:`Person`)-[:`ACTED_IN` {role:""Neo""}]->(m) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p, m" +"MATCH (p:Person)<-[:!DIRECTED]-(:Movie) RETURN p, count(*)","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:!DIRECTED]->(:Movie) RETURN p, count(*)" +"MATCH (p:Person)<-[:`ACTED_IN`|`DIRECTED`]-(m:Movie) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p, m","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH (p:Person)-[:`ACTED_IN`|`DIRECTED`]->(m:Movie) +WHERE p.name = $actorName +AND m.title = $movieName +RETURN p, m" +"MATCH (a:Person:Actor)-[:ACTED_IN]->(:Movie) +RETURN a, count(*)","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (Actor, ACTED_IN, Movie)","MATCH (a:Person:Actor)-[:ACTED_IN]->(:Movie) +RETURN a, count(*)" +"MATCH (a:Person:Actor)<-[:ACTED_IN]-(:Movie) +RETURN a, count(*)","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (Actor, ACTED_IN, Movie)","MATCH (a:Person:Actor)-[:ACTED_IN]->(:Movie) +RETURN a, count(*)" +"MATCH (a:Person:Actor)<-[:ACTED_IN]-() +RETURN a, count(*)","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (Actor, ACTED_IN, Movie)","MATCH (a:Person:Actor)-[:ACTED_IN]->() +RETURN a, count(*)" +"MATCH (a:Person:Actor) +RETURN a, [(a)<-[:`ACTED_IN`]-(m) | m.title] AS movies","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (Actor, ACTED_IN, Movie)","MATCH (a:Person:Actor) +RETURN a, [(a)-[:`ACTED_IN`]->(m) | m.title] AS movies" +"MATCH (a:Person:Actor) +RETURN a, [(a)-[:`ACTED_IN`]->(m) | m.title] AS movies","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (Actor, ACTED_IN, Movie)","MATCH (a:Person:Actor) +RETURN a, [(a)-[:`ACTED_IN`]->(m) | m.title] AS movies" +"MATCH p = ((person:Person)-[:DIRECTED*]->(:Movie)) RETURN p +","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","MATCH p = ((person:Person)-[:DIRECTED*]->(:Movie)) RETURN p +" +"""MATCH p = ((person:Person)-[:DIRECTED*1..3]->(:Movie)) RETURN p""","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","""MATCH p = ((person:Person)-[:DIRECTED*1..3]->(:Movie)) RETURN p""" +"""MATCH p = ((person:Person)-[:DIRECTED*..3]->(:Movie)) RETURN p""","(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)","""MATCH p = ((person:Person)-[:DIRECTED*..3]->(:Movie)) RETURN p""" +"MATCH (p:Person {name:""Emil Eifrem""})-[:HAS_CEO]-(o:Organization)<-[:MENTIONS]-(a:Article)-[:HAS_CHUNK]->(c) +RETURN o.name AS company, a.title AS title, c.text AS text, a.date AS date +ORDER BY date DESC LIMIT 3 +","(Person, HAS_CEO, Organization), (Article, MENTIONS, Organization), (Article, HAS_CHUNK, Chunk), (Organization, HAS_COMPETITOR, Organization), (Organization, HAS_SUBSIDIARY, Organization)","MATCH (p:Person {name:""Emil Eifrem""})-[:HAS_CEO]-(o:Organization)<-[:MENTIONS]-(a:Article)-[:HAS_CHUNK]->(c) +RETURN o.name AS company, a.title AS title, c.text AS text, a.date AS date +ORDER BY date DESC LIMIT 3 +" +"MATCH (p:Person {name:""Emil Eifrem""})-[:HAS_CEO]->(o:Organization)<-[:MENTIONS]-(a:Article)-[:HAS_CHUNK]->(c) +RETURN o.name AS company, a.title AS title, c.text AS text, a.date AS date +ORDER BY date DESC LIMIT 3 +","(Organization, HAS_CEO, Person), (Article, MENTIONS, Organization), (Article, HAS_CHUNK, Chunk), (Organization, HAS_COMPETITOR, Organization), (Organization, HAS_SUBSIDIARY, Organization)","MATCH (p:Person {name:""Emil Eifrem""})<-[:HAS_CEO]-(o:Organization)<-[:MENTIONS]-(a:Article)-[:HAS_CHUNK]->(c) +RETURN o.name AS company, a.title AS title, c.text AS text, a.date AS date +ORDER BY date DESC LIMIT 3 +" +"MATCH (o:Organization {name: ""Databricks""})-[:HAS_COMPETITOR]->(c:Organization) +RETURN c.name as Competitor","(Organization, HAS_CEO, Person), (Article, MENTIONS, Organization), (Article, HAS_CHUNK, Chunk), (Organization, HAS_COMPETITOR, Organization), (Organization, HAS_SUBSIDIARY, Organization)","MATCH (o:Organization {name: ""Databricks""})-[:HAS_COMPETITOR]->(c:Organization) +RETURN c.name as Competitor" +"MATCH (o:Organization {name: ""Databricks""})<-[:HAS_COMPETITOR]-(c:Organization) +RETURN c.name as Competitor","(Organization, HAS_CEO, Person), (Article, MENTIONS, Organization), (Article, HAS_CHUNK, Chunk), (Organization, HAS_COMPETITOR, Organization), (Organization, HAS_SUBSIDIARY, Organization)","MATCH (o:Organization {name: ""Databricks""})<-[:HAS_COMPETITOR]-(c:Organization) +RETURN c.name as Competitor" +"MATCH p=(o:Organization {name:""Blackstone""})-[:HAS_SUBSIDIARY*]->(t) +WHERE NOT EXISTS {(t)-[:HAS_SUBSIDIARY]->()} +RETURN max(length(p)) AS max","(Organization, HAS_CEO, Person), (Article, MENTIONS, Organization), (Article, HAS_CHUNK, Chunk), (Organization, HAS_COMPETITOR, Organization), (Organization, HAS_SUBSIDIARY, Organization)","MATCH p=(o:Organization {name:""Blackstone""})-[:HAS_SUBSIDIARY*]->(t) +WHERE NOT EXISTS {(t)-[:HAS_SUBSIDIARY]->()} +RETURN max(length(p)) AS max" +"MATCH p=(o:Organization {name:""Blackstone""})-[:HAS_SUBSIDIARY*]-(t) +WHERE NOT EXISTS {(t)-[:HAS_SUBSIDIARY]->()} +RETURN max(length(p)) AS max","(Organization, HAS_CEO, Person), (Article, MENTIONS, Organization), (Article, HAS_CHUNK, Chunk), (Organization, HAS_COMPETITOR, Organization), (Organization, HAS_SUBSIDIARY, Organization)","MATCH p=(o:Organization {name:""Blackstone""})-[:HAS_SUBSIDIARY*]-(t) +WHERE NOT EXISTS {(t)-[:HAS_SUBSIDIARY]->()} +RETURN max(length(p)) AS max" +"MATCH p=(o:Organization {name:""Blackstone""})-[:HAS_SUBSIDIARY*]-(t:Person) +WHERE NOT EXISTS {(o)-[:HAS_SUBSIDIARY]->()} +RETURN max(length(p)) AS max","(Organization, HAS_CEO, Person), (Article, MENTIONS, Organization), (Article, HAS_CHUNK, Chunk), (Organization, HAS_COMPETITOR, Organization), (Organization, HAS_SUBSIDIARY, Organization)","MATCH p=(o:Organization {name:""Blackstone""})-[:HAS_SUBSIDIARY*]-(t:Person) +WHERE NOT EXISTS {(o)-[:HAS_SUBSIDIARY]->()} +RETURN max(length(p)) AS max" +"CALL apoc.ml.openai.embedding([""Are there any news regarding employee satisfaction?""], $openai_api_key) YIELD embedding +CALL db.index.vector.queryNodes(""news"", 3, embedding) YIELD node,score +RETURN node.text AS text, score","(Organization, HAS_CEO, Person), (Article, MENTIONS, Organization), (Article, HAS_CHUNK, Chunk), (Organization, HAS_COMPETITOR, Organization), (Organization, HAS_SUBSIDIARY, Organization)","CALL apoc.ml.openai.embedding([""Are there any news regarding employee satisfaction?""], $openai_api_key) YIELD embedding +CALL db.index.vector.queryNodes(""news"", 3, embedding) YIELD node,score +RETURN node.text AS text, score" +"MATCH (o:Organization {name:""Neo4j""})<-[:MENTIONS]-(a:Article)-[:HAS_CHUNK]->(c) +WHERE toLower(c.text) CONTAINS 'partnership' +RETURN a.title AS title, c.text AS text, a.date AS date +ORDER BY date DESC LIMIT 3","(Organization, HAS_CEO, Person), (Article, MENTIONS, Organization), (Article, HAS_CHUNK, Chunk), (Organization, HAS_COMPETITOR, Organization), (Organization, HAS_SUBSIDIARY, Organization)","MATCH (o:Organization {name:""Neo4j""})<-[:MENTIONS]-(a:Article)-[:HAS_CHUNK]->(c) +WHERE toLower(c.text) CONTAINS 'partnership' +RETURN a.title AS title, c.text AS text, a.date AS date +ORDER BY date DESC LIMIT 3" +"MATCH (n:`Some Label`)-[:`SOME REL TYPE üäß`]->(m:`Sömé Øther Læbel`) RETURN n,m","(Some Label, SOME REL TYPE üäß, Sömé Øther Læbel)","MATCH (n:`Some Label`)-[:`SOME REL TYPE üäß`]->(m:`Sömé Øther Læbel`) RETURN n,m" +"MATCH (n:`Some Label`)<-[:`SOME REL TYPE üäß`]-(m:`Sömé Øther Læbel`) RETURN n,m","(Some Label, SOME REL TYPE üäß, Sömé Øther Læbel)","MATCH (n:`Some Label`)-[:`SOME REL TYPE üäß`]->(m:`Sömé Øther Læbel`) RETURN n,m"