Convert English sentences to cypher queries
This repository contains code to generate a parser for converting english to cypher. The only input needed are english sentences and their corresponding cyphers. The generated parser is an earley parser. This is similar to the template phrases feature offered in neo4j bloom.
Check out a working demo here
Motivation
Though neo4j's cypher language is intuitive and great for making requests on a neo4j database, often neo4j is running on the backend of your project/website and for making requests from the front-end, one needs to generate cypher queries. Since cypher is a query language and takes some time to learn, it would be easier if there was a tool to convert natural english sentences to cyphers. This would allow any consumer/common man to make queries to the neo4j database (Note: These queries need to be of a pre-defined structure).
TODO
- Add case-insensitiveness for english queries.
- Add support for cypher syntax highlighting using code mirror.
- Add support for string and int data types.
- Add support for list of strings.
- Add support for auto-suggest in text-box.
- Write a blog post explaining everything.
Setup/Installation
First install nearley.js on your system using the following command:
npm install -g nearley
npm install --save nearley
Download the codemirror.zip file from here.
Enter rules (english sentences) in rules.txt
and corresponding cyphers in cyphers.txt
separated by a newline (having a newline in between is a must). An example has been explained in the next section.
Next, run the following commands:
python generate.py
nearleyc grammar.ne -o grammar.js
The first command would generate grammar.ne
and english2cypher.js
respectively. The second command would generate grammar.js
.
Copy english2cypher.js
, node_modules
directory, codemirror-5.52.0
directory and grammar.js
to your website directory and add the following lines in index.html
:
<script src="node_modules/nearley/lib/nearley.js"></script>
<script src="./english2cypher.js"></script>
<script src="./grammar.js"></script>
<!-- Codemirror for syntax highlighting -->
<link rel="stylesheet" href="./codemirror-5.52.0/lib/codemirror.css">
<link rel="stylesheet" href="./codemirror-5.52.0/theme/neo.css">
<script src="./codemirror-5.52.0/lib/codemirror.js"></script>
<script src="./codemirror-5.52.0/mode/cypher/cypher.js"></script>
<input class="input" type="text" placeholder="English Query" id="englishTextBoxId">
<button onclick="myFunction()">Convert 2 Cypher</button>
<input type="text" id="cypherBox" class="bar" wrap="hard" style="width:100%; align:center;" class="form-control" >
<script>
var codeMirrorEditor = CodeMirror.fromTextArea(document.getElementById("cypherBox"), {
mode:'cypher',
lineNumbers: true,
lineWrapping: true,
scrollbarStyle: "native",
theme: 'neo'
});
var code =
``;
codeMirrorEditor.setValue(code);
</script>
<script>
function myFunction(){
englishParser("englishTextBoxId", codeMirrorEditor);
};
</script>
Note: On downloading codemirror, if the version you get is different from 5.52.0
, edit the path in index.html
accordingly. Styling is up to you. The above html file is just barebones and it would result in a website that would look like this:
Example
Consider the following example where a neo4j database has two kinds of nodes person
and company
with name
as their properties and WORKS
as the relationship. And now say that we want to do the following queries:
- Find all the companies a person is working with. This can have the following english phrase:
Companies that person $[personName](string) is working with
with the corresponding cypher:
MATCH (a:Person)-[:WORKS]-(b:Company)
WHERE a.name = $[personName]
RETURN a
- Find the people working for a given company. This can have the following english phrase:
All the people working for the company $[companyName](string)
with the corresponding cypher:
MATCH (a:Person)-[:WORKS]-(b:Company)
WHERE b.name = $[companyName]
RETURN a
- Find all the the people limit to 100. This can have the following english phrase:
All the people in the database limit to $[number](int)
with the corresponding cypher:
MATCH (a:Person)
RETURN distinct a.name LIMIT $[number]
- Find all the companies. This can have the following english phrase:
All the companies in the database
with the corresponding cypher:
MATCH (b:Company)
RETURN distinct b.name
Note: string can have the following characters a-zA-Z0-9 -.,
whereas int can have only 0-9
. Try to avoid creating rules which are prefixes of one another, for example: All the people in the database
and All the people in the database limit to $[number](int)
. Instead you can modify them and have the following two rules All the people in the database no limit
and All the people in the database limit to $[number](int)
.
Contribution, issues and new features
If you have any questions or suggestions about the code or if you encounter any bugs, feel free to create an issue. If you want any new feature to be added to the code besides the ones mentioned in TODO
, feel free to create an issue.