Skip to content
Snippets Groups Projects
convertQuery_test.go 41.8 KiB
Newer Older
/*
 This program has been developed by students from the bachelor Computer Science at Utrecht University within the Software Project course.
 © Copyright Utrecht University(Department of Information and Computing Sciences)
*/

package cypherv2

import (
	"encoding/json"
	"fmt"
	"strings"
	"testing"

	"git.science.uu.nl/graphpolaris/query-conversion/entityv2"
	"github.com/stretchr/testify/assert"
)

// All these tests test the entire flow

func fixCypherSpaces(cypher *string) string {
	trimmedCypher := strings.Replace(*cypher, "\n", " ", -1)
	trimmedCypher = strings.Replace(trimmedCypher, "  ", " ", -1)
	trimmedCypher = strings.Replace(trimmedCypher, "\t", "", -1)
	return trimmedCypher
}

func TestV2NoLogic(t *testing.T) {
	query := []byte(`{
		"databaseName": "Movies3",
		"return": ["*"],
		"query": [
		  {
			"id": "path1",
			"node": {
			  "label": "Person",
			  "id": "p1",
			  "relation": {
				"label": "DIRECTED",
				"direction": "TO",
				"depth": { "min": 1, "max": 1 },
				"node": {
				  "label": "Movie",
				  "id": "m1"
				}
			  }
			}
		  },
		  {
			"id": "path2",
			"node": {
			  "label": "Person",
			  "id": "p1",
			  "relation": {
				"label": "IN_GENRE",
				"direction": "TO",
				"depth": { "min": 1, "max": 1 },
				"node": {
				  "label": "Genre",
				  "id": "g1"
				}
			  }
			}
		  }
		],
		"limit": 5000
	  }
	  `)

	var JSONQuery entityv2.IncomingQueryJSON
	err := json.Unmarshal(query, &JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}

	s := NewService()
	cypher, _, err := s.ConvertQuery(&JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}
	t.Log(*cypher)

	answer := `MATCH path1 = ((p1:Person)<-[:DIRECTED*1..1]-(m1:Movie))
	MATCH path2 = ((p1:Person)<-[:IN_GENRE*1..1]-(g1:Genre))
	RETURN * LIMIT 5000`

	fmt.Printf("Cypher: %s\n", answer)
	trimmedCypher := fixCypherSpaces(cypher)
	trimmedAnswer := fixCypherSpaces(&answer)

	assert.Equal(t, trimmedAnswer, trimmedCypher)
}

func TestV2Simple(t *testing.T) {
	query := []byte(`{
		"databaseName": "Movies3",
		"return": ["*"],
		"logic": ["!=", "@p1.name", "\"Raymond Campbell\""],
		"query": [
		  {
			"id": "path1",
			"node": {
			  "label": "Person",
			  "id": "p1",
			  "relation": {
				"label": "DIRECTED",
				"direction": "TO",
				"depth": { "min": 1, "max": 1 },
				"node": {
				  "label": "Movie",
				  "id": "m1"
				}
			  }
			}
		  },
		  {
			"id": "path2",
			"node": {
			  "label": "Person",
			  "id": "p1",
			  "relation": {
				"label": "IN_GENRE",
				"direction": "TO",
				"depth": { "min": 1, "max": 1 },
				"node": {
				  "label": "Genre",
				  "id": "g1"
				}
			  }
			}
		  }
		],
		"limit": 5000
	  }
	  `)

	var JSONQuery entityv2.IncomingQueryJSON
	err := json.Unmarshal(query, &JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}

	s := NewService()
	cypher, _, err := s.ConvertQuery(&JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}
	t.Log(*cypher)

	answer := `MATCH path1 = ((p1:Person)<-[:DIRECTED*1..1]-(m1:Movie))
	MATCH path2 = ((p1:Person)<-[:IN_GENRE*1..1]-(g1:Genre)) 
	WHERE (p1.name <> "Raymond Campbell")
	RETURN * LIMIT 5000`

	fmt.Printf("Cypher: %s\n", answer)
	trimmedCypher := fixCypherSpaces(cypher)
	trimmedAnswer := fixCypherSpaces(&answer)

	assert.Equal(t, trimmedAnswer, trimmedCypher)
}

func TestV2GroupBy(t *testing.T) {
	query := []byte(`{
		"databaseName": "TweedeKamer",
		"limit": 5000,
		"logic": ["AND", ["<", "@movie.imdbRating", 7.5], ["==", "p2.age", "p1.age"]],
		"query": [
		  {
			"ID": "path1",
			"node": {
			  "label": "Person",
			  "ID": "p1",
			  "relation": {
				"ID": "acted",
				"label": "ACTED_IN",
				"depth": { "min": 1, "max": 1 },
				"direction": "TO",
				"node": {
				  "label": "Movie",
				}
			  }
			}
		  },
		  {
			"ID": "path2",
			"node": {
			  "label": "Person",
			}
		  }
		],
		"return": ["@path2"]
	  }`)

	var JSONQuery entityv2.IncomingQueryJSON
	err := json.Unmarshal(query, &JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}

	s := NewService()
	cypher, _, err := s.ConvertQuery(&JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}
	t.Log(*cypher)

	answer := `MATCH path1 = ((p1:Person)<-[acted:ACTED_IN*1..1]-(movie:Movie))
	MATCH path2 = ((p2:Person)) 
	WHERE ((movie.imdbRating < 7.500000) AND (p2.age = p1.age))
	RETURN path2 LIMIT 5000`

	fmt.Printf("Cypher: %s\n", answer)
	trimmedCypher := fixCypherSpaces(cypher)
	trimmedAnswer := fixCypherSpaces(&answer)

	assert.Equal(t, trimmedAnswer, trimmedCypher)
}

func TestV2NoLabel(t *testing.T) {
	query := []byte(`{
		"databaseName": "TweedeKamer",
		"limit": 5000,
		"logic": ["<", ["-", "@movie.year", "p1.year"], 10],
		"query": [
		  {
			"ID": "path1",
			"node": {
			  "ID": "p1",
			  "filter": [],
			  "relation": {
				"ID": "acted",
				"depth": { "min": 1, "max": 1 },
				"direction": "TO",
				"node": {
				  "label": "Movie",
	  }`)

	var JSONQuery entityv2.IncomingQueryJSON
	err := json.Unmarshal(query, &JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}

	s := NewService()
	cypher, _, err := s.ConvertQuery(&JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}
	t.Log(*cypher)

	answer := `MATCH path1 = ((p1)<-[acted*1..1]-(movie:Movie))
	WHERE ((movie.year - p1.year) < 10.000000)
	RETURN * LIMIT 5000`

	fmt.Printf("Cypher: %s\n", answer)
	trimmedCypher := fixCypherSpaces(cypher)
	trimmedAnswer := fixCypherSpaces(&answer)

	assert.Equal(t, trimmedAnswer, trimmedCypher)
}

func TestV2NoDepth(t *testing.T) {
	query := []byte(`{
		"databaseName": "TweedeKamer",
		"limit": 5000,
		"logic": ["AND", ["<", "@movie.imdbRating", 7.5], ["==", "p2.age", "p1.age"]],
		"query": [
		  {
			"ID": "path1",
			"node": {
			  "ID": "p1",
			  "relation": {
				"ID": "acted",
				"direction": "TO",
				"node": {
				  "label": "Movie",
				}
			  }
			}
		  },
		  {
			"ID": "path2",
			"node": {
	  }`)

	var JSONQuery entityv2.IncomingQueryJSON
	err := json.Unmarshal(query, &JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}
	fmt.Printf("%+v\n", JSONQuery)

	s := NewService()
	cypher, _, err := s.ConvertQuery(&JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}
	t.Log(*cypher)

	answer := `MATCH path1 = ((p1)<-[acted]-(movie:Movie))
	MATCH path2 = ((p2)) 
	WHERE ((movie.imdbRating < 7.500000) AND (p2.age = p1.age))
	RETURN * LIMIT 5000`

	fmt.Printf("Cypher: %s\n", answer)
	trimmedCypher := fixCypherSpaces(cypher)
	trimmedAnswer := fixCypherSpaces(&answer)

	assert.Equal(t, trimmedAnswer, trimmedCypher)
}

func TestV2WithAverage(t *testing.T) {
	query := []byte(`{
		"databaseName": "TweedeKamer",
		"limit": 5000,
		"logic": ["<", "@p1.age", ["Avg", "@p1.age"]],
		"query": [
		  {
			"ID": "path1",
			"node": {
			  "label": "Person",
			  "ID": "p1",
			  "relation": {
				"ID": "acted",
				"label": "ACTED_IN",
				"depth": { "min": 1, "max": 1 },
				"direction": "TO",
				"node": {
				  "label": "Movie",
				  "ID": "movie"
				}
			  }
			}
		  }
		],
		"return": ["*"]
	  }`)

	var JSONQuery entityv2.IncomingQueryJSON
	err := json.Unmarshal(query, &JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}

	s := NewService()
	cypher, _, err := s.ConvertQuery(&JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}
	t.Log(*cypher)

	answer := `MATCH path1 = ((p1:Person)<-[acted:ACTED_IN*1..1]-(movie:Movie))
	WITH avg(p1.age) AS p1_age_avg
	MATCH path1 = ((p1:Person)<-[acted:ACTED_IN*1..1]-(movie:Movie))
	WHERE (p1.age <  p1_age_avg)
	RETURN * LIMIT 5000`

	fmt.Printf("Cypher: %s\n", answer)
	trimmedCypher := fixCypherSpaces(cypher)
	trimmedAnswer := fixCypherSpaces(&answer)

	assert.Equal(t, trimmedAnswer, trimmedCypher)
}

func TestV2WithAverage2Paths(t *testing.T) {
	query := []byte(`{
		"databaseName": "TweedeKamer",
		"limit": 5000,
		"logic": ["<", "@p1.age", ["Avg", "@p1.age"]],
		"query": [
			{
				"ID": "path1",
				"node": {
					"label": "Person",
					"ID": "p1",
					"relation": {
						"ID": "acted",
						"label": "ACTED_IN",
						"depth": { "min": 1, "max": 1 },
						"direction": "TO",
						"node": {
							"label": "Movie",
							"ID": "movie"
						}
					}
				}
			},{
				"ID": "path2",
				"node": {
				"label": "Person",
				"ID": "p2",
				"relation": {
					"ID": "acted",
					"label": "ACTED_IN",
					"depth": { "min": 1, "max": 1 },
					"direction": "TO",
					"node": {
						"label": "Movie",
						"ID": "movie"
					}
				}
			}
		  }
		],
		"return": ["*"]
	  }`)

	var JSONQuery entityv2.IncomingQueryJSON
	err := json.Unmarshal(query, &JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}

	s := NewService()
	cypher, _, err := s.ConvertQuery(&JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}
	t.Log(*cypher)

	answer := `MATCH path1 = ((p1:Person)<-[acted:ACTED_IN*1..1]-(movie:Movie))
	MATCH path2 = ((p2:Person)<-[acted:ACTED_IN*1..1]-(movie:Movie))
	WITH avg(p1.age) AS p1_age_avg
	MATCH path1 = ((p1:Person)<-[acted:ACTED_IN*1..1]-(movie:Movie))
	MATCH path2 = ((p2:Person)<-[acted:ACTED_IN*1..1]-(movie:Movie))
	WHERE (p1.age <  p1_age_avg)
	RETURN * LIMIT 5000`

	fmt.Printf("Cypher: %s\n", answer)
	trimmedCypher := fixCypherSpaces(cypher)
	trimmedAnswer := fixCypherSpaces(&answer)

	assert.Equal(t, trimmedAnswer, trimmedCypher)
}

func TestV2SingleEntityWithLowerLike(t *testing.T) {
	query := []byte(`{
		"databaseName": "TweedeKamer",
		"limit": 5000,
		"logic": ["Like", ["Lower", "@p1.name"], "\"john\""],
		"query": [
		  {
			"ID": "path1",
			"node": {
			  "label": "Person",
			  "ID": "p1"
			}
		  }
		],
		"return": ["*"]
	  }`)

	var JSONQuery entityv2.IncomingQueryJSON
	err := json.Unmarshal(query, &JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}

	s := NewService()
	cypher, _, err := s.ConvertQuery(&JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}
	t.Log(*cypher)

	answer := `MATCH path1 = ((p1:Person))
	MATCH path1 = ((p1:Person))
	WHERE (toLower(p1.name) =~ (".*" + "john" + ".*"))
	RETURN * LIMIT 5000`

	fmt.Printf("Cypher: %s\n", answer)
	trimmedCypher := fixCypherSpaces(cypher)
	trimmedAnswer := fixCypherSpaces(&answer)

	assert.Equal(t, trimmedAnswer, trimmedCypher)
}

func TestV2Like(t *testing.T) {
	query := []byte(`{
		"databaseName": "neo4j",
		"query": [
			{
				"ID": "path_0",
				"node": {
					"ID": "id_1691576718400",
					"label": "Employee",
					"relation": {
						"ID": "id_1691576720177",
						"label": "REPORTS_TO",
						"direction": "TO",
						"node": {}
					}
				}
			}
		],
		"limit": 500,
		"return": [
			"*"
		],
		"logic": [
			"Like",
			"@id_1691576718400.title",
			"\"ale\""
		]
	}`)

	var JSONQuery entityv2.IncomingQueryJSON
	err := json.Unmarshal(query, &JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}

	s := NewService()
	cypher, _, err := s.ConvertQuery(&JSONQuery)
	if err != nil {
		fmt.Println(err)
		t.Log(err)
	}
	t.Log(*cypher)

	answer := `MATCH path_0 = ((id_1691576718400:Employee)<-[id_1691576720177:REPORTS_TO]-()) 
	WHERE (id_1691576718400.title =~ (".*" + "ale" + ".*")) 
	RETURN * LIMIT 500`

	fmt.Printf("Cypher: %s\n", answer)
	trimmedCypher := fixCypherSpaces(cypher)
	trimmedAnswer := fixCypherSpaces(&answer)

	assert.Equal(t, trimmedAnswer, trimmedCypher)
}

// func TestSmallChain(t *testing.T) {
// 	query := []byte(`{
// 		"databaseName": "TweedeKamer",
// 		"return": {
// 			"entities": [
// 				0,
// 				1,
// 				2
// 			],
// 			"relations": [
// 				0,
// 				1
// 			]
// 		},
// 		"entities": [
// 			{
// 				"name": "parliament",
// 				"ID": 0,
// 				"constraints": [
// 					{
// 						"attribute": "name",
// 						"value": "Geert",
// 						"dataType": "string",
// 						"matchType": "contains",
// 						"inID": -1,
// 						"inType": ""
// 					}
// 				]
// 			},
// 			{
// 				"name": "parties",
// 				"ID": 1,
// 				"constraints": []
// 			},
// 			{
// 				"name": "resolutions",
// 				"ID": 2,
// 				"constraints": []
// 			}
// 		],
// 		"relations": [
// 			{
// 				"ID": 0,
// 				"name": "member_of",
// 				"depth": {
// 					"min": 1,
// 					"max": 1
// 				},
// 				"fromType": "entity",
// 				"fromID": 0,
// 				"toType": "entity",
// 				"toID": 1,
// 				"constraints": []
// 			},
// 			{
// 				"ID": 1,
// 				"name": "submits",
// 				"depth": {
// 					"min": 1,
// 					"max": 1
// 				},
// 				"fromType": "entity",
// 				"fromID": 0,
// 				"toType": "entity",
// 				"toID": 2,
// 				"constraints": []
// 			}
// 		],
// 		"groupBys": [],
// 		"machineLearning": [],
// 		"limit": 5000
// 	}
// 	`)

// 	var JSONQuery entity.IncomingQueryJSON
// 	json.Unmarshal(query, &JSONQuery)

// 	s := NewService()
// 	cypher, _, err := s.ConvertQuery(&JSONQuery)
// 	if err != nil {
// 		fmt.Println(err)
// 	}

// 	answer := `MATCH p0 = (e0:parliament)-[:member_of*1..1]-(e1:parties)
// 	WHERE e0.name CONTAINS "%Geert%"
// 	UNWIND relationships(p0) as r0
// 	WITH *
// 	MATCH p1 = (e0:parliament)-[:submits*1..1]-(e2:resolutions)
// 		WHERE e0.name CONTAINS "%Geert%"
// 	UNWIND relationships(p1) as r1
// 	UNWIND [r1,e0,e2,r0,e0,e1] AS x
// 	RETURN DISTINCT x
// 	LIMIT 5000;nodelink`

// 	trimmedCypher := fixCypherSpaces(cypher)
// 	trimmedAnswer := fixCypherSpaces(&answer)

// 	assert.Equal(t, trimmedAnswer, trimmedCypher)

// }

// // This one does not really have dependencies, the order doesnt matter, maybe sort on numbers between equal dependencies?
// func TestLargeQueryChain(t *testing.T) {
// 	query := []byte(`{
// 		"databaseName": "TweedeKamer",
// 		"return": {
// 			"entities": [
// 				0,
// 				1,
// 				2,
// 				3,
// 				4
// 			],
// 			"relations": [
// 				0,
// 				1,
// 				2,
// 				3
// 			]
// 		},
// 		"entities": [
// 			{
// 				"name": "parliament",
// 				"ID": 0,
// 				"constraints": [
// 					{
// 						"attribute": "name",
// 						"value": "A",
// 						"dataType": "string",
// 						"matchType": "contains",
// 						"inID": -1,
// 						"inType": ""
// 					}
// 				]
// 			},
// 			{
// 				"name": "parties",
// 				"ID": 1,
// 				"constraints": [
// 					{
// 						"attribute": "seats",
// 						"value": "10",
// 						"dataType": "int",
// 						"matchType": "LT",
// 						"inID": -1,
// 						"inType": ""
// 					}
// 				]
// 			},
// 			{
// 				"name": "resolutions",
// 				"ID": 2,
// 				"constraints": [
// 					{
// 						"attribute": "date",
// 						"value": "mei",
// 						"dataType": "string",
// 						"matchType": "contains",
// 						"inID": -1,
// 						"inType": ""
// 					}
// 				]
// 			},
// 			{
// 				"name": "parliament",
// 				"ID": 3,
// 				"constraints": []
// 			},
// 			{
// 				"name": "parties",
// 				"ID": 4,
// 				"constraints": [
// 					{
// 						"attribute": "name",
// 						"value": "Volkspartij voor Vrijheid en Democratie",
// 						"dataType": "string",
// 						"matchType": "==",
// 						"inID": -1,
// 						"inType": ""
// 					}
// 				]
// 			}
// 		],
// 		"relations": [
// 			{
// 				"ID": 0,
// 				"name": "member_of",
// 				"depth": {
// 					"min": 1,
// 					"max": 1
// 				},
// 				"fromType": "entity",
// 				"fromID": 0,
// 				"toType": "entity",
// 				"toID": 1,
// 				"constraints": []
// 			},
// 			{
// 				"ID": 1,
// 				"name": "submits",
// 				"depth": {
// 					"min": 1,
// 					"max": 1
// 				},
// 				"fromType": "entity",
// 				"fromID": 1,
// 				"toType": "entity",
// 				"toID": 2,
// 				"constraints": []
// 			},
// 			{
// 				"ID": 2,
// 				"name": "submits",
// 				"depth": {
// 					"min": 1,
// 					"max": 1
// 				},
// 				"fromType": "entity",
// 				"fromID": 2,
// 				"toType": "entity",
// 				"toID": 3,
// 				"constraints": []
// 			},
// 			{
// 				"ID": 3,
// 				"name": "member_of",
// 				"depth": {
// 					"min": 1,
// 					"max": 1
// 				},
// 				"fromType": "entity",
// 				"fromID": 3,
// 				"toType": "entity",
// 				"toID": 4,
// 				"constraints": []
// 			}
// 		],
// 		"groupBys": [],
// 		"machineLearning": [],
// 		"limit": 5000
// 	}

// 	`)

// 	var JSONQuery entity.IncomingQueryJSON
// 	json.Unmarshal(query, &JSONQuery)

// 	s := NewService()
// 	cypher, _, err := s.ConvertQuery(&JSONQuery)
// 	if err != nil {
// 		fmt.Println(err)
// 	}

// 	answer := `MATCH p0 = (e0:parliament)-[:member_of*1..1]-(e1:parties)
// 	WHERE  e0.name CONTAINS "%A%"
// 	AND  e1.seats < 10
// 	UNWIND relationships(p0) as r0
// 	WITH *
// 	MATCH p1 = (e1:parties)-[:submits*1..1]-(e2:resolutions)
// 	WHERE e1.seats < 10
// 	AND e2.date CONTAINS "%mei%"
// 	UNWIND relationships(p1) as r1
// 	WITH *
// 	MATCH p2 = (e2:resolutions)-[:submits*1..1]-(e3:parliament)
// 	WHERE  e2.date CONTAINS "%mei%"
// 	UNWIND relationships(p2) as r2
// 	WITH *
// 	MATCH p3 = (e3:parliament)-[:member_of*1..1]-(e4:parties)
// 	WHERE  e4.name = "Volkspartij voor Vrijheid en Democratie"
// 	UNWIND relationships(p3) as r3
// 	UNWIND [r3,e3,e4,r2,e2,e3,r1,e1,e2,r0,e0,e1] AS x
// 	RETURN DISTINCT x
// 	LIMIT 5000;nodelink`

// 	trimmedCypher := fixCypherSpaces(cypher)
// 	trimmedAnswer := fixCypherSpaces(&answer)

// 	assert.Equal(t, trimmedAnswer, trimmedCypher)

// }

// func TestInStatement(t *testing.T) {
// 	query := []byte(`{
// 		"databaseName": "Movies3",
// 		"entities": [
// 			{
// 				"id": 0,
// 				"name": "Person",
// 				"constraints": []
// 			},
// 			{
// 				"id": 1,
// 				"name": "Movie",
// 				"constraints": []
// 			},
// 			{
// 				"id": 2,
// 				"name": "Person",
// 				"constraints": [
// 					{
// 						"attribute": "bornIn",
// 						"value": "",
// 						"dataType": "string",
// 						"matchType": "",
// 						"inID": 0,
// 						"inType": "groupBy"
// 					}
// 				]
// 			}
// 		],
// 		"relations": [
// 			{
// 				"id": 0,
// 				"name": "ACTED_IN",
// 				"depth": {
// 					"min": 1,
// 					"max": 1
// 				},
// 				"fromType": "entity",
// 				"fromID": 0,
// 				"toType": "entity",
// 				"toID": 1,
// 				"constraints": []
// 			}
// 		],
// 		"groupBys": [
// 			{
// 				"id": 0,
// 				"groupType": "entity",
// 				"groupID": [1],
// 				"groupAttribute": "imdbRating",
// 				"byType": "entity",
// 				"byID": [0],
// 				"byAttribute": "bornIn",
// 				"appliedModifier": "AVG",
// 				"relationID": 0,
// 				"constraints": [
// 					{
// 						"attribute": "imdbRating",
// 						"value": "7.5",
// 						"dataType": "int",
// 						"matchType": "GT",
// 						"inID": -1,
// 						"inType": ""
// 					}
// 				]
// 			}
// 		],
// 		"machineLearning": [],
// 		"limit": 5000
// 	}
// 	`)

// 	answer := `MATCH p0 = (e0:Person)-[:ACTED_IN*1..1]-(e1:Movie)
// 	UNWIND relationships(p0) as r0
// 	WITH *
// 	WITH e0.bornIn AS e0_bornIn, AVG(e1.imdbRating) AS AVG_imdbRating
// 		WHERE  AVG_imdbRating > 7.5
// 	MATCH (e2:Person)
// 		WHERE e2.bornIn IN e0_bornIn
// 	WITH *
// 	UNWIND [e2] AS x
// 	RETURN DISTINCT x
// 	LIMIT 5000;nodelink`

// 	var JSONQuery entity.IncomingQueryJSON
// 	json.Unmarshal(query, &JSONQuery)

// 	s := NewService()
// 	cypher, _, err := s.ConvertQuery(&JSONQuery)
// 	if err != nil {
// 		fmt.Println(err)
// 	}

// 	trimmedCypher := fixCypherSpaces(cypher)
// 	trimmedAnswer := fixCypherSpaces(&answer)
// 	assert.Equal(t, trimmedAnswer, trimmedCypher)

// }
// func TestMultipleByStatementDisconnected(t *testing.T) {
// 	query := []byte(`{
// 		"databaseName": "Movies3",
// 		"entities": [
// 			{
// 				"id": 0,
// 				"name": "Person",
// 				"constraints": []
// 			},
// 			{
// 				"id": 1,
// 				"name": "Movie",
// 				"constraints": []
// 			},
// 			{
// 				"id": 2,
// 				"name": "Person",
// 				"constraints": []
// 			},
// 			{
// 				"id": 3,
// 				"name": "Movie",
// 				"constraints": []
// 			}
// 		],
// 		"relations": [
// 			{
// 				"id": 0,
// 				"name": "ACTED_IN",
// 				"depth": {
// 					"min": 1,
// 					"max": 1
// 				},
// 				"fromType": "entity",
// 				"fromID": 0,
// 				"toType": "entity",
// 				"toID": 1,
// 				"constraints": []
// 			},
// 			{
// 				"id": 2,
// 				"name": "ACTED_IN",
// 				"depth": {
// 					"min": 1,
// 					"max": 1
// 				},
// 				"fromType": "entity",
// 				"fromID": 2,
// 				"toType": "entity",
// 				"toID": 3,
// 				"constraints": []
// 			}
// 		],
// 		"groupBys": [
// 			{
// 				"id": 0,