diff --git a/cypher/clustering.go b/cypher/clustering.go
index 1504b1125a52c4039b98c5d95495bf011a9c0917..5a9a39519d9e191a41c65edd6a215bd33a39e5fc 100644
--- a/cypher/clustering.go
+++ b/cypher/clustering.go
@@ -1,6 +1,7 @@
 package cypher
 
 import (
+	"errors"
 	"fmt"
 
 	"git.science.uu.nl/graphpolaris/query-conversion/entity"
@@ -175,3 +176,89 @@ func checkForQueryCluster(JSONQuery *entity.IncomingQueryJSON) (*entity.Incoming
 
 	return &clusterJSON, &restJSON, isRest
 }
+
+// checkNoDeadEnds checks to see if al from's and to's exist
+func checkNoDeadEnds(JSONQuery *entity.IncomingQueryJSON) (bool, error) {
+
+	// Check for all the connections of a relation
+	for _, rel := range JSONQuery.Relations {
+		if rel.FromID != -1 {
+			if rel.FromType == "entity" {
+				ent := JSONQuery.FindE(rel.FromID)
+				if ent == nil {
+					return false, errors.New("Invalid query")
+				}
+			} else if rel.FromType == "groupBy" {
+				gb := JSONQuery.FindG(rel.FromID)
+				if gb == nil {
+					return false, errors.New("Invalid query")
+				}
+			}
+		}
+
+		if rel.ToID != -1 {
+			if rel.ToType == "entity" {
+				ent := JSONQuery.FindE(rel.ToID)
+				if ent == nil {
+					return false, errors.New("Invalid query")
+				}
+			} else if rel.ToType == "groupBy" {
+				gb := JSONQuery.FindG(rel.ToID)
+				if gb == nil {
+					return false, errors.New("Invalid query")
+				}
+			}
+		}
+	}
+
+	// Check for all the connections of a group by
+	for _, gb := range JSONQuery.GroupBys {
+		if gb.GroupType == "entity" {
+			ent := JSONQuery.FindE(gb.GroupID)
+			if ent == nil {
+				return false, errors.New("Invalid query")
+			}
+		}
+
+		if gb.GroupType == "relation" {
+			rel := JSONQuery.FindE(gb.GroupID)
+			if rel == nil {
+				return false, errors.New("Invalid query")
+			}
+		}
+
+		if gb.ByType == "entity" {
+			ent := JSONQuery.FindE(gb.ByID)
+			if ent == nil {
+				return false, errors.New("Invalid query")
+			}
+		}
+
+		if gb.ByType == "relation" {
+			rel := JSONQuery.FindE(gb.ByID)
+			if rel == nil {
+				return false, errors.New("Invalid query")
+			}
+		}
+	}
+
+	// Check all the connections of IN-statements
+	for _, ent := range JSONQuery.Entities {
+		if len(ent.Constraints) == 0 {
+			continue
+		}
+
+		for _, cons := range ent.Constraints {
+			if cons.InID == -1 {
+				continue
+			}
+
+			gb := JSONQuery.FindG(cons.InID)
+			if gb == nil {
+				return false, errors.New("Invalid query")
+			}
+		}
+	}
+
+	return true, nil
+}
diff --git a/cypher/convertQuery.go b/cypher/convertQuery.go
index 6575fe72e488e2bb1e25d9d65c6106d483f6ca44..e4d95375cd9e68c10bcf79dee0a0b3a1691dbf01 100644
--- a/cypher/convertQuery.go
+++ b/cypher/convertQuery.go
@@ -21,6 +21,11 @@ func (s *Service) ConvertQuery(totalJSONQuery *entity.IncomingQueryJSON) (*strin
 		return nil, errors.New("Invalid query")
 	}
 
+	ok, err := checkNoDeadEnds(query)
+	if !ok {
+		return nil, err
+	}
+
 	if isRest {
 		fmt.Println("Rest:")
 		fmt.Println(rest)
@@ -28,7 +33,7 @@ func (s *Service) ConvertQuery(totalJSONQuery *entity.IncomingQueryJSON) (*strin
 		// If something needs to be done with other query cluster, then add code here
 	}
 
-	finalCypher, err := createCypher(query)
+	finalCypher, err = createCypher(query)
 	if err != nil {
 		return nil, err
 	}
@@ -45,6 +50,8 @@ func createCypher(JSONQuery *entity.IncomingQueryJSON) (*string, error) {
 		return nil, err
 	}
 
+	fmt.Println(hierarchy)
+
 	// translate it to cypher in the right order, using the hierarchy
 	cypher, err := formQuery(JSONQuery, hierarchy)
 	if err != nil {
@@ -141,7 +148,6 @@ func createQueryHierarchy(JSONQuery *entity.IncomingQueryJSON) (entity.Query, er
 	IDctr := 0
 
 	// Add relations all to query parts
-	log.Println(JSONQuery.Relations)
 	for _, rel := range JSONQuery.Relations {
 
 		part := entity.QueryPart{
@@ -156,35 +162,6 @@ func createQueryHierarchy(JSONQuery *entity.IncomingQueryJSON) (entity.Query, er
 
 	}
 
-	// // Here comes a checker for (A)-->(B) and (B)-->(A). This can be converted to one relation with the other as a constraint
-	// // Lets call it a small cycle. It wont catch bigger cycles (with 3 nodes for example)
-
-	// // ** Note: nog code schrijven die hiervan een goeie exist call kan maken
-	// // EN de return statement is ook belangrijk
-	// for i := 0; i < len(parts); i++ {
-	// 	rel := JSONQuery.FindR(parts[i].QID)
-	// 	if rel.FromID == -1 || rel.ToID == -1 {
-	// 		continue
-	// 	}
-
-	// 	for j := i + 1; j < len(parts); j++ {
-	// 		other := JSONQuery.FindR(parts[j].QID)
-
-	// 		if other.FromID == -1 || other.ToID == -1 {
-	// 			continue
-	// 		}
-
-	// 		if (rel.ToID == other.FromID && rel.FromID == other.ToID) {
-	// 			// Thus a cycle: Add the part as a nested one and remove it from the query
-
-	// 			parts[i].NestedPart = &parts[j]
-	// 			parts = entity.Remove(parts, j)
-	// 			j--
-
-	// 		}
-	// 	}
-	// }
-
 	// Add the Groupby's
 	for _, gb := range JSONQuery.GroupBys {
 		part := entity.QueryPart{
@@ -239,6 +216,7 @@ func createQueryHierarchy(JSONQuery *entity.IncomingQueryJSON) (entity.Query, er
 			if rel.FromID == rela.ToID && rel.FromType == rela.ToType {
 				part := parts.Find(rel.ID, "relation")
 				part.Dependencies = append(part.Dependencies, parts.Find(rela.ID, "relation").PartID)
+				log.Println("yeet")
 			}
 		}
 
@@ -297,21 +275,7 @@ func createQueryHierarchy(JSONQuery *entity.IncomingQueryJSON) (entity.Query, er
 	}
 
 	// Here comes a checker for (A)-->(B) and (B)-->(A). This is mitigated partly by ignoring it
-	// (It appears the wrong is with neo4j in returning strange results, after querying the same query in 4 different ways)
 	// Lets call it a small cycle. It wont catch bigger cycles (with 3 nodes for example)
-	// It needs to create a new type of constraint (which createConstraints.go needs to be able to handle)
-
-	// ** NOTE: dit is nogal even een open kwestie, want cypher geeft vage antwoorden op simpele queries met dit principe,
-	// er komen vage extra relations bij die niet aan de patronen voldoen, terwijl je zou zeggen dat het simpel moet zijn
-	// en cypher heeft geen INTERSECT maar wel een UNION #hoedan
-
-	// Misschien werkt dit al, want dit werkt ook:
-	// Match (a:Person)-[r:ACTED_IN]-(m:Movie)
-	// with *
-	// Match (m:Movie)-[f:DIRECTED]-(a)
-	// return count (*)
-
-	// ** Kijk of dit ook nog werkt als er andere relations afhangen van deze cycle!!
 
 	for _, p := range parts {
 		// We only allow small cycles with relations
@@ -326,19 +290,23 @@ func createQueryHierarchy(JSONQuery *entity.IncomingQueryJSON) (entity.Query, er
 				continue
 			}
 
+			// Deleting from a slice while looping through it is an easy way to make mistakes, hence the workaround
 			cycle := false
 			toRemove := -1
 
 			for i, otherDep := range other.Dependencies {
 				if otherDep == p.PartID {
-					// small cycle detected
+					// Small cycle detected
 
 					cycle = true
 					toRemove = i
 				}
 			}
 
+			// Remove one of the two dependencies, does not really matter which, cypher knits it back together due to the query
+			// using the same ID's, thus making it a cycle again later on.
 			if cycle {
+				log.Println("Cycle detected and removed")
 				if len(other.Dependencies) == 0 {
 					other.Dependencies = make([]int, 0)
 				} else {
@@ -492,8 +460,6 @@ func createInCypher(JSONQuery *entity.IncomingQueryJSON, part entity.QueryPart)
 	retStatement := match + eConstraints + with
 	return &retStatement, nil
 
-	// Should be able to handle multiple IN statements from one entity, not sure if that will ever happen
-	// TODO: test this
 }
 
 // createRelationCypher takes the json and a query part, finds the necessary entities and converts it into cypher
diff --git a/cypher/convertQuery_test.go b/cypher/convertQuery_test.go
index 636353e6f771842e9ad13dcaae213e602943cca0..01de62f85542165dca4cb36e07a39fc27999c787 100644
--- a/cypher/convertQuery_test.go
+++ b/cypher/convertQuery_test.go
@@ -2,6 +2,7 @@ package cypher
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"strings"
 	"testing"
@@ -12,8 +13,7 @@ import (
 
 // All these tests test the entire flow
 
-func Test1(t *testing.T) {
-	// Works, but, the AVG function is applied to a string, so that doesnt work, but the translation does :D
+func TestGroupBy(t *testing.T) {
 	query := []byte(`{
 		"databaseName": "Movies3",
 		"return": {
@@ -121,9 +121,8 @@ func Test1(t *testing.T) {
 	UNWIND relationships(p1) as r1 
 	WITH *
 	RETURN  r1, eg1, e2
-	LIMIT 5000`
+	LIMIT 5000;nodelink`
 
-	fmt.Println(*cypher)
 	trimmedCypher := strings.Replace(*cypher, "\n", "", -1)
 	trimmedCypher = strings.Replace(trimmedCypher, "\t", "", -1)
 
@@ -131,11 +130,10 @@ func Test1(t *testing.T) {
 	trimmedAnswer = strings.Replace(trimmedAnswer, "\t", "", -1)
 
 	fmt.Println(*cypher)
-	assert.Equal(t, trimmedAnswer, trimmedAnswer)
+	assert.Equal(t, trimmedAnswer, trimmedCypher)
 
 }
-func Test2(t *testing.T) {
-	// Works, but, the AVG function is applied to a string, so that doesnt work, but the translation does :D
+func TestSmallChain(t *testing.T) {
 	query := []byte(`{
 		"databaseName": "TweedeKamer",
 		"return": {
@@ -227,7 +225,7 @@ func Test2(t *testing.T) {
 	UNWIND relationships(p1) as r1 
 	WITH *
 	RETURN  r1, e0, e2, r0, e0, e1
-	LIMIT 5000`
+	LIMIT 5000;nodelink`
 
 	fmt.Println(*cypher)
 
@@ -238,11 +236,12 @@ func Test2(t *testing.T) {
 	trimmedAnswer = strings.Replace(trimmedAnswer, "\t", "", -1)
 
 	fmt.Println(*cypher)
-	assert.Equal(t, trimmedAnswer, trimmedAnswer)
+	assert.Equal(t, trimmedAnswer, trimmedCypher)
 
 }
-func Test3(t *testing.T) {
-	// Works, but, the AVG function is applied to a string, so that doesnt work, but the translation does :D
+
+// 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": {
@@ -345,7 +344,7 @@ func Test3(t *testing.T) {
 					"max": 1
 				},
 				"fromType": "entity",
-				"fromID": 0,
+				"fromID": 1,
 				"toType": "entity",
 				"toID": 2,
 				"constraints": []
@@ -358,9 +357,9 @@ func Test3(t *testing.T) {
 					"max": 1
 				},
 				"fromType": "entity",
-				"fromID": 3,
+				"fromID": 2,
 				"toType": "entity",
-				"toID": 2,
+				"toID": 3,
 				"constraints": []
 			},
 			{
@@ -398,12 +397,12 @@ func Test3(t *testing.T) {
 		AND  e1.seats < 10 
 	UNWIND relationships(p0) as r0 
 	WITH *
-	MATCH p1 = (e0:parliament)-[:submits*1..1]-(e2:resolutions)
-		WHERE  e0.name CONTAINS "%A%" 
+	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 = (e3:parliament)-[:submits*1..1]-(e2:resolutions)
+	MATCH p2 = (e2:resolutions)-[:submits*1..1]-(e3:parliament)
 		WHERE  e2.date CONTAINS "%mei%" 
 	UNWIND relationships(p2) as r2 
 	WITH *
@@ -411,10 +410,8 @@ func Test3(t *testing.T) {
 		WHERE  e4.name = "Volkspartij voor Vrijheid en Democratie" 
 	UNWIND relationships(p3) as r3 
 	WITH *
-	RETURN  r3, e3, e4, r2, e3, e2, r1, e0, e2, r0, e0, e1
-	LIMIT 5000`
-
-	fmt.Println(*cypher)
+	RETURN  r3, e3, e4, r2, e2, e3, r1, e1, e2, r0, e0, e1
+	LIMIT 5000;nodelink`
 
 	trimmedCypher := strings.Replace(*cypher, "\n", "", -1)
 	trimmedCypher = strings.Replace(trimmedCypher, "\t", "", -1)
@@ -423,177 +420,75 @@ func Test3(t *testing.T) {
 	trimmedAnswer = strings.Replace(trimmedAnswer, "\t", "", -1)
 
 	fmt.Println(*cypher)
-	assert.Equal(t, trimmedAnswer, trimmedAnswer)
+	assert.Equal(t, trimmedAnswer, trimmedCypher)
 
 }
 
-func Test4(t *testing.T) {
-	// Works, but, the AVG function is applied to a string, so that doesnt work, but the translation does :D
+func TestInStatement(t *testing.T) {
 	query := []byte(`{
+		"databaseName": "Movies3",
 		"entities": [
 			{
-				"name": "parliament",
-				"ID": 0,
-				"constraints": [
-					{
-						"attribute": "name",
-						"value": "Geert",
-						"dataType": "string",
-						"matchType": "contains",
-						"inID": -1,
-						"inType": ""
-					}
-				]
-			},
-			{
-				"name": "commissions",
-				"ID": 1,
+				"id": 0,
+				"name": "Person",
 				"constraints": []
 			},
 			{
-				"name": "parliament",
-				"ID": 2,
+				"id": 1,
+				"name": "Movie",
 				"constraints": []
 			},
 			{
-				"name": "parties",
-				"ID": 3,
-				"constraints": [
-					{
-						"attribute": "seats",
-						"value": "10",
-						"dataType": "int",
-						"matchType": "LT",
-						"inID": -1,
-						"inType": ""
-					}
-				]
-			},
-			{
-				"name": "resolutions",
-				"ID": 4,
+				"id": 2,
+				"name": "Person",
 				"constraints": [
 					{
-						"attribute": "date",
-						"value": "mei",
+						"attribute": "bornIn",
+						"value": "",
 						"dataType": "string",
-						"matchType": "contains",
-						"inID": -1,
-						"inType": ""
+						"matchType": "",
+						"inID": 0,
+						"inType": "groupBy"
 					}
 				]
-			},
-			{
-				"name": "resolutions",
-				"ID": 5,
-				"constraints": []
-			},
-			{
-				"name": "parties",
-				"ID": 6,
-				"constraints": []
-			}
-			,
-			{
-				"name": "parliament",
-				"ID": 7,
-				"constraints": []
 			}
-		   
 		],
-		"groupBys": [],
 		"relations": [
 			{
-				"ID": 0,
-				"name": "part_of",
-				"depth": {
-					"min": 1,
-					"max": 1
-				},
-				"fromType": "entity",
-				"fromId": 0,
-				"toType": "entity",
-				"toID": 1,
-				"constraints": []
-			},
-			{
-				"ID": 1,
-				"name": "part_of",
+				"id": 0,
+				"name": "ACTED_IN",
 				"depth": {
 					"min": 1,
 					"max": 1
 				},
 				"fromType": "entity",
-				"fromId": 2,
+				"fromID": 0,
 				"toType": "entity",
 				"toID": 1,
 				"constraints": []
-			},
-			{
-				"ID": 2,
-				"name": "member_of",
-				"depth": {
-					"min": 1,
-					"max": 1
-				},
-				"fromType": "entity",
-				"fromId": 2,
-				"toType": "entity",
-				"toID": 3,
-				"constraints": []
-			},
-			{
-				"ID": 3,
-				"name": "submits",
-				"depth": {
-					"min": 1,
-					"max": 1
-				},
-				"fromType": "entity",
-				"fromId": 2,
-				"toType": "entity",
-				"toID": 4,
-				"constraints": []
-			},
-			{
-				"ID": 4,
-				"name": "submits",
-				"depth": {
-					"min": 1,
-					"max": 1
-				},
-				"fromType": "entity",
-				"fromId": 0,
-				"toType": "entity",
-				"toID": 5,
-				"constraints": []
-			},
-			{
-				"ID": 5,
-				"name": "member_of",
-				"depth": {
-					"min": 1,
-					"max": 1
-				},
-				"fromType": "entity",
-				"fromId": 0,
-				"toType": "entity",
-				"toID": 6,
-				"constraints": []
 			}
-			,
+		],
+		"groupBys": [
 			{
-				"ID": 6,
-				"name": "member_of",
-				"depth": {
-					"min": 1,
-					"max": 1
-				},
-				"fromType": "entity",
-				"fromId": 7,
-				"toType": "entity",
-				"toID": 6,
-				"constraints": []
+				"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": [],
@@ -601,6 +496,17 @@ func Test4(t *testing.T) {
 	}
 	`)
 
+	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 *
+	RETURN  e2
+	LIMIT 5000;nodelink`
+
 	var JSONQuery entity.IncomingQueryJSON
 	json.Unmarshal(query, &JSONQuery)
 
@@ -610,36 +516,6 @@ func Test4(t *testing.T) {
 		fmt.Println(err)
 	}
 
-	answer := `MATCH p2 = (e2:parliament)-[:member_of*1..1]-(e3:parties)
-		WHERE  e3.seats < 10 
-	UNWIND relationships(p2) as r2 
-	WITH *
-	MATCH p3 = (e2:parliament)-[:submits*1..1]-(e4:resolutions)
-		WHERE  e4.date CONTAINS "%mei%" 
-	UNWIND relationships(p3) as r3 
-	WITH *
-	MATCH p6 = (e7:parliament)-[:member_of*1..1]-(e6:parties)
-	UNWIND relationships(p6) as r6 
-	WITH *
-	MATCH p4 = (e0:parliament)-[:submits*1..1]-(e5:resolutions)
-		WHERE  e0.name CONTAINS "%%Geert%" 
-	UNWIND relationships(p4) as r4 
-	WITH *
-	MATCH p0 = (e0:parliament)-[:part_of*1..1]-(e1:commissions)
-		WHERE  e0.name CONTAINS "%%Geert%" 
-	UNWIND relationships(p0) as r0 
-	WITH *
-	MATCH p5 = (e0:parliament)-[:member_of*1..1]-(e6:parties)
-		WHERE  e0.name CONTAINS "%%Geert%" 
-	UNWIND relationships(p5) as r5 
-	WITH *
-	MATCH p1 = (e2:parliament)-[:part_of*1..1]-(e1:commissions)
-	UNWIND relationships(p1) as r1 
-	WITH *
-	RETURN  r1, e2, e1, r5, e0, e6, r0, e0, e1, r4, e0, e5, r6, e7, e6, r3, e2, e4, r2, e2, e3
-	LIMIT 5000`
-
-	fmt.Println(*cypher)
 	trimmedCypher := strings.Replace(*cypher, "\n", "", -1)
 	trimmedCypher = strings.Replace(trimmedCypher, "\t", "", -1)
 
@@ -647,11 +523,10 @@ func Test4(t *testing.T) {
 	trimmedAnswer = strings.Replace(trimmedAnswer, "\t", "", -1)
 
 	fmt.Println(*cypher)
-	assert.Equal(t, trimmedAnswer, trimmedAnswer)
+	assert.Equal(t, trimmedAnswer, trimmedCypher)
 
 }
-func Test5(t *testing.T) {
-	// Works, but, the AVG function is applied to a string, so that doesnt work, but the translation does :D
+func TestDoubleInStatement(t *testing.T) {
 	query := []byte(`{
 		"databaseName": "Movies3",
 		"entities": [
@@ -678,6 +553,20 @@ func Test5(t *testing.T) {
 						"inType": "groupBy"
 					}
 				]
+			},
+			{
+				"id": 3,
+				"name": "Person",
+				"constraints": [
+					{
+						"attribute": "bornIn",
+						"value": "",
+						"dataType": "string",
+						"matchType": "",
+						"inID": 0,
+						"inType": "groupBy"
+					}
+				]
 			}
 		],
 		"relations": [
@@ -731,8 +620,11 @@ func Test5(t *testing.T) {
 	MATCH (e2:Person)
 		WHERE e2.bornIn IN e0_bornIn
 	WITH *
-	RETURN  e2
-	LIMIT 5000`
+	MATCH (e3:Person)
+		WHERE e3.bornIn IN e0_bornIn
+	WITH *
+	RETURN  e3
+	LIMIT 5000;nodelink`
 
 	var JSONQuery entity.IncomingQueryJSON
 	json.Unmarshal(query, &JSONQuery)
@@ -750,11 +642,10 @@ func Test5(t *testing.T) {
 	trimmedAnswer = strings.Replace(trimmedAnswer, "\t", "", -1)
 
 	fmt.Println(*cypher)
-	assert.Equal(t, trimmedAnswer, trimmedAnswer)
+	assert.Equal(t, trimmedAnswer, trimmedCypher)
 
 }
-func Test6(t *testing.T) {
-	// Works, but, the AVG function is applied to a string, so that doesnt work, but the translation does :D
+func TestSimpleQuery(t *testing.T) {
 	query := []byte(`{
 		"return": {
 			"entities": [
@@ -800,10 +691,14 @@ func Test6(t *testing.T) {
 	}
 	`)
 
+	answer := `MATCH p0 = (e11:Person)-[:DIRECTED*1..1]-(e12:Movie)
+	UNWIND relationships(p0) as r10 
+	WITH *
+	RETURN  r10, e11, e12
+	LIMIT 5000;nodelink`
+
 	var JSONQuery entity.IncomingQueryJSON
 	json.Unmarshal(query, &JSONQuery)
-	fmt.Println(JSONQuery)
-	fmt.Println(" ")
 
 	s := NewService()
 	cypher, err := s.ConvertQuery(&JSONQuery)
@@ -811,11 +706,16 @@ func Test6(t *testing.T) {
 		fmt.Println(err)
 	}
 
+	trimmedCypher := strings.Replace(*cypher, "\n", "", -1)
+	trimmedCypher = strings.Replace(trimmedCypher, "\t", "", -1)
+
+	trimmedAnswer := strings.Replace(answer, "\n", "", -1)
+	trimmedAnswer = strings.Replace(trimmedAnswer, "\t", "", -1)
+
 	fmt.Println(*cypher)
-	t.Fail()
+	assert.Equal(t, trimmedAnswer, trimmedCypher)
 }
 func TestNoRelation(t *testing.T) {
-	// Works, but, the AVG function is applied to a string, so that doesnt work, but the translation does :D
 	query := []byte(`{
 		"return": {
 			"entities": [
@@ -863,7 +763,6 @@ func TestNoRelation(t *testing.T) {
 }
 
 func TestNoEntities(t *testing.T) {
-	// Works, but, the AVG function is applied to a string, so that doesnt work, but the translation does :D
 	query := []byte(`{
 		"return": {
 			"entities": [
@@ -912,8 +811,7 @@ func TestNoEntities(t *testing.T) {
 		t.Fail()
 	}
 }
-func TestTwoRelations(t *testing.T) {
-	// Works, but, the AVG function is applied to a string, so that doesnt work, but the translation does :D
+func TestTwoRelationsCycle(t *testing.T) {
 	query := []byte(`{
 		"return": {
 			"entities": [
@@ -989,25 +887,247 @@ func TestTwoRelations(t *testing.T) {
 		t.Fail()
 		return
 	}
+
+	answer1 := `MATCH p0 = (e11:Person)-[:DIRECTED*1..1]-(e12:Movie)
+	UNWIND relationships(p0) as r10
+	WITH *
+	MATCH p1 = (e11:Person)-[:DIRECTED*1..1]-(e12:Movie)
+	UNWIND relationships(p1) as r10
+	WITH *
+	RETURN  r10, e11, e12, r10, e11, e12
+	LIMIT 5000;nodelink`
+
+	answer2 := `MATCH p1 = (e12:Movie)-[:ACTED_IN*1..1]-(e11:Person)
+	UNWIND relationships(p1) as r11 
+	WITH *
+	MATCH p0 = (e11:Person)-[:DIRECTED*1..1]-(e12:Movie)
+	UNWIND relationships(p0) as r10 
+	WITH *
+	RETURN  r10, e11, e12, r11, e12, e11
+	LIMIT 5000;nodelink`
+
+	trimmedCypher := strings.Replace(*cypher, "\n", "", -1)
+	trimmedCypher = strings.Replace(trimmedCypher, "\t", "", -1)
+
+	trimmedAnswer1 := strings.Replace(answer1, "\n", "", -1)
+	trimmedAnswer1 = strings.Replace(trimmedAnswer1, "\t", "", -1)
+	trimmedAnswer2 := strings.Replace(answer2, "\n", "", -1)
+	trimmedAnswer2 = strings.Replace(trimmedAnswer2, "\t", "", -1)
+
 	fmt.Println(*cypher)
-	t.Fail()
-	// fmt.Println(*cypher)
+	// Both answers are correct
+	if !(trimmedAnswer1 == trimmedCypher || trimmedAnswer2 == trimmedCypher) {
+		t.Fail()
+	}
+}
+
+func TestCyclePlusDependency(t *testing.T) {
+	query := []byte(`{
+		"return": {
+			"entities": [
+				11,
+				12
+			],
+			"relations": [
+				10
+			],
+			"groupBys": []
+		},
+		"entities": [
+			{
+				"name": "Person",
+				"ID": 11,
+				"constraints": []
+			},
+			{
+				"name": "Movie",
+				"ID": 12,
+				"constraints": []
+			},
+			{
+				"name": "Person",
+				"ID": 13,
+				"constraints": []
+			}
+		],
+		"relations": [
+			{
+			"ID": 10,
+			"name": "DIRECTED",
+			"depth": {
+				"min": 1,
+				"max": 1
+			},
+			"fromType": "entity",
+			"fromID": 11,
+			"toType": "entity",
+			"toID": 12,
+			"constraints": []
+		},
+		{
+			"ID": 11,
+			"name": "ACTED_IN",
+			"depth": {
+				"min": 1,
+				"max": 1
+			},
+			"fromType": "entity",
+			"fromID": 12,
+			"toType": "entity",
+			"toID": 11,
+			"constraints": []
+		},
+		{
+			"ID": 12,
+			"name": "ACTED_IN",
+			"depth": {
+				"min": 1,
+				"max": 1
+			},
+			"fromType": "entity",
+			"fromID": 13,
+			"toType": "entity",
+			"toID": 12,
+			"constraints": []
+		}
+		],
+		"groupBys": [],
+		"machineLearning": [],
+		"limit": 5000,
+		"databaseName": "Movies3"
+	}
+	`)
+
+	var JSONQuery entity.IncomingQueryJSON
+	json.Unmarshal(query, &JSONQuery)
+	fmt.Println(JSONQuery)
+	fmt.Println(" ")
+
+	s := NewService()
+	cypher, err := s.ConvertQuery(&JSONQuery)
+	if err != nil {
+		fmt.Println(err)
+		t.Fail()
+		return
+	}
 
-	// answer := `MATCH p0 = (e11:Person)-[:DIRECTED*1..1]-(e12:Movie)
-	// UNWIND relationships(p0) as r10
-	// WITH *
-	// MATCH p1 = (e11:Person)-[:DIRECTED*1..1]-(e12:Movie)
-	// UNWIND relationships(p1) as r10
-	// WITH *
-	// RETURN  r10, e11, e12, r10, e11, e12
-	// LIMIT 5000;nodelink`
+	if cypher == nil {
+		t.Fail()
+		return
+	}
 
-	// trimmedCypher := strings.Replace(*cypher, "\n", "", -1)
-	// trimmedCypher = strings.Replace(trimmedCypher, "\t", "", -1)
+	answer := `MATCH p2 = (e13:Person)-[:ACTED_IN*1..1]-(e12:Movie)
+	UNWIND relationships(p2) as r12 
+	WITH *
+	MATCH p1 = (e12:Movie)-[:ACTED_IN*1..1]-(e11:Person)
+	UNWIND relationships(p1) as r11 
+	WITH *
+	MATCH p0 = (e11:Person)-[:DIRECTED*1..1]-(e12:Movie)
+	UNWIND relationships(p0) as r10 
+	WITH *
+	RETURN  r10, e11, e12, r11, e12, e11, r12, e13, e12
+	LIMIT 5000;nodelink`
+
+	trimmedCypher := strings.Replace(*cypher, "\n", "", -1)
+	trimmedCypher = strings.Replace(trimmedCypher, "\t", "", -1)
 
-	// trimmedAnswer := strings.Replace(answer, "\n", "", -1)
-	// trimmedAnswer = strings.Replace(trimmedAnswer, "\t", "", -1)
+	trimmedAnswer := strings.Replace(answer, "\n", "", -1)
+	trimmedAnswer = strings.Replace(trimmedAnswer, "\t", "", -1)
 
-	// fmt.Println(*cypher)
-	// assert.Equal(t, trimmedAnswer, trimmedAnswer)
+	fmt.Println(*cypher)
+	assert.Equal(t, trimmedAnswer, trimmedCypher)
+}
+func TestTripleCycle(t *testing.T) {
+	query := []byte(`{
+		"return": {
+			"entities": [
+				11,
+				12
+			],
+			"relations": [
+				10
+			],
+			"groupBys": []
+		},
+		"entities": [
+			{
+				"name": "Person",
+				"ID": 11,
+				"constraints": []
+			},
+			{
+				"name": "Movie",
+				"ID": 12,
+				"constraints": []
+			},
+			{
+				"name": "Person",
+				"ID": 13,
+				"constraints": []
+			}
+		],
+		"relations": [
+			{
+			"ID": 10,
+			"name": "DIRECTED",
+			"depth": {
+				"min": 1,
+				"max": 1
+			},
+			"fromType": "entity",
+			"fromID": 11,
+			"toType": "entity",
+			"toID": 12,
+			"constraints": []
+		},
+		{
+			"ID": 11,
+			"name": "ACTED_IN",
+			"depth": {
+				"min": 1,
+				"max": 1
+			},
+			"fromType": "entity",
+			"fromID": 12,
+			"toType": "entity",
+			"toID": 13,
+			"constraints": []
+		},
+		{
+			"ID": 12,
+			"name": "ACTED_IN",
+			"depth": {
+				"min": 1,
+				"max": 1
+			},
+			"fromType": "entity",
+			"fromID": 13,
+			"toType": "entity",
+			"toID": 11,
+			"constraints": []
+		}
+		],
+		"groupBys": [],
+		"machineLearning": [],
+		"limit": 5000,
+		"databaseName": "Movies3"
+	}
+	`)
+
+	var JSONQuery entity.IncomingQueryJSON
+	json.Unmarshal(query, &JSONQuery)
+
+	s := NewService()
+	cypher, err := s.ConvertQuery(&JSONQuery)
+	if err != nil {
+		fmt.Println(err)
+		assert.Equal(t, err, errors.New("Cyclic query detected"))
+		return
+	}
+
+	if cypher == nil {
+		t.Fail()
+		return
+	}
+	t.Fail()
 }
diff --git a/entity/queryStruct.go b/entity/queryStruct.go
index fe43b58524e8dbf14281ff157efd9c73bb20926a..ea069ee5e3d53c2e4b056ebca724dbf607a49933 100644
--- a/entity/queryStruct.go
+++ b/entity/queryStruct.go
@@ -40,6 +40,7 @@ type QueryRelationStruct struct {
 	Constraints []QueryConstraintStruct `json:"constraints"`
 }
 
+// QueryGroupByStruct holds all the info needed to form a group by
 type QueryGroupByStruct struct {
 	ID              int                     `json:"id"`
 	GroupType       string                  `json:"groupType"`
@@ -67,6 +68,7 @@ type QueryConstraintStruct struct {
 	InType    string `json:"inType"`
 }
 
+// QueryMLStruct holds info for machinelearning
 type QueryMLStruct struct {
 	Queuename  string
 	Parameters []string
@@ -116,6 +118,7 @@ func (JSONQuery IncomingQueryJSON) FindG(qID int) *QueryGroupByStruct {
 	return nil
 }
 
+// QueryPart is a struct containing a part of the query and a list of dependencies on which this part of the query depends
 type QueryPart struct {
 	QType        string     // Eg if it is a relation or groupby
 	QID          int        // ID of said relation/gb
@@ -124,8 +127,10 @@ type QueryPart struct {
 	NestedPart   *QueryPart // Pointer to another part, used in some cases to avoid cycles
 }
 
+// Query is a list of (possibly unordered) queryparts
 type Query []QueryPart
 
+// Find retrieves a QueryPart based on the query's specifications
 func (q Query) Find(qID int, qType string) *QueryPart {
 	for i := range q {
 		if q[i].QID == qID && q[i].QType == qType {
@@ -135,6 +140,7 @@ func (q Query) Find(qID int, qType string) *QueryPart {
 	return nil
 }
 
+// SelectByID retrieves a QueryPart based on its PartID
 func (q Query) SelectByID(ID int) *QueryPart {
 	for i := range q {
 		if q[i].PartID == ID {