diff --git a/aql/convertQuery.go b/aql/convertQuery.go
index 9ee0b578ba262ea20839631c7fd0ffec6452b114..46097d4a6dfb459539ab7f237adfe89ba3780452 100644
--- a/aql/convertQuery.go
+++ b/aql/convertQuery.go
@@ -8,7 +8,6 @@ package aql
 import (
 	"errors"
 	"fmt"
-	"strconv"
 
 	"git.science.uu.nl/graphpolaris/query-conversion/entity"
 )
@@ -38,7 +37,7 @@ func (s *Service) ConvertQuery(JSONQuery *entity.IncomingQueryJSON) (*string, er
 
 	// Make sure that no relation mentions a non-existing entity
 	for _, r := range JSONQuery.Relations {
-		if (r.FromID > largestEntityID && r.FromType == "entity") || (r.ToID > largestEntityID && r.ToType == "entity") {
+		if r.FromID > largestEntityID && r.FromType == "entity" || r.ToID > largestEntityID && r.ToType == "entity" {
 			return nil, errors.New("non-exisiting entity referenced in relation")
 		}
 	}
@@ -49,7 +48,6 @@ func (s *Service) ConvertQuery(JSONQuery *entity.IncomingQueryJSON) (*string, er
 			return nil, errors.New("non-existing relation referenced in return")
 		}
 	}
-	search(JSONQuery)
 	result := createQuery(JSONQuery)
 	return result, nil
 }
@@ -60,468 +58,179 @@ createQuery generates a query based on the json file provided
 	Return: *string, a string containing the corresponding AQL query and an error
 */
 func createQuery(JSONQuery *entity.IncomingQueryJSON) *string {
-	// Note: Case #4, where there is an edge only query (without any entity), is not supported by frontend
-
-	// If a modifier is used, disable the limit
-	if len(JSONQuery.Modifiers) > 0 {
-		JSONQuery.Limit = -1
-	}
-
-	var (
-		relationsToReturn []string
-		nodesToReturn     []string
-		nodeUnion         string
-		relationUnion     string
-	)
-	// If we've already used an entity we can set the value to true so we skip it in the result later
-	entityDone := make(map[int]bool)
-	for o := range JSONQuery.Entities {
-		entityDone[o] = false
-	}
-	// Loop over all relations
-	ret := ""
-
-	// Add a WITH statement for entityTo
-	includedTypes := make(map[string]bool)
-	allTypes := make(map[string]bool)
-	for _, relation := range JSONQuery.Relations {
-		if relation.FromID >= 0 && relation.FromType == "entity" {
-			includedTypes[JSONQuery.Entities[relation.FromID].Name] = true
-			allTypes[JSONQuery.Entities[relation.FromID].Name] = true
-
-			// If the type is in the entityTo it is a valid type but not yet included
-			if relation.ToID >= 0 && relation.ToType == "entity" {
-				allTypes[JSONQuery.Entities[relation.ToID].Name] = true
-			}
-		}
-		if relation.FromType != "entity" && relation.ToID >= 0 && relation.ToType == "entity" {
-			includedTypes[JSONQuery.Entities[relation.ToID].Name] = true
-			allTypes[JSONQuery.Entities[relation.ToID].Name] = true
-		}
-	}
-
-	// Include all types that are not yet included
-	first := true
-	for k := range allTypes {
-		if !includedTypes[k] {
-			if first {
-				ret += fmt.Sprintf("WITH %v", k)
-				first = false
-			} else {
-				ret += fmt.Sprintf(", %v", k)
-			}
-		}
-	}
-	if !first {
-		ret += "\n"
-	}
-
-	for i, relation := range JSONQuery.Relations {
-
-		relationName := fmt.Sprintf("r%v", i)
-
-		if relation.FromID >= 0 && relation.FromType == "entity" {
-			// if there is a from-node
-			// create the let for this node
-			// IF WE'VE ALREADY SEEN THIS ENTITY WE DON'T HAVE TO REQUERY IT, WE CAN JUST REUSE THE LET BINDING
-			if !entityDone[relation.FromID] {
-				fromName := fmt.Sprintf("n%v", relation.FromID)
-
-				ret += *createNodeLet(&JSONQuery.Entities[relation.FromID], &fromName, &JSONQuery.Filters)
-				entityDone[relation.FromID] = true
-			}
-			var function *entity.QueryGroupByStruct
-			for _, f := range JSONQuery.GroupBys {
-				if i == f.RelationID {
-					function = &f
-				}
+	query := "LET result = {\"vertices\":[],\"edges\":[]}\n"
+	for list := range listoflists {
+		for index := range listoflists[list] {
+			element := listoflists[list][index]
+			switch element.typename {
+			case "entity":
+				entity := JSONQuery.Entities[element.pointer]
+				query += entityToQuery(entity, JSONQuery)
+			case "relation":
+				relation := JSONQuery.Relations[element.pointer]
+				query += relationToQuery(relation, JSONQuery)
+			case "function":
+				function := JSONQuery.GroupBys[element.pointer]
+				query += functionToQuery(function, JSONQuery, list == len(listoflists)-1)
+			case "filter":
+				filter := JSONQuery.Filters[element.pointer]
+				query += filterToQuery(filter, JSONQuery)
 			}
-			ret += *createRelationLetWithFromEntity(&relation, relationName, &JSONQuery.Entities, JSONQuery.Limit, function, &JSONQuery.Filters)
-
-		} else if relation.ToID >= 0 && relation.ToType == "entity" {
-			fmt.Println("Joris are you a madman! How did this happen?")
-			// if there is only a to-node
-			if !entityDone[relation.ToID] {
-				toName := fmt.Sprintf("n%v", relation.ToID)
-
-				ret += *createNodeLet(&JSONQuery.Entities[relation.ToID], &toName, &JSONQuery.Filters)
-				entityDone[relation.ToID] = true
-			}
-
-			ret += *createRelationLetWithOnlyToEntity(&relation, relationName, &JSONQuery.Entities, JSONQuery.Limit, &JSONQuery.Filters)
-			// Add this relation to the list
-		} else {
-			fmt.Println("Relation-only queries are currently not supported")
-			continue
-		}
-
-		// Add this relation to the list
-		relationsToReturn = append(relationsToReturn, relationName)
-	}
-
-	// Add node let statements for nodes that are not yet returned
-	// Create a set from all the entity-from's and entity-to's, to check if they are returned
-	nodeSet := make(map[int]bool)
-	for _, relation := range JSONQuery.Relations {
-		if relation.FromType == "entity" {
-			nodeSet[relation.FromID] = true
-		}
-		if relation.ToType == "entity" {
-			nodeSet[relation.ToID] = true
 		}
 	}
+	return &query
+}
 
-	// Check if the entities to return are already returned
-	for _, entityIndex := range JSONQuery.Return.Entities {
-		if !nodeSet[entityIndex] {
-			// If not, return this node
-			name := fmt.Sprintf("n%v", entityIndex)
-			ret += *createNodeLet(&JSONQuery.Entities[entityIndex], &name, &JSONQuery.Filters)
-
-			// Add this node to the list
-			nodesToReturn = append(nodesToReturn, name)
-		}
-	}
-
-	if len(JSONQuery.GroupBys) == 0 {
-
-		//If there are modifiers within the query, we run a different set of checks which focus on quantifiable aspects
-		if len(JSONQuery.Modifiers) > 0 {
-			modifier := JSONQuery.Modifiers[0]
-			// There is a distinction between (relations and entities) and (relations or entities)
-			if len(JSONQuery.Return.Relations) > 0 && len(JSONQuery.Return.Entities) > 0 {
-
-				var pathDistinction string // .vertices or .edges
-
-				// Select the correct addition to the return of r0[**]
-				if modifier.SelectedType == "entity" {
-					// ASSUMING THERE IS ONLY 1 RELATION
-					if JSONQuery.Relations[0].FromID == modifier.SelectedTypeID && JSONQuery.Relations[0].FromType == "entity" {
-						// This should always be 0, because that is the start of the path
-						pathDistinction = ".vertices[0]"
-
-					} else {
-						// Otherwise take the depth.max -1 to get the last
-						pathDistinction = fmt.Sprintf(".vertices[%v]", JSONQuery.Relations[0].Depth.Max)
-
-					}
-				} else {
-					pathDistinction = ".edges[**]"
-				}
-
-				// Getting the attribute if there is one
-				if modifier.AttributeIndex != -1 {
-					if modifier.SelectedType == "entity" {
-						nodeFilters := GetFiltersOnNode(&JSONQuery.Entities[modifier.SelectedTypeID], &JSONQuery.Filters)
-						pathDistinction += fmt.Sprintf(".%v", (*nodeFilters)[modifier.AttributeIndex].Attribute)
-
-					} else {
-						relationFilters := GetFiltersOnRelation(&JSONQuery.Relations[modifier.SelectedTypeID], &JSONQuery.Filters)
-						pathDistinction += fmt.Sprintf(".%v", (*relationFilters)[modifier.AttributeIndex].Attribute)
-
-					}
-				}
-
-				// If count is used it has to be replaced with Length + unique else use the modifier type
-				if modifier.Type == "COUNT" {
-					ret += fmt.Sprintf("RETURN LENGTH (unique(r0[*]%v))", pathDistinction)
-
-				} else {
-					ret += fmt.Sprintf("RETURN %v (r0[*]%v)", modifier.Type, pathDistinction)
-
-				}
+func entityToQuery(element entity.QueryEntityStruct, JSONQuery *entity.IncomingQueryJSON) string {
+	thisname := fmt.Sprintf("e%v", element.ID)
+	ret := createLetFor(thisname, element.Name)
+	ret += "\tRETURN x\n)"
+	return ret
+}
 
+func relationToQuery(element entity.QueryRelationStruct, JSONQuery *entity.IncomingQueryJSON) string {
+	thisname := fmt.Sprintf("r%v", element.ID)
+	ret := createLetFor(thisname, element.Name)
+	filters := tryGetFilterTo("relation", element.ID, JSONQuery)
+	var ydefined bool = false
+	var zdefined bool = false
+	if len(filters) > 0 {
+		for i := range filters {
+			filter := filters[i]
+			if filter.FromID == element.FromID {
+				ret += fmt.Sprintf("\tFOR y in f%v\n", filter.ID)
+				ydefined = true
 			} else {
-				// Check if the modifier is on an attribute
-				if modifier.AttributeIndex == -1 {
-					ret += fmt.Sprintf("RETURN LENGTH (n%v)", modifier.SelectedTypeID)
-				} else {
-					var attribute string
-
-					// Selecting the right attribute from either the entity constraint or relation constraint
-					if modifier.SelectedType == "entity" {
-						nodeFilters := GetFiltersOnNode(&JSONQuery.Entities[modifier.SelectedTypeID], &JSONQuery.Filters)
-						attribute = (*nodeFilters)[modifier.AttributeIndex].Attribute
-
-					} else {
-						relationFilters := GetFiltersOnRelation(&JSONQuery.Relations[modifier.SelectedTypeID], &JSONQuery.Filters)
-						attribute = (*relationFilters)[modifier.AttributeIndex].Attribute
-
-					}
-
-					// If count is used it has to be replaced with Length + unique else use the modifier type
-					if modifier.Type == "COUNT" {
-						ret += fmt.Sprintf("RETURN LENGTH (unique(n%v[*].%v))", modifier.SelectedTypeID, attribute)
-
-					} else {
-						ret += fmt.Sprintf("RETURN %v (n%v[*].%v)", modifier.Type, modifier.SelectedTypeID, attribute)
-
-					}
-				}
+				ret += fmt.Sprintf("\tFOR z in f%v\n", filter.ID)
+				zdefined = true
 			}
-
-		} else {
-
-			// Create UNION statements that create unique lists of all the nodes and relations
-			// Thus removing all duplicates
-			nodeUnion = "\nLET nodes = first(RETURN UNION_DISTINCT("
-			for _, relation := range relationsToReturn {
-				nodeUnion += fmt.Sprintf("flatten(%v[**].vertices), ", relation)
-			}
-
-			for _, node := range nodesToReturn {
-				nodeUnion += fmt.Sprintf("%v,", node)
-			}
-			nodeUnion += "[],[]))\n"
-
-			relationUnion = "LET edges = first(RETURN UNION_DISTINCT("
-			for _, relation := range relationsToReturn {
-				relationUnion += fmt.Sprintf("flatten(%v[**].edges), ", relation)
-			}
-			relationUnion += "[],[]))\n"
-
-			ret += nodeUnion + relationUnion
-			ret += "RETURN {\"vertices\":nodes, \"edges\":edges }"
-
 		}
-
-	} else {
-		ret += createTableWithFunctions(&JSONQuery.GroupBys, &JSONQuery.Relations, &JSONQuery.Entities, &JSONQuery.Filters)
 	}
-
-	return &ret
-}
-
-/*
-GetFiltersOnNode gets all the filters on a certain node
-	node: *entity.QueryEntityStruct, node is an entityStruct containing the information of a single node,
-	JSONQuery: *entity.IncomingQueryJSON, the full incoming query,
-	Return: *[]entity.QueryFilterStruct, a list of filters attached to the node
-*/
-func GetFiltersOnNode(node *entity.QueryEntityStruct, filters *[]entity.QueryFilterStruct) *[]entity.QueryFilterStruct {
-	var retval []entity.QueryFilterStruct
-	for _, filter := range *filters {
-		if filter.FilteredType == "entity" && filter.FilteredID == node.ID {
-			retval = append(retval, filter)
-		}
+	if !ydefined {
+		ret += fmt.Sprintf("\tFOR y in %v%v\n", typeToPrefix(element.FromType), element.FromID)
 	}
-	return &retval
-}
-
-func GetFiltersOnRelation(relation *entity.QueryRelationStruct, filters *[]entity.QueryFilterStruct) *[]entity.QueryFilterStruct {
-	var retval []entity.QueryFilterStruct
-	for _, filter := range *filters {
-		if filter.FilteredType == "entity" && filter.FilteredID == relation.ID {
-			retval = append(retval, filter)
-		}
+	if !zdefined {
+		ret += fmt.Sprintf("\tFOR z in %v%v\n", typeToPrefix(element.ToType), element.ToID)
 	}
-	return &retval
+	ret += "\tFILTER x._from == y._id AND x._to == z._id\n"
+	ret += "\tLET nodes = APPEND(result.vertices, [y, z])\n"
+	ret += "\tRETURN DISTINCT {\n"
+	ret += "\t\"edges\": x,\n"
+	ret += "\t\"vertices\": nodes\n\t}\n)"
+	return ret
 }
 
-func GetFiltersOnFunction(function *entity.QueryGroupByStruct, filters *[]entity.QueryFilterStruct) *[]entity.QueryFilterStruct {
-	var retval []entity.QueryFilterStruct
-	for _, filter := range *filters {
-		if filter.FilteredType == "entity" && filter.FilteredID == function.ID {
-			retval = append(retval, filter)
-		}
-	}
-	return &retval
+func functionToQuery(element entity.QueryGroupByStruct, JSONQuery *entity.IncomingQueryJSON, final bool) string {
+	ret := getTupleVar(element, JSONQuery)
+	ret += createGroupBy(element, JSONQuery, final)
+	return ret
 }
 
-/*
-createNodeLet generates a 'LET' statement for a node related query
-	node: *entity.QueryEntityStruct, node is an entityStruct containing the information of a single nod,
-	name: *string, is the autogenerated name of the node consisting of "n" + the index of the node,
-	Return: *string, a string containing a single LET-statement in AQL
-*/
-func createNodeLet(node *entity.QueryEntityStruct, name *string, filters *[]entity.QueryFilterStruct) *string {
-	header := createLetFor(*name, "x", node.Name)
-	footer := "\tRETURN x\n)\n"
-	attachedfilters := GetFiltersOnNode(node, filters)
-	constraints := *createConstraintStatements(attachedfilters, "x", false)
-
-	ret := header + constraints + footer
-	return &ret
+func filterToQuery(element entity.QueryFilterStruct, JSONQuery *entity.IncomingQueryJSON) string {
+	thisname := fmt.Sprintf("f%v", element.ID)
+	ret := createLetFor(thisname, fmt.Sprintf("%v%v", typeToPrefix(element.FromType), element.FromID))
+	ret += fmt.Sprintf("\tFILTER x.%v %v %v\n", element.Attribute, wordsToLogicalSign((element.MatchType)), element.Value)
+	ret += "\tRETURN x\n)"
+	return ret
 }
 
-/*
-createRelationLetWithFromEntity generates a 'LET' statement for relations with an 'EntityFrom' property and optionally an 'EntitiyTo' property
-	relation: *entity.QueryRekationStruct, relation is a relation struct containing the information of a single relation,
-	name: string, is the autogenerated name of the node consisting of "r" + the index of the relation,
-	entities: *[]entity.QueryEntityStrucy, is a list of entityStructs that are needed to form the relation LET-statement,
-	Return: *string, a string containing a single LET-statement in AQL
-*/
-// JSON FORMAT CHANGES COMMENT
-// THIS ONLY GETS CALLED WHEN THE RELATION FROM HAS ALREADY BEEN VERIFIED TO BE AN ENTITY
-// THAT IS WHY WE CAN USE FROMID WITHOUT CHECKING IF IT IS AN ENTITY BEFOREHAND
-func createRelationLetWithFromEntity(relation *entity.QueryRelationStruct, name string, entities *[]entity.QueryEntityStruct, limit int, function *entity.QueryGroupByStruct, filters *[]entity.QueryFilterStruct) *string {
-	header := createLetFor(name, "x", "n"+strconv.Itoa(relation.FromID))
-	forStatement := fmt.Sprintf("\tFOR v, e, p IN %v..%v OUTBOUND x %s \n", relation.Depth.Min, relation.Depth.Max, relation.Name)
-
-	// Guarantees that there is no path returned with a duplicate edge
-	// This way there are no cycle paths possible, TODO: more research about this needed
-	optionStmtn := "\tOPTIONS { uniqueEdges: \"path\" }\n"
-
-	vFilterStmnt := ""
-	if relation.ToType == "entity" {
-		// If there is a to-node, generate the filter statement
-		toFilters := GetFiltersOnNode(&(*entities)[relation.ToID], filters)
-		vFilterStmnt += *createConstraintStatements(toFilters, "v", false)
-	}
-	relationFilters := GetFiltersOnRelation(relation, filters)
-	relationFilterStmnt := *createConstraintStatements(relationFilters, "p", true)
-
-	// Dont use a limit on quantifing queries
-	footer := ""
-	if limit != -1 {
-		footer += fmt.Sprintf("\tLIMIT %v \n", limit)
-	}
-	if function != nil {
-		footer += "RETURN DISTINCT v )\n"
-	} else {
-		footer += "RETURN DISTINCT p )\n"
-	}
-
-	ret := header + forStatement + optionStmtn + vFilterStmnt + relationFilterStmnt + footer
-	return &ret
+func createLetFor(variableName string, enumerableName string) string {
+	return "LET " + variableName + " = (\n\tFOR x IN " + enumerableName + "\n"
 }
 
-/*
-createRelationLetWithOnlyToEntity generates a 'LET' statement for relations with only an 'EntityTo' property
-	relation: *entity.QueryRelationStruct, relation is a relation struct containing the information of a single relation,
-	name: string, is the autogenerated name of the node consisting of "r" + the index of the relation,
-	entities: *[]entity.QueryEntityStruct, is a list of entityStructs that are needed to form the relation LET-statement,
-	Return: *string, a string containing a single LET-statement in AQL
-*/
-// JSON FORMAT CHANGES COMMENT
-// THIS ONLY GETS CALLED WHEN THE RELATION FROM HAS ALREADY BEEN VERIFIED TO BE AN ENTITY
-// THAT IS WHY WE CAN USE FROMID WITHOUT CHECKING IF IT IS AN ENTITY BEFOREHAND
-func createRelationLetWithOnlyToEntity(relation *entity.QueryRelationStruct, name string, entities *[]entity.QueryEntityStruct, limit int, filters *[]entity.QueryFilterStruct) *string {
-	header := createLetFor(name, "x", "n"+strconv.Itoa(relation.ToID))
-	forStatement := fmt.Sprintf("\tFOR v, e, p IN %v..%v INBOUND x %s \n", relation.Depth.Min, relation.Depth.Max, relation.Name)
-
-	// Guarantees that there is no path returned with a duplicate edge
-	// This way there are no cycle paths possible, TODO: more research about this needed
-	optionStmtn := "\tOPTIONS { uniqueEdges: \"path\" }\n"
-
-	relationFilters := GetFiltersOnRelation(relation, filters)
-	relationFilterStmnt := *createConstraintStatements(relationFilters, "p", true)
-
-	// Dont use a limit on quantifing queries
-	footer := ""
-	if limit != -1 {
-		footer += fmt.Sprintf("\tLIMIT %v \n", limit)
+func typeToPrefix(pillType string) string {
+	switch pillType {
+	case "entity":
+		return "e"
+	case "relation":
+		return "r"
+	case "groupBy":
+		return "g"
+	case "filter":
+		return "f"
+	default:
+		return ""
 	}
-	footer += "RETURN DISTINCT p )\n"
-
-	ret := header + forStatement + optionStmtn + relationFilterStmnt + footer
-	return &ret
-}
-
-func createLetFor(variableName string, iteratorName string, enumerableName string) string {
-	return "LET " + variableName + " = (\n\tFOR " + iteratorName + " IN " +
-		enumerableName + " \n"
-}
-
-type variableNameGeneratorToken struct {
-	token int
 }
 
-func newVariableNameGeneratorToken() *variableNameGeneratorToken {
-	v := variableNameGeneratorToken{token: 0}
-	return &v
-}
-
-func variableNameGenerator(vngt *variableNameGeneratorToken) string {
-	result := "variable_" + strconv.Itoa(vngt.token)
-	vngt.token++
-	return result
-}
-
-func createTableWithFunctions(functions *[]entity.QueryGroupByStruct, relations *[]entity.QueryRelationStruct, entities *[]entity.QueryEntityStruct, filters *[]entity.QueryFilterStruct) string {
-	result := ""
-	v := newVariableNameGeneratorToken()
-	for _, function := range *functions {
-		currRelation := (*relations)[function.RelationID]
-		if true {
-			a := variableNameGenerator(v)
-			b := variableNameGenerator(v)
-			c := variableNameGenerator(v)
-			d := variableNameGenerator(v)
-			e := variableNameGenerator(v)
-			f := variableNameGenerator(v)
-			g := variableNameGenerator(v)
-			h := variableNameGenerator(v)
-			rName := fmt.Sprintf("r%v", function.RelationID)
-			nName := fmt.Sprintf("n%v", function.GroupID)
-			result += createTupleVariable(a, b, c, d, e, f, g, currRelation, rName, nName, function)
-			result += createFunction(function, a, f, g, h, filters)
+func tryGetFilterTo(toType string, toID int, JSONQuery *entity.IncomingQueryJSON) []entity.QueryFilterStruct {
+	var list []entity.QueryFilterStruct
+	for i := range JSONQuery.Filters {
+		filter := JSONQuery.Filters[i]
+		if filter.ToType == toType && filter.ToID == toID {
+			list = append(list, filter)
 		}
-
 	}
-	result += "RETURN {"
-	if len(*functions) > 1 {
-		for l := 0; l < len(*functions)-1; l++ {
-			result += "function_" + strconv.Itoa((*functions)[l].ID) + ", "
+	return list
+}
+
+func tryGetFilterFrom(fromType string, fromID int, JSONQuery *entity.IncomingQueryJSON) []entity.QueryFilterStruct {
+	var list []entity.QueryFilterStruct
+	for i := range JSONQuery.Filters {
+		filter := JSONQuery.Filters[i]
+		if filter.FromType == fromType && filter.FromID == fromID {
+			list = append(list, filter)
 		}
 	}
-	result += "function_" + strconv.Itoa((*functions)[len(*functions)-1].ID) + "}"
-	return result
+	return list
 }
 
-func createTupleVariable(a string, b string, c string, d string, e string, f string, g string, currRelation entity.QueryRelationStruct, forName1 string, forName2 string, function entity.QueryGroupByStruct) string {
-	result := ""
-	result += createLetFor(a, "r", currRelation.Name)
-	result += createSubVariable(b, c, forName1, "_id", "r._to", function.ByAttribute)
-	result += createSubVariable(d, e, forName2, "_id", "r._from", function.GroupAttribute)
-	result += createTupleReturn(c, e, "\""+f+"\"", "\""+g+"\"")
-	return result
+func wordsToLogicalSign(word string) string {
+	if word == "LT" {
+		return "<"
+	} else if word == "LTE" {
+		return "<="
+	} else if word == "EQ" {
+		return "=="
+	} else if word == "GTE" {
+		return ">="
+	} else if word == "NEQ" {
+		return "!="
+	} else {
+		return ">"
+	}
 }
 
-func createFunction(function entity.QueryGroupByStruct, variableName1 string, variableName2 string, variableName3 string, variableName4 string, filters *[]entity.QueryFilterStruct) string {
+func getTupleVar(element entity.QueryGroupByStruct, JSONQuery *entity.IncomingQueryJSON) string {
 	result := ""
-	result += createLetFor("function_"+strconv.Itoa(function.ID), "r", variableName1)
-	result += createCollect("c", "r."+variableName2, "r."+variableName3, variableName4, function)
-	functionFilters := GetFiltersOnFunction(&function, filters)
-	if len(*functionFilters) > 0 {
-		result += createFilter(variableName4, function, filters)
-	}
-	result += createTupleReturn("c", variableName4, function.ByAttribute, function.AppliedModifier+"_"+function.GroupAttribute)
+	thisname := fmt.Sprintf("gt%v", element.ID)
+	result += createLetFor(thisname, JSONQuery.Relations[element.RelationID].Name)
+	result += createSubVariable("variable_0", "variable_1", fmt.Sprintf("r%v", element.RelationID), "_id", "r._to", element.ByAttribute)
+	result += createSubVariable("variable_2", "variable_3", fmt.Sprintf("%v%v", typeToPrefix(element.GroupType), element.GroupID), "_id", "r._to", element.GroupAttribute)
+	result += "\tRETURN {\n\t\t\"variable_0\": variable_1, \n\t\t\"variable_1\": variable_3\n\t}\n)\n"
 	return result
 }
 
 func createSubVariable(variableName string, variableName2 string, forName string, filter1 string, filter2 string, returnValue string) string {
-	result := "\t"
-	result += createLetFor(variableName, "c", forName)
-	return result + "\t\tFILTER c." + filter1 + " == " + filter2 + "\n\t\tRETURN c." + returnValue + "\n\t) " +
+	result := "\tLET " + variableName + " = (\n\tFOR y IN " + forName + "\n"
+	return result + "\t\tFILTER y." + filter1 + " == " + filter2 + "\n\t\tRETURN y." + returnValue + "\n\t) " +
 		"\n\tLET " + variableName2 + " = " + variableName + "[0] \n"
 }
 
-func createTupleReturn(assignVariable1 string, assignVariable2 string, variableName1 string, variableName2 string) string {
-	return "\tRETURN {\n\t\t" + variableName1 + " : " + assignVariable1 + ", \n\t\t" +
-		"" + variableName2 + " : " + assignVariable2 + "\n\t}\n) \n"
-}
-
-func createCollect(collectionName string, variableName1 string, variableName2 string, variableName3 string, function entity.QueryGroupByStruct) string {
-	return "\tCOLLECT " + collectionName + " = " + variableName1 + " INTO groups = " + variableName2 + " \n\t\t" +
-		"LET " + variableName3 + " = " + function.AppliedModifier + "(groups) \n\t"
+func createGroupBy(element entity.QueryGroupByStruct, JSONQuery *entity.IncomingQueryJSON, final bool) string {
+	thisname := fmt.Sprintf("g%v", element.ID)
+	tuplename := fmt.Sprintf("gt%v", element.ID)
+	result := createLetFor(thisname, tuplename)
+	result += createCollect(element)
+	filters := tryGetFilterFrom("groupBy", element.ID, JSONQuery)
+	if len(filters) > 0 {
+		for i := range filters {
+			result += createFilter(filters[i])
+		}
+	}
+	if final {
+		result += fmt.Sprintf("\tRETURN {\n\tname: c,\n\t%v: variable_0\n\t}\n)", element.GroupAttribute)
+	} else {
+		result += "\tRETURN c\n)"
+	}
+	return result
 }
 
-func createFilter(variableName string, function entity.QueryGroupByStruct, filters *[]entity.QueryFilterStruct) string {
-	functionFilters := GetFiltersOnFunction(&function, filters)
-	return "FILTER " + variableName + " " + wordsToLogicalSign((*functionFilters)[0].MatchType) + " " + (*functionFilters)[0].Value + " \n\t"
+func createCollect(element entity.QueryGroupByStruct) string {
+	return "\tCOLLECT c = x.variable_0 INTO groups = x.variable_1\n\t\t" +
+		"LET variable_0 = " + element.AppliedModifier + "(groups) \n"
 }
 
-func wordsToLogicalSign(word string) string {
-	if word == "LT" {
-		return "<"
-	} else if word == "LTE" {
-		return "<="
-	} else if word == "EQ" {
-		return "=="
-	} else if word == "GTE" {
-		return ">="
-	} else {
-		return ">"
-	}
+func createFilter(filter entity.QueryFilterStruct) string {
+	return "\tFILTER variable_0 " + wordsToLogicalSign(filter.MatchType) + " " + filter.Value + " \n"
 }
diff --git a/aql/convertQuery2.go b/aql/convertQuery2.go
deleted file mode 100644
index 28388d557957e8d6d486258214f574d137a17930..0000000000000000000000000000000000000000
--- a/aql/convertQuery2.go
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
-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 aql
-
-import (
-	"errors"
-	"fmt"
-
-	"git.science.uu.nl/graphpolaris/query-conversion/entity"
-)
-
-// Version 1.13
-
-/*
-ConvertQuery converts an IncomingQueryJSON object into AQL
-	JSONQuery: *entity.IncomingQueryJSON, the query to be converted to AQL
-	Returns: *string, the AQL query and a possible error
-*/
-func (s *Service) ConvertQuery(JSONQuery *entity.IncomingQueryJSON) (*string, error) {
-
-	// Check to make sure all indexes exist
-	// The largest possible id for an entity
-	largestEntityID := len(JSONQuery.Entities) - 1
-	// The largest possible id for a relation
-	largestRelationID := len(JSONQuery.Relations) - 1
-
-	// Make sure no entity should be returned that is outside the range of that list
-	for _, e := range JSONQuery.Return.Entities {
-		// If this entity references an entity that is outside the range
-		if e > largestEntityID || e < 0 {
-			return nil, errors.New("non-existing entity referenced in return")
-		}
-	}
-
-	// Make sure that no relation mentions a non-existing entity
-	for _, r := range JSONQuery.Relations {
-		if r.EntityFrom > largestEntityID || r.EntityTo > largestEntityID {
-			return nil, errors.New("non-exisiting entity referenced in relation")
-		}
-	}
-
-	// Make sure no non-existing relation is tried to be returned
-	for _, r := range JSONQuery.Return.Relations {
-		if r > largestRelationID || r < 0 {
-			return nil, errors.New("non-existing relation referenced in return")
-		}
-	}
-	result := createQuery(JSONQuery)
-	return result, nil
-}
-
-/*
-createQuery generates a query based on the json file provided
-	JSONQuery: *entity.IncomingQueryJSON, this is a parsedJSON struct holding all the data needed to form a query,
-	Return: *string, a string containing the corresponding AQL query and an error
-*/
-func createQuery(JSONQuery *entity.IncomingQueryJSON) *string {
-	query := ""
-	for list := range listoflists {
-		for index := range listoflists[list] {
-			element := listoflists[list][index]
-			switch element.typename {
-			case "entity":
-				entity := JSONQuery.Entities[element.pointer]
-				query += entityToQuery(entity, JSONQuery)
-			case "relation":
-				relation := JSONQuery.Relations[element.pointer]
-				query += relationToQuery(relation, JSONQuery)
-			case "function":
-				function := JSONQuery.GroupBys[element.pointer]
-				query += functionToQuery(function, JSONQuery)
-			case "filter":
-				filter := JSONQuery.Filters[element.pointer]
-				query += filterToQuery(filter, JSONQuery)
-			}
-		}
-	}
-	return &query
-}
-
-func entityToQuery(element entity.QueryEntityStruct, JSONQuery *entity.IncomingQueryJSON) string {
-	thisname := fmt.Sprintf("e%v", element.ID)
-	ret := createLetFor(thisname, element.Name)
-	ret += "\tRETURN x\n)"
-	return ret
-}
-
-func relationToQuery(element entity.QueryRelationStruct, JSONQuery *entity.IncomingQueryJSON) string {
-	thisname := fmt.Sprintf("r%v", element.ID)
-	ret := createLetFor(thisname, element.Name)
-	ret += fmt.Sprintf("\tFOR y in %v%v\n")
-	return ret
-}
-
-func functionToQuery(element entity.QueryGroupByStruct, JSONQuery *entity.IncomingQueryJSON) string {
-	thisname := fmt.Sprintf("g%v", element.ID)
-	element
-	ret := createLetFor(thisname)
-	return ret
-}
-
-func filterToQuery(element entity.QueryFilterStruct, JSONQuery *entity.IncomingQueryJSON) string {
-	thisname := fmt.Sprintf("f%v", element.ID)
-	ret := createLetFor(thisname, fmt.Sprintf("%v%v", typeToPrefix(element.FromType), element.FromID))
-	ret += fmt.Sprintf("\tFILTER x.%v %v %v\n", element.Attribute, wordsToLogicalSign((element.MatchType)), element.Value)
-	ret += "\tRETURN x\n)"
-	return ret
-}
-
-func createLetFor(variableName string, enumerableName string) string {
-	return "LET " + variableName + " = (\n\tFOR x IN " + enumerableName + "\n"
-}
-
-func typeToPrefix(pillType string) string {
-	switch pillType {
-	case "entity":
-		return "e"
-	case "relation":
-		return "r"
-	case "function":
-		return "g"
-	case "filter":
-		return "f"
-	default:
-		return ""
-	}
-}
-
-func tryGetFilter(toType string, toID int, JSONQuery *entity.IncomingQueryJSON) *entity.QueryFilterStruct {
-	for i := range JSONQuery.Filters {
-		filter := JSONQuery.Filters[i]
-		if filter.ToType == toType && filter.ToID == toID {
-			return &filter
-		}
-	}
-	return nil
-}
-
-func wordsToLogicalSign(word string) string {
-	if word == "LT" {
-		return "<"
-	} else if word == "LTE" {
-		return "<="
-	} else if word == "EQ" {
-		return "=="
-	} else if word == "GTE" {
-		return ">="
-	} else if word == "NEQ" {
-		return "!="
-	} else {
-		return ">"
-	}
-}
diff --git a/test.json b/test.json
index c863d48f8f6cbd1cfa0649d4fa9224262cb77d31..a8d15a4a56a72376eeb2563508d1f19847cb469d 100644
--- a/test.json
+++ b/test.json
@@ -37,8 +37,10 @@
     "filters": [
         {
             "ID": 0,
-            "filteredType": "entity",
-            "filteredID": 0,
+            "fromType": "entity",
+            "fromID": 0,
+            "toType": "entity",
+            "toID": 0,
             "attribute": "age",
             "dataType": "int",
             "matchType": "NEQ",
@@ -48,8 +50,10 @@
         },
         {
             "ID": 1,
-            "filteredType": "relation",
-            "filteredID": 0,
+            "fromType": "relation",
+            "fromID": 0,
+            "toType": "relation",
+            "toID": 0,
             "attribute": "isChairman",
             "dataType": "bool",
             "matchType": "exact",