diff --git a/.gitignore b/.gitignore
index 55fd5e32e74ea895434c02b92ad70ca3811794de..b3442db2f07649c1182f3cb879d73f4661967d02 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
-builds/
\ No newline at end of file
+builds/
+cover.html
+cover.out
diff --git a/integration-testing/config.json b/integration-testing/config.json
index 6ee18939dc2e4625c3e66b6831211326bf882d8f..be98942096c77e10172dc9b3d8d3870dd90a19a7 100644
--- a/integration-testing/config.json
+++ b/integration-testing/config.json
@@ -11,7 +11,14 @@
           "headers": {
             "sessionID": "test-session"
           },
-          "data":"{'Return':{'Entities':[0,1],'Relations':[0]},'Entities':[{'Type':'airports','Constraints':[{'Attribute':'city','Value':'New York','DataType':'text','MatchType':'exact'}]},{'Type':'airports','Constraints':[{'Attribute':'city','Value':'San Francisco','DataType':'text','MatchType':'exact'},{'Attribute':'vip','Value':'true','DataType':'bool','MatchType':'exact'}]}],'Relations':[{'Type':'flights','Depth':{'min':1,'max':1},'EntityFrom':0,'EntityTo':1,'Constraints':[{'Attribute':'Month','Value':'1','DataType':'number','MatchType':'exact'},{'Attribute':'Day','Value':'15','DataType':'number','MatchType':'exact'}]}], 'limit': 1000}"
+          "data":"This is not a valid query"
+        },
+        {
+          "routingKey": "aql-query-request",
+          "headers": {
+            "sessionID": "test-session"
+          },
+          "data":"{\"Return\":{\"Entities\":[0,1],\"Relations\":[0]},\"Entities\":[{\"Type\":\"airports\",\"Constraints\":[{\"Attribute\":\"city\",\"Value\":\"New York\",\"DataType\":\"text\",\"MatchType\":\"exact\"}]},{\"Type\":\"airports\",\"Constraints\":[{\"Attribute\":\"city\",\"Value\":\"San Francisco\",\"DataType\":\"text\",\"MatchType\":\"exact\"},{\"Attribute\":\"vip\",\"Value\":\"true\",\"DataType\":\"bool\",\"MatchType\":\"exact\"}]}],\"Relations\":[{\"Type\":\"flights\",\"Depth\":{\"min\":1,\"max\":1},\"EntityFrom\":0,\"EntityTo\":1,\"Constraints\":[{\"Attribute\":\"Month\",\"Value\":\"1\",\"DataType\":\"number\",\"MatchType\":\"exact\"},{\"Attribute\":\"Day\",\"Value\":\"15\",\"DataType\":\"number\",\"MatchType\":\"exact\"}]}], \"limit\": 1000}"
         }
       ]
     }
@@ -30,13 +37,19 @@
       "type": "exact",
       "consumerid": "consumer1",
       "id": "query result returned",
-      "data": "{'type':'query_result','values':{'edges':[{'_from':'airports/JFK','_id':'flights/286552','_key':'286552','_rev':'_cLqg0be--U','_to':'airports/SFO','attributes':{'ArrTime':2332,'ArrTimeUTC':'2008-01-16T07:32:00.000Z','Day':15,'DayOfWeek':2,'DepTime':2006,'DepTimeUTC':'2008-01-16T01:06:00.000Z','Distance':2586,'FlightNum':649,'Month':1,'TailNum':'N597JB','UniqueCarrier':'B6','Year':2008}},{'_from':'airports/JFK','_id':'flights/286394','_key':'286394','_rev':'_cLqg0bG--s','_to':'airports/SFO','attributes':{'ArrTime':2330,'ArrTimeUTC':'2008-01-16T07:30:00.000Z','Day':15,'DayOfWeek':2,'DepTime':1958,'DepTimeUTC':'2008-01-16T00:58:00.000Z','Distance':2586,'FlightNum':19,'Month':1,'TailNum':'N537UA','UniqueCarrier':'UA','Year':2008}},{'_from':'airports/JFK','_id':'flights/283386','_key':'283386','_rev':'_cLqg0Ty--g','_to':'airports/SFO','attributes':{'ArrTime':2215,'ArrTimeUTC':'2008-01-16T06:15:00.000Z','Day':15,'DayOfWeek':2,'DepTime':1849,'DepTimeUTC':'2008-01-15T23:49:00.000Z','Distance':2586,'FlightNum':73,'Month':1,'TailNum':'N3759','UniqueCarrier':'DL','Year':2008}},{'_from':'airports/JFK','_id':'flights/282498','_key':'282498','_rev':'_cLqg0Rm--Y','_to':'airports/SFO','attributes':{'ArrTime':2358,'ArrTimeUTC':'2008-01-16T07:58:00.000Z','Day':15,'DayOfWeek':2,'DepTime':2052,'DepTimeUTC':'2008-01-16T01:52:00.000Z','Distance':2586,'FlightNum':9,'Month':1,'TailNum':'N554UA','UniqueCarrier':'UA','Year':2008}},{'_from':'airports/JFK','_id':'flights/282321','_key':'282321','_rev':'_cLqg0RK--s','_to':'airports/SFO','attributes':{'ArrTime':2132,'ArrTimeUTC':'2008-01-16T05:32:00.000Z','Day':15,'DayOfWeek':2,'DepTime':1825,'DepTimeUTC':'2008-01-15T23:25:00.000Z','Distance':2586,'FlightNum':647,'Month':1,'TailNum':'N651JB','UniqueCarrier':'B6','Year':2008}},{'_from':'airports/JFK','_id':'flights/281151','_key':'281151','_rev':'_cLqg0Oe--M','_to':'airports/SFO','attributes':{'ArrTime':2108,'ArrTimeUTC':'2008-01-16T05:08:00.000Z','Day':15,'DayOfWeek':2,'DepTime':1746,'DepTimeUTC':'2008-01-15T22:46:00.000Z','Distance':2586,'FlightNum':17,'Month':1,'TailNum':'N560UA','UniqueCarrier':'UA','Year':2008}},{'_from':'airports/JFK','_id':'flights/281077','_key':'281077','_rev':'_cLqg0OS--S','_to':'airports/SFO','attributes':{'ArrTime':2119,'ArrTimeUTC':'2008-01-16T05:19:00.000Z','Day':15,'DayOfWeek':2,'DepTime':1742,'DepTimeUTC':'2008-01-15T22:42:00.000Z','Distance':2586,'FlightNum':177,'Month':1,'TailNum':'N321AA','UniqueCarrier':'AA','Year':2008}},{'_from':'airports/JFK','_id':'flights/279990','_key':'279990','_rev':'_cLqg0Lq--m','_to':'airports/SFO','attributes':{'ArrTime':1423,'ArrTimeUTC':'2008-01-15T22:23:00.000Z','Day':15,'DayOfWeek':2,'DepTime':1114,'DepTimeUTC':'2008-01-15T16:14:00.000Z','Distance':2586,'FlightNum':11,'Month':1,'TailNum':'N555UA','UniqueCarrier':'UA','Year':2008}},{'_from':'airports/JFK','_id':'flights/279206','_key':'279206','_rev':'_cLqg0Jy--U','_to':'airports/SFO','attributes':{'ArrTime':1406,'ArrTimeUTC':'2008-01-15T22:06:00.000Z','Day':15,'DayOfWeek':2,'DepTime':1054,'DepTimeUTC':'2008-01-15T15:54:00.000Z','Distance':2586,'FlightNum':15,'Month':1,'TailNum':'N356AA','UniqueCarrier':'AA','Year':2008}},{'_from':'airports/JFK','_id':'flights/278458','_key':'278458','_rev':'_cLqg0H6--s','_to':'airports/SFO','attributes':{'ArrTime':2003,'ArrTimeUTC':'2008-01-16T04:03:00.000Z','Day':15,'DayOfWeek':2,'DepTime':1624,'DepTimeUTC':'2008-01-15T21:24:00.000Z','Distance':2586,'FlightNum':151,'Month':1,'TailNum':'N3744D','UniqueCarrier':'DL','Year':2008}},{'_from':'airports/JFK','_id':'flights/276601','_key':'276601','_rev':'_cLqg0Dq--O','_to':'airports/SFO','attributes':{'ArrTime':1909,'ArrTimeUTC':'2008-01-16T03:09:00.000Z','Day':15,'DayOfWeek':2,'DepTime':1535,'DepTimeUTC':'2008-01-15T20:35:00.000Z','Distance':2586,'FlightNum':15,'Month':1,'TailNum':'N510UA','UniqueCarrier':'UA','Year':2008}},{'_from':'airports/JFK','_id':'flights/276139','_key':'276139','_rev':'_cLqg0Ci--i','_to':'airports/SFO','attributes':{'ArrTime':1815,'ArrTimeUTC':'2008-01-16T02:15:00.000Z','Day':15,'DayOfWeek':2,'DepTime':1524,'DepTimeUTC':'2008-01-15T20:24:00.000Z','Distance':2586,'FlightNum':85,'Month':1,'TailNum':'N373AA','UniqueCarrier':'AA','Year':2008}},{'_from':'airports/JFK','_id':'flights/273773','_key':'273773','_rev':'_cLqgz86--K','_to':'airports/SFO','attributes':{'ArrTime':1156,'ArrTimeUTC':'2008-01-15T19:56:00.000Z','Day':15,'DayOfWeek':2,'DepTime':840,'DepTimeUTC':'2008-01-15T13:40:00.000Z','Distance':2586,'FlightNum':2979,'Month':1,'TailNum':'N387AA','UniqueCarrier':'AA','Year':2008}},{'_from':'airports/JFK','_id':'flights/273538','_key':'273538','_rev':'_cLqgz8W--k','_to':'airports/SFO','attributes':{'ArrTime':1131,'ArrTimeUTC':'2008-01-15T19:31:00.000Z','Day':15,'DayOfWeek':2,'DepTime':831,'DepTimeUTC':'2008-01-15T13:31:00.000Z','Distance':2586,'FlightNum':893,'Month':1,'TailNum':'N505UA','UniqueCarrier':'UA','Year':2008}},{'_from':'airports/JFK','_id':'flights/272322','_key':'272322','_rev':'_cLqgz5q--g','_to':'airports/SFO','attributes':{'ArrTime':1118,'ArrTimeUTC':'2008-01-15T19:18:00.000Z','Day':15,'DayOfWeek':2,'DepTime':757,'DepTimeUTC':'2008-01-15T12:57:00.000Z','Distance':2586,'FlightNum':641,'Month':1,'TailNum':'N528JB','UniqueCarrier':'B6','Year':2008}},{'_from':'airports/JFK','_id':'flights/271860','_key':'271860','_rev':'_cLqgz4q--G','_to':'airports/SFO','attributes':{'ArrTime':1133,'ArrTimeUTC':'2008-01-15T19:33:00.000Z','Day':15,'DayOfWeek':2,'DepTime':743,'DepTimeUTC':'2008-01-15T12:43:00.000Z','Distance':2586,'FlightNum':877,'Month':1,'TailNum':'N502UA','UniqueCarrier':'UA','Year':2008}},{'_from':'airports/JFK','_id':'flights/270140','_key':'270140','_rev':'_cLqgz02--K','_to':'airports/SFO','attributes':{'ArrTime':1042,'ArrTimeUTC':'2008-01-15T18:42:00.000Z','Day':15,'DayOfWeek':2,'DepTime':650,'DepTimeUTC':'2008-01-15T11:50:00.000Z','Distance':2586,'FlightNum':59,'Month':1,'TailNum':'N399AA','UniqueCarrier':'AA','Year':2008}},{'_from':'airports/JFK','_id':'flights/269347','_key':'269347','_rev':'_cLqgzz---A','_to':'airports/SFO','attributes':{'ArrTime':913,'ArrTimeUTC':'2008-01-15T17:13:00.000Z','Day':15,'DayOfWeek':2,'DepTime':606,'DepTimeUTC':'2008-01-15T11:06:00.000Z','Distance':2586,'FlightNum':5,'Month':1,'TailNum':'N537UA','UniqueCarrier':'UA','Year':2008}}],'nodes':[{'_id':'airports/SFO','_key':'SFO','_rev':'_cLp3eL6-_G','attributes':{'city':'San Francisco','country':'USA','lat':37.61900194,'long':-122.3748433,'name':'San Francisco International','state':'CA','vip':true}},{'_id':'airports/JFK','_key':'JFK','_rev':'_cLp3eLO-_I','attributes':{'city':'New York','country':'USA','lat':40.63975111,'long':-73.77892556,'name':'John F Kennedy Intl','state':'NY','vip':true}}]}}" 
+      "data": "{\"type\":\"query_result\",\"values\":{\"edges\":[{\"_from\":\"airports/JFK\",\"_id\":\"flights/286552\",\"_key\":\"286552\",\"_rev\":\"_cLqg0be--U\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":2332,\"ArrTimeUTC\":\"2008-01-16T07:32:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":2006,\"DepTimeUTC\":\"2008-01-16T01:06:00.000Z\",\"Distance\":2586,\"FlightNum\":649,\"Month\":1,\"TailNum\":\"N597JB\",\"UniqueCarrier\":\"B6\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/286394\",\"_key\":\"286394\",\"_rev\":\"_cLqg0bG--s\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":2330,\"ArrTimeUTC\":\"2008-01-16T07:30:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":1958,\"DepTimeUTC\":\"2008-01-16T00:58:00.000Z\",\"Distance\":2586,\"FlightNum\":19,\"Month\":1,\"TailNum\":\"N537UA\",\"UniqueCarrier\":\"UA\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/283386\",\"_key\":\"283386\",\"_rev\":\"_cLqg0Ty--g\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":2215,\"ArrTimeUTC\":\"2008-01-16T06:15:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":1849,\"DepTimeUTC\":\"2008-01-15T23:49:00.000Z\",\"Distance\":2586,\"FlightNum\":73,\"Month\":1,\"TailNum\":\"N3759\",\"UniqueCarrier\":\"DL\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/282498\",\"_key\":\"282498\",\"_rev\":\"_cLqg0Rm--Y\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":2358,\"ArrTimeUTC\":\"2008-01-16T07:58:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":2052,\"DepTimeUTC\":\"2008-01-16T01:52:00.000Z\",\"Distance\":2586,\"FlightNum\":9,\"Month\":1,\"TailNum\":\"N554UA\",\"UniqueCarrier\":\"UA\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/282321\",\"_key\":\"282321\",\"_rev\":\"_cLqg0RK--s\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":2132,\"ArrTimeUTC\":\"2008-01-16T05:32:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":1825,\"DepTimeUTC\":\"2008-01-15T23:25:00.000Z\",\"Distance\":2586,\"FlightNum\":647,\"Month\":1,\"TailNum\":\"N651JB\",\"UniqueCarrier\":\"B6\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/281151\",\"_key\":\"281151\",\"_rev\":\"_cLqg0Oe--M\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":2108,\"ArrTimeUTC\":\"2008-01-16T05:08:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":1746,\"DepTimeUTC\":\"2008-01-15T22:46:00.000Z\",\"Distance\":2586,\"FlightNum\":17,\"Month\":1,\"TailNum\":\"N560UA\",\"UniqueCarrier\":\"UA\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/281077\",\"_key\":\"281077\",\"_rev\":\"_cLqg0OS--S\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":2119,\"ArrTimeUTC\":\"2008-01-16T05:19:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":1742,\"DepTimeUTC\":\"2008-01-15T22:42:00.000Z\",\"Distance\":2586,\"FlightNum\":177,\"Month\":1,\"TailNum\":\"N321AA\",\"UniqueCarrier\":\"AA\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/279990\",\"_key\":\"279990\",\"_rev\":\"_cLqg0Lq--m\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":1423,\"ArrTimeUTC\":\"2008-01-15T22:23:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":1114,\"DepTimeUTC\":\"2008-01-15T16:14:00.000Z\",\"Distance\":2586,\"FlightNum\":11,\"Month\":1,\"TailNum\":\"N555UA\",\"UniqueCarrier\":\"UA\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/279206\",\"_key\":\"279206\",\"_rev\":\"_cLqg0Jy--U\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":1406,\"ArrTimeUTC\":\"2008-01-15T22:06:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":1054,\"DepTimeUTC\":\"2008-01-15T15:54:00.000Z\",\"Distance\":2586,\"FlightNum\":15,\"Month\":1,\"TailNum\":\"N356AA\",\"UniqueCarrier\":\"AA\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/278458\",\"_key\":\"278458\",\"_rev\":\"_cLqg0H6--s\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":2003,\"ArrTimeUTC\":\"2008-01-16T04:03:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":1624,\"DepTimeUTC\":\"2008-01-15T21:24:00.000Z\",\"Distance\":2586,\"FlightNum\":151,\"Month\":1,\"TailNum\":\"N3744D\",\"UniqueCarrier\":\"DL\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/276601\",\"_key\":\"276601\",\"_rev\":\"_cLqg0Dq--O\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":1909,\"ArrTimeUTC\":\"2008-01-16T03:09:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":1535,\"DepTimeUTC\":\"2008-01-15T20:35:00.000Z\",\"Distance\":2586,\"FlightNum\":15,\"Month\":1,\"TailNum\":\"N510UA\",\"UniqueCarrier\":\"UA\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/276139\",\"_key\":\"276139\",\"_rev\":\"_cLqg0Ci--i\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":1815,\"ArrTimeUTC\":\"2008-01-16T02:15:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":1524,\"DepTimeUTC\":\"2008-01-15T20:24:00.000Z\",\"Distance\":2586,\"FlightNum\":85,\"Month\":1,\"TailNum\":\"N373AA\",\"UniqueCarrier\":\"AA\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/273773\",\"_key\":\"273773\",\"_rev\":\"_cLqgz86--K\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":1156,\"ArrTimeUTC\":\"2008-01-15T19:56:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":840,\"DepTimeUTC\":\"2008-01-15T13:40:00.000Z\",\"Distance\":2586,\"FlightNum\":2979,\"Month\":1,\"TailNum\":\"N387AA\",\"UniqueCarrier\":\"AA\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/273538\",\"_key\":\"273538\",\"_rev\":\"_cLqgz8W--k\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":1131,\"ArrTimeUTC\":\"2008-01-15T19:31:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":831,\"DepTimeUTC\":\"2008-01-15T13:31:00.000Z\",\"Distance\":2586,\"FlightNum\":893,\"Month\":1,\"TailNum\":\"N505UA\",\"UniqueCarrier\":\"UA\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/272322\",\"_key\":\"272322\",\"_rev\":\"_cLqgz5q--g\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":1118,\"ArrTimeUTC\":\"2008-01-15T19:18:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":757,\"DepTimeUTC\":\"2008-01-15T12:57:00.000Z\",\"Distance\":2586,\"FlightNum\":641,\"Month\":1,\"TailNum\":\"N528JB\",\"UniqueCarrier\":\"B6\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/271860\",\"_key\":\"271860\",\"_rev\":\"_cLqgz4q--G\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":1133,\"ArrTimeUTC\":\"2008-01-15T19:33:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":743,\"DepTimeUTC\":\"2008-01-15T12:43:00.000Z\",\"Distance\":2586,\"FlightNum\":877,\"Month\":1,\"TailNum\":\"N502UA\",\"UniqueCarrier\":\"UA\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/270140\",\"_key\":\"270140\",\"_rev\":\"_cLqgz02--K\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":1042,\"ArrTimeUTC\":\"2008-01-15T18:42:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":650,\"DepTimeUTC\":\"2008-01-15T11:50:00.000Z\",\"Distance\":2586,\"FlightNum\":59,\"Month\":1,\"TailNum\":\"N399AA\",\"UniqueCarrier\":\"AA\",\"Year\":2008}},{\"_from\":\"airports/JFK\",\"_id\":\"flights/269347\",\"_key\":\"269347\",\"_rev\":\"_cLqgzz---A\",\"_to\":\"airports/SFO\",\"attributes\":{\"ArrTime\":913,\"ArrTimeUTC\":\"2008-01-15T17:13:00.000Z\",\"Day\":15,\"DayOfWeek\":2,\"DepTime\":606,\"DepTimeUTC\":\"2008-01-15T11:06:00.000Z\",\"Distance\":2586,\"FlightNum\":5,\"Month\":1,\"TailNum\":\"N537UA\",\"UniqueCarrier\":\"UA\",\"Year\":2008}}],\"nodes\":[{\"_id\":\"airports/SFO\",\"_key\":\"SFO\",\"_rev\":\"_cLp3eL6-_G\",\"attributes\":{\"city\":\"San Francisco\",\"country\":\"USA\",\"lat\":37.61900194,\"long\":-122.3748433,\"name\":\"San Francisco International\",\"state\":\"CA\",\"vip\":true}},{\"_id\":\"airports/JFK\",\"_key\":\"JFK\",\"_rev\":\"_cLp3eLO-_I\",\"attributes\":{\"city\":\"New York\",\"country\":\"USA\",\"lat\":40.63975111,\"long\":-73.77892556,\"name\":\"John F Kennedy Intl\",\"state\":\"NY\",\"vip\":true}}]}}" 
     },
     {
       "type": "exact",
       "consumerid": "consumer1",
       "id": "query translation result returned",
-      "data": "{'type':'query_translation_result','values':'LET n0 = (FOR x IN airports FILTER x.city == \\\"New York\\\" RETURN x)LET r0 = (FOR x IN n0 FOR v, e, p IN 1..1 OUTBOUND x flights OPTIONS { uniqueEdges: \\\"path\\\" }FILTER v.city == \\\"San Francisco\\\" AND v.vip == true FILTER p.edges[*].Month ALL == 1 AND p.edges[*].Day ALL == 15 LIMIT 1000 RETURN DISTINCT p )LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), [],[]))LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), [],[]))RETURN {\\\"vertices\\\":nodes, \\\"edges\\\":edges }'}" 
+      "data": "{\"type\":\"query_translation_result\",\"values\":\"LET n0 = (FOR x IN airports FILTER x.city == \\\"New York\\\" RETURN x)LET r0 = (FOR x IN n0 FOR v, e, p IN 1..1 OUTBOUND x flights OPTIONS { uniqueEdges: \\\"path\\\" }FILTER v.city == \\\"San Francisco\\\" AND v.vip == true FILTER p.edges[*].Month ALL == 1 AND p.edges[*].Day ALL == 15 LIMIT 1000 RETURN DISTINCT p )LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), [],[]))LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), [],[]))RETURN {\\\"vertices\\\":nodes, \\\"edges\\\":edges }\"}" 
+    },
+    {
+      "type": "exact",
+      "consumerid": "consumer1",
+      "id": "query translation error returned",
+      "data": "{\"type\":\"query_translation_error\",\"value\":\"invalid character 'T' looking for beginning of value\"}"
     }
   ],
   "redisSet": {
diff --git a/internal/drivers/brokerdriver/interface.go b/internal/drivers/brokerdriver/interface.go
index 3aacf64fea45b25f2eb1dd9c89792ceecbf8192f..3dc54da2fc47fbae03fcf60d59c5dedcf8f296f6 100644
--- a/internal/drivers/brokerdriver/interface.go
+++ b/internal/drivers/brokerdriver/interface.go
@@ -20,5 +20,5 @@ type Consumer interface {
 
 // A Producer belongs to a broker and publishes messages to a queue
 type Producer interface {
-	PublishMessage(body *[]byte, queueID *string, headers *amqp.Table)
+	PublishMessage(body *[]byte, routingKey *string, headers *amqp.Table)
 }
diff --git a/internal/drivers/brokerdriver/mock/broker.go b/internal/drivers/brokerdriver/mock/broker.go
index 8483d8fdc1f2b4d2d25061596854daf041d79393..80f1c1c89637212a46c18cd1fd89fc32a2a6c8f7 100644
--- a/internal/drivers/brokerdriver/mock/broker.go
+++ b/internal/drivers/brokerdriver/mock/broker.go
@@ -8,18 +8,32 @@ import (
 // Driver is mock gateway
 type Driver struct {
 	gateway brokeradapter.GatewayInterface
+
+	// Mock messages that are published by producers on this broker
+	// Key is the routing key
+	// Value is a slice of messages, in order of being sent 'first -> last'
+	Messages map[string][]brokeradapter.Message
 }
 
-// CreateBroker is a creates a mock driver
+// CreateBroker creates a broker driver (mock)
 func CreateBroker(gateway brokeradapter.GatewayInterface) *Driver {
 	return &Driver{
-		gateway: gateway,
+		gateway:  gateway,
+		Messages: make(map[string][]brokeradapter.Message),
 	}
 }
 
-// CreateConsumer creates a mock consumer
+// CreateConsumer creates a consumer (mock)
 func (d *Driver) CreateConsumer() brokerdriver.Consumer {
 	return &Consumer{
 		broker: d,
 	}
 }
+
+// CreateProducer creates a producer (mock)
+func (d *Driver) CreateProducer() brokerdriver.Producer {
+	return &Producer{
+		broker:   d,
+		exchange: "ui-direct-exchange", // This is the only exchange this service produces to
+	}
+}
diff --git a/internal/drivers/brokerdriver/mock/consumer.go b/internal/drivers/brokerdriver/mock/consumer.go
index b3391265198146245752370f2f559524e73df65b..9118043873bffca0bad53758fc7c109361cf409c 100644
--- a/internal/drivers/brokerdriver/mock/consumer.go
+++ b/internal/drivers/brokerdriver/mock/consumer.go
@@ -2,17 +2,17 @@ package mockbrokerdriver
 
 import "query-service/internal/adapters/brokeradapter"
 
-// Consumer is a mock consumer
+// A Consumer implements the consumer interface (mock)
 type Consumer struct {
 	broker *Driver
 }
 
-// ConsumeMessages mocks the consume messages func
+// ConsumeMessages consumes messages from the broker (mock)
 func (c *Consumer) ConsumeMessages() {
 
 }
 
-// SetMessageHandler mocks the setting of a message handler
+// SetMessageHandler mocks the setting of a message handler (mock)
 func (c *Consumer) SetMessageHandler(handler func(msg *brokeradapter.Message)) {
 
 }
diff --git a/internal/drivers/brokerdriver/mock/producer.go b/internal/drivers/brokerdriver/mock/producer.go
new file mode 100644
index 0000000000000000000000000000000000000000..1367971d059641fec4a3c0adcec28cf6d4591bd3
--- /dev/null
+++ b/internal/drivers/brokerdriver/mock/producer.go
@@ -0,0 +1,27 @@
+package mockbrokerdriver
+
+import (
+	"query-service/internal/adapters/brokeradapter"
+
+	"github.com/streadway/amqp"
+)
+
+// A Producer implements the producer interface (mock)
+type Producer struct {
+	broker *Driver
+
+	// The exchange this producer is connected to
+	exchange string
+}
+
+// PublishMessage publishes a message to the given queue (mock)
+func (p *Producer) PublishMessage(body *[]byte, routingKey *string, headers *amqp.Table) {
+	// Create the message
+	msg := brokeradapter.Message{
+		Headers: *headers,
+		Body:    *body,
+	}
+
+	// Append the message to the list
+	p.broker.Messages[*routingKey] = append(p.broker.Messages[*routingKey], msg)
+}
diff --git a/internal/drivers/brokerdriver/producer.go b/internal/drivers/brokerdriver/producer.go
index e037aac06b3c6e2911851f722dd17017b5c21653..513e43d41b55110590092c0c9dc7479b7dd83402 100644
--- a/internal/drivers/brokerdriver/producer.go
+++ b/internal/drivers/brokerdriver/producer.go
@@ -14,10 +14,10 @@ type AliceProducer struct {
 	producer alice.Producer
 }
 
-// PublishMessage will publish a message to the specified queue id
-func (ap *AliceProducer) PublishMessage(body *[]byte, queueID *string, headers *amqp.Table) {
+// PublishMessage will publish a message to the specified queue id (mock)
+func (ap *AliceProducer) PublishMessage(body *[]byte, routingKey *string, headers *amqp.Table) {
 	sessionID := (*headers)["sessionID"]
-	logger.Log(fmt.Sprintf("Publishing message to queue %v, for session %v", *queueID, sessionID))
+	logger.Log(fmt.Sprintf("Publishing message to queue %v, for session %v", *routingKey, sessionID))
 
-	ap.producer.PublishMessage(*body, queueID, headers)
+	ap.producer.PublishMessage(*body, routingKey, headers)
 }
diff --git a/internal/drivers/keyvaluedriver/interface.go b/internal/drivers/keyvaluedriver/interface.go
index ad465b3f7f4212470076b09d9edaa38edab9892d..9c2c98c3d1e0606e253c9cc381e3ed034e37a06c 100644
--- a/internal/drivers/keyvaluedriver/interface.go
+++ b/internal/drivers/keyvaluedriver/interface.go
@@ -1,7 +1,7 @@
 package keyvaluedriver
 
-// KeyValueStore is an interface for a key value storage
-type KeyValueStore interface {
-	Get(key *string) *string
-	Set(key *string, value interface{}) error
+// KeyValueStoreInterface is an interface for a key value storage
+type KeyValueStoreInterface interface {
+	Get(key *string) string
+	Set(key *string, value *string) error
 }
diff --git a/internal/drivers/keyvaluedriver/redisdriver.go b/internal/drivers/keyvaluedriver/keyvaluedriver.go
similarity index 63%
rename from internal/drivers/keyvaluedriver/redisdriver.go
rename to internal/drivers/keyvaluedriver/keyvaluedriver.go
index c3420dd52d3196bdced96d97e8de3d30dccfd028..15c3595072b3b1b4229cea9d48b58890f1931d59 100644
--- a/internal/drivers/keyvaluedriver/redisdriver.go
+++ b/internal/drivers/keyvaluedriver/keyvaluedriver.go
@@ -9,18 +9,18 @@ import (
 	"github.com/go-redis/redis/v8"
 )
 
-// RedisDriver models the redis driver
-type RedisDriver struct {
+// KeyValueDriver models the redis driver
+type KeyValueDriver struct {
 	client *redis.Client
 }
 
 // NewRedisDriver creates and returns a redis driver
-func NewRedisDriver() *RedisDriver {
-	return &RedisDriver{}
+func NewRedisDriver() *KeyValueDriver {
+	return &KeyValueDriver{}
 }
 
 // Start starts the redis driver
-func (d *RedisDriver) Start() {
+func (d *KeyValueDriver) Start() {
 	// Grab the redis host and port from environment vars
 	redisAddress := os.Getenv("REDIS_ADDRESS")
 	// redisPassword := os.Getenv("REDIS_PASSWORD")
@@ -35,13 +35,12 @@ func (d *RedisDriver) Start() {
 }
 
 // Get retrieves the value from the redis store that belongs to the given key
-func (d *RedisDriver) Get(key *string) *string {
-	value := d.client.Get(context.Background(), *key).Val()
-	return &value
+func (d *KeyValueDriver) Get(key *string) string {
+	return d.client.Get(context.Background(), *key).Val()
 }
 
 // Set sets the key value pair in the redis store
-func (d *RedisDriver) Set(key *string, value interface{}) error {
-	status := d.client.Set(context.Background(), *key, value, 0)
+func (d *KeyValueDriver) Set(key *string, value *string) error {
+	status := d.client.Set(context.Background(), *key, *value, 0)
 	return status.Err()
 }
diff --git a/internal/drivers/keyvaluedriver/mock/mockkeyvaluedriver.go b/internal/drivers/keyvaluedriver/mock/mockkeyvaluedriver.go
new file mode 100644
index 0000000000000000000000000000000000000000..981b7cdacb6d455d966913406dbe9569fed896df
--- /dev/null
+++ b/internal/drivers/keyvaluedriver/mock/mockkeyvaluedriver.go
@@ -0,0 +1,24 @@
+package mockkeyvaluedriver
+
+// A KeyValueStore implements methods to set key-value data (mock)
+type KeyValueStore struct {
+	data map[string]string
+}
+
+// CreateKeyValueStore creates a key value store driver (mock)
+func CreateKeyValueStore() *KeyValueStore {
+	return &KeyValueStore{
+		data: make(map[string]string),
+	}
+}
+
+// Set sets a key to a value in the key value store. Expects a non-pointer as value. (mock)
+func (kvs *KeyValueStore) Set(key *string, value *string) error {
+	kvs.data[*key] = *value
+	return nil
+}
+
+// Get gets the value for the supplied key from the key value store (mock)
+func (kvs *KeyValueStore) Get(key *string) string {
+	return kvs.data[*key]
+}
diff --git a/internal/entity/document.go b/internal/entity/document.go
new file mode 100644
index 0000000000000000000000000000000000000000..08ef36d21bf6d9943034e2080d49b8110e621266
--- /dev/null
+++ b/internal/entity/document.go
@@ -0,0 +1,13 @@
+package entity
+
+// Document with Empty struct to retrieve all data from the DB Document
+type Document map[string]interface{}
+
+// GeneralFormat with Empty struct to retrieve all data from the DB Document
+type GeneralFormat map[string][]Document
+
+// ListContainer is a struct that keeps track of the nodes and edges that need to be returned
+type ListContainer struct {
+	NodeList []Document
+	EdgeList []Document
+}
diff --git a/internal/entity/querystruct.go b/internal/entity/querystruct.go
new file mode 100644
index 0000000000000000000000000000000000000000..8e3d4f28fc6bcf4a0e502d871db3fca36fce1b2d
--- /dev/null
+++ b/internal/entity/querystruct.go
@@ -0,0 +1,53 @@
+package entity
+
+// QueryParsedJSON is used for JSON conversion of the incoming byte array
+type QueryParsedJSON struct {
+	Return    QueryReturnStruct
+	Entities  []QueryEntityStruct
+	Relations []QueryRelationStruct
+
+	// Limit is for limiting the amount of paths AQL will return in a relation let statement
+	Limit int
+}
+
+// QueryReturnStruct holds the indices of the entities and relations that need to be returned
+type QueryReturnStruct struct {
+	Entities  []int
+	Relations []int
+}
+
+// QueryEntityStruct encapsulates a single entity with its corresponding constraints
+type QueryEntityStruct struct {
+	Type        string
+	Constraints []QueryConstraintStruct
+}
+
+// QueryRelationStruct encapsulates a single relation with its corresponding constraints
+type QueryRelationStruct struct {
+	Type        string
+	EntityFrom  int
+	EntityTo    int
+	Depth       QuerySearchDepthStruct
+	Constraints []QueryConstraintStruct
+}
+
+// QuerySearchDepthStruct holds the range of traversals for the relation
+type QuerySearchDepthStruct struct {
+	Min int
+	Max int
+}
+
+/*
+QueryConstraintStruct holds the information of the constraint
+
+Constraint datatypes
+	text     MatchTypes: exact/contains/startswith/endswith
+	number   MatchTypes: GT/LT/EQ
+	bool     MatchTypes: EQ/NEQ
+*/
+type QueryConstraintStruct struct {
+	Attribute string
+	Value     string
+	DataType  string
+	MatchType string
+}
diff --git a/internal/usecases/consume/consume.go b/internal/usecases/consume/consume.go
index 2ccb2e3bbdce20cbd2ddfcea32202a36ca1752f5..af9cd8f6427f868f93e5cd65c1b31bb941160e71 100644
--- a/internal/usecases/consume/consume.go
+++ b/internal/usecases/consume/consume.go
@@ -17,11 +17,11 @@ type Service struct {
 }
 
 // NewService creates a new service
-func NewService(broker brokerdriver.Broker, produceService produce.UseCase, converQueryService convertquery.UseCase, requestSenderService request.UseCase) *Service {
+func NewService(broker brokerdriver.Broker, produceService produce.UseCase, convertQueryService convertquery.UseCase, requestSenderService request.UseCase) *Service {
 	return &Service{
 		broker:         broker,
 		producer:       produceService,
-		queryConverter: converQueryService,
+		queryConverter: convertQueryService,
 		requestSender:  requestSenderService,
 	}
 }
diff --git a/internal/usecases/consume/consume_test.go b/internal/usecases/consume/consume_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..acea44e1662df3eaf51d51fec2558f5391e79e90
--- /dev/null
+++ b/internal/usecases/consume/consume_test.go
@@ -0,0 +1,215 @@
+package consume
+
+import (
+	"encoding/json"
+	"query-service/internal/adapters/brokeradapter"
+	mockbrokerdriver "query-service/internal/drivers/brokerdriver/mock"
+	mockkeyvaluedriver "query-service/internal/drivers/keyvaluedriver/mock"
+	mockconvertquery "query-service/internal/usecases/convertquery/mock"
+	"query-service/internal/usecases/produce"
+	mockrequest "query-service/internal/usecases/request/mock"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestStart(t *testing.T) {
+	// // Create broker adapter
+	// brokerAdapter := brokeradapter.CreateGateway()
+	// // Create a mock broker
+	// mockBroker := mockbrokerdriver.CreateBroker(brokerAdapter)
+	// // Create mock key value store
+	// keyValueStore := mockkeyvaluedriver.CreateKeyValueStore()
+	// // Create new producer service
+	// producerService := produce.NewService(mockBroker, keyValueStore)
+	// // Create new convert query service
+	// convertQueryService := convertquery.NewService()
+	// // Create new request sender service
+	// requestSenderService := request.NewService()
+	// // Create new service
+	// service := NewService(mockBroker, producerService, convertQueryService, requestSenderService)
+}
+
+func TestHandleCorrectMessage(t *testing.T) {
+	// Create broker adapter
+	brokerAdapter := brokeradapter.CreateGateway()
+	// Create a mock broker
+	mockBroker := mockbrokerdriver.CreateBroker(brokerAdapter)
+	// Create mock key value store
+	keyValueStore := mockkeyvaluedriver.CreateKeyValueStore()
+	// Create new producer service
+	producerService := produce.NewService(mockBroker, keyValueStore)
+	producerService.Start()
+	// Create new convert query service
+	convertQueryService := mockconvertquery.NewService()
+	// Create new request sender service
+	requestSenderService := mockrequest.NewService()
+	// Create new service
+	service := NewService(mockBroker, producerService, convertQueryService, requestSenderService)
+
+	// Create mock session and mock queue
+	mockSession := "mock-session"
+	mockQueue := "mock-queue"
+
+	// Set the test-session sessionID queue to mock-queue in key value store
+	keyValueStore.Set(&mockSession, &mockQueue)
+
+	// Create headers containing a sessionID
+	headers := make(map[string]interface{})
+	headers["sessionID"] = mockSession
+	mockMessage := brokeradapter.Message{
+		Headers: headers,
+		Body:    []byte("test message"),
+	}
+
+	// Assert that there have not been any messages sent yet
+	assert.Empty(t, mockBroker.Messages)
+
+	// Send the mock message
+	service.HandleMessage(&mockMessage)
+
+	// Assert that there now are two messages that have been sent with routing key mock-queue
+	assert.Len(t, mockBroker.Messages[mockQueue], 2)
+
+	// Assert that the first message is of type 'query_translation_result' and has 'Query converted' as value
+	var translationMessage map[string]interface{}
+	json.Unmarshal(mockBroker.Messages[mockQueue][0].Body, &translationMessage)
+	assert.Equal(t, "query_translation_result", translationMessage["type"])
+	assert.Equal(t, "Query converted", translationMessage["values"])
+
+	// Assert that the second message is of type 'query_result' and contains no values
+	var resultMessage map[string]interface{}
+	json.Unmarshal(mockBroker.Messages[mockQueue][1].Body, &resultMessage)
+	assert.Equal(t, "query_result", resultMessage["type"])
+	assert.Empty(t, resultMessage["values"])
+}
+
+// Unit test message received with no session ID
+func TestHandleMessageNoSessionID(t *testing.T) {
+	// Create broker adapter
+	brokerAdapter := brokeradapter.CreateGateway()
+	// Create a mock broker
+	mockBroker := mockbrokerdriver.CreateBroker(brokerAdapter)
+	// Create mock key value store
+	keyValueStore := mockkeyvaluedriver.CreateKeyValueStore()
+	// Create new producer service
+	producerService := produce.NewService(mockBroker, keyValueStore)
+	// Create new convert query service
+	convertQueryService := mockconvertquery.NewService()
+	// Create new request sender service
+	requestSenderService := mockrequest.NewService()
+	// Create new service
+	service := NewService(mockBroker, producerService, convertQueryService, requestSenderService)
+
+	// Create headers containing a sessionID
+	headers := make(map[string]interface{})
+	mockMessage := brokeradapter.Message{
+		Headers: headers,
+		Body:    []byte("test message"),
+	}
+
+	// Assert that there have not been any messages sent yet
+	assert.Empty(t, mockBroker.Messages)
+
+	// Send the mock message
+	service.HandleMessage(&mockMessage)
+
+	// Assert that there was no message published
+	assert.Empty(t, mockBroker.Messages)
+}
+
+// Unit test receival of message and not being able to parse it
+func TestFailToConvertQuery(t *testing.T) {
+	// Create broker adapter
+	brokerAdapter := brokeradapter.CreateGateway()
+	// Create a mock broker
+	mockBroker := mockbrokerdriver.CreateBroker(brokerAdapter)
+	// Create mock key value store
+	keyValueStore := mockkeyvaluedriver.CreateKeyValueStore()
+	// Create new producer service
+	producerService := produce.NewService(mockBroker, keyValueStore)
+	producerService.Start()
+	// Create new convert query service
+	convertQueryService := mockconvertquery.NewService()
+	// Create new request sender service
+	requestSenderService := mockrequest.NewService()
+	// Create new service
+	service := NewService(mockBroker, producerService, convertQueryService, requestSenderService)
+
+	// Create mock session and mock queue
+	mockSession := "mock-session"
+	mockQueue := "mock-queue"
+
+	// Set the test-session sessionID queue to mock-queue in key value store
+	keyValueStore.Set(&mockSession, &mockQueue)
+
+	// Create headers containing a sessionID
+	headers := make(map[string]interface{})
+	headers["sessionID"] = mockSession
+	mockMessage := brokeradapter.Message{
+		Headers: headers,
+		Body:    []byte("test message"),
+	}
+
+	// Make it so that the conversion service throws an error
+	convertQueryService.ToggleError()
+
+	// Assert that there have not been any messages sent yet
+	assert.Empty(t, mockBroker.Messages)
+
+	// Send the mock message
+	service.HandleMessage(&mockMessage)
+
+	// Assert that there was an error message published
+	var errorMsg map[string]interface{}
+	json.Unmarshal(mockBroker.Messages[mockQueue][0].Body, &errorMsg)
+	assert.Equal(t, "query_translation_error", errorMsg["type"])
+}
+
+// Test AQL querying error handling
+func TestArangoError(t *testing.T) {
+	// Create broker adapter
+	brokerAdapter := brokeradapter.CreateGateway()
+	// Create a mock broker
+	mockBroker := mockbrokerdriver.CreateBroker(brokerAdapter)
+	// Create mock key value store
+	keyValueStore := mockkeyvaluedriver.CreateKeyValueStore()
+	// Create new producer service
+	producerService := produce.NewService(mockBroker, keyValueStore)
+	producerService.Start()
+	// Create new convert query service
+	convertQueryService := mockconvertquery.NewService()
+	// Create new request sender service
+	requestSenderService := mockrequest.NewService()
+	// Create new service
+	service := NewService(mockBroker, producerService, convertQueryService, requestSenderService)
+
+	// Create mock session and mock queue
+	mockSession := "mock-session"
+	mockQueue := "mock-queue"
+
+	// Set the test-session sessionID queue to mock-queue in key value store
+	keyValueStore.Set(&mockSession, &mockQueue)
+
+	// Create headers containing a sessionID
+	headers := make(map[string]interface{})
+	headers["sessionID"] = mockSession
+	mockMessage := brokeradapter.Message{
+		Headers: headers,
+		Body:    []byte("test message"),
+	}
+
+	// Make it so that the request sender service throws an error
+	requestSenderService.ToggleError()
+
+	// Assert that there have not been any messages sent yet
+	assert.Empty(t, mockBroker.Messages)
+
+	// Send the mock message
+	service.HandleMessage(&mockMessage)
+
+	// Assert that there was an error message published
+	var errorMsg map[string]interface{}
+	json.Unmarshal(mockBroker.Messages[mockQueue][1].Body, &errorMsg)
+	assert.Equal(t, "query_database_error", errorMsg["type"])
+}
diff --git a/internal/usecases/consume/handlemessage.go b/internal/usecases/consume/handlemessage.go
index c28a24b539800ad65a12b7738ddf1b66c905c20d..95caff83e553221d2a884c1b7d195b31d97e41ed 100644
--- a/internal/usecases/consume/handlemessage.go
+++ b/internal/usecases/consume/handlemessage.go
@@ -4,7 +4,6 @@ import (
 	"encoding/json"
 	"query-service/internal/adapters/brokeradapter"
 	"query-service/pkg/errorhandler"
-	"query-service/pkg/logger"
 	"strings"
 )
 
@@ -13,13 +12,17 @@ func (s *Service) HandleMessage(msg *brokeradapter.Message) {
 	// Grab sessionID from the headers
 	sessionID, ok := msg.Headers["sessionID"].(string)
 	if !ok {
-		// TODO: Handle error where there is no session ID supplied
+		return
 	}
 
 	// Convert the json byte msg to a query string
 	query, err := s.queryConverter.ConvertQuery(&msg.Body)
 	if err != nil {
-		errorhandler.LogError(err, "failed to parse incoming msg to query language") // TODO: send error message to client instead
+		errorMsg := make(map[string]string)
+		errorMsg["type"] = "query_translation_error"
+		errorMsg["value"] = err.Error()
+		errorMsgBytes, _ := json.Marshal(errorMsg)
+		s.producer.PublishMessage(&errorMsgBytes, &sessionID)
 		return
 	}
 
@@ -44,8 +47,12 @@ func (s *Service) HandleMessage(msg *brokeradapter.Message) {
 	// convert result to general (node-link (?)) format
 	result, err := s.requestSender.SendAQLQuery(*query)
 	if err != nil {
-		logger.Log(err.Error())
-		return // TODO: Send message in queue notifying of error
+		errorMsg := make(map[string]string)
+		errorMsg["type"] = "query_database_error"
+		errorMsg["value"] = err.Error()
+		errorMsgBytes, _ := json.Marshal(errorMsg)
+		s.producer.PublishMessage(&errorMsgBytes, &sessionID)
+		return
 	}
 
 	// Add type indicator to result from database
diff --git a/internal/usecases/consume/mock/consume.go b/internal/usecases/consume/mock/consume.go
new file mode 100644
index 0000000000000000000000000000000000000000..95fb4ff8722a1e85d97a20e8e551b63bdf6b67c1
--- /dev/null
+++ b/internal/usecases/consume/mock/consume.go
@@ -0,0 +1,18 @@
+package mockconsume
+
+// A Service implements the consume usecase interface (mock)
+type Service struct {
+	throwError bool
+}
+
+// NewService creates a new consume service (mock)
+func NewService() *Service {
+	return &Service{
+		throwError: false,
+	}
+}
+
+// Start starts the consume service (mock)
+func (s *Service) Start() {
+
+}
diff --git a/internal/usecases/convertquery/aql.go b/internal/usecases/convertquery/aql.go
index 312a529511e0db8e757b8bd7637982ee48e2a233..f2bf420726fff1085d9f25c16dcb994084a2f7cf 100644
--- a/internal/usecases/convertquery/aql.go
+++ b/internal/usecases/convertquery/aql.go
@@ -2,7 +2,9 @@ package convertquery
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
+	"query-service/internal/entity"
 )
 
 /*
@@ -19,6 +21,34 @@ func (s *Service) ConvertQuery(jsonMsg *[]byte) (*string, error) {
 		return nil, err
 	}
 
+	// Check to make sure all indexes exist
+	// How many entities are there
+	numEntities := len(jsonStruct.Entities) - 1
+	// How many relations there are
+	numRelations := len(jsonStruct.Relations) - 1
+
+	// Make sure no entity should be returned that is outside the range of that list
+	for _, e := range jsonStruct.Return.Entities {
+		// If this entity references an entity that is outside the range
+		if e > numEntities || 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 jsonStruct.Relations {
+		if r.EntityFrom > numEntities || r.EntityTo > numEntities {
+			return nil, errors.New("non-exisiting entity referenced in relation")
+		}
+	}
+
+	// Make sure no non-existing relation is tried to be returned
+	for _, r := range jsonStruct.Return.Relations {
+		if r > numRelations || r < 0 {
+			return nil, errors.New("non-existing relation referenced in return")
+		}
+	}
+
 	result := createQuery(jsonStruct)
 	return result, nil
 }
@@ -28,8 +58,8 @@ Parameters: jsonMsg is the JSON file directly outputted by the drag and drop que
 
 Return: parsedJSON is a struct with the same structure and holding the same data as jsonMsg
 */
-func convertJSONToStruct(jsonMsg *[]byte) (*parsedJSON, error) {
-	jsonStruct := parsedJSON{}
+func convertJSONToStruct(jsonMsg *[]byte) (*entity.QueryParsedJSON, error) {
+	jsonStruct := entity.QueryParsedJSON{}
 	err := json.Unmarshal(*jsonMsg, &jsonStruct)
 
 	if err != nil {
@@ -44,7 +74,7 @@ Parameters: jsonQuery is a parsedJSON struct holding all the data needed to form
 
 Return: a string containing the corresponding AQL query and an error
 */
-func createQuery(jsonQuery *parsedJSON) *string {
+func createQuery(jsonQuery *entity.QueryParsedJSON) *string {
 	// GROTE SIDENOTE:
 	// Vrij zeker dat een query waar alléén edges worden opgevraagd (#4)
 	// niet wordt gesupport door zowel de result parser als de frontend receiver
@@ -62,16 +92,18 @@ func createQuery(jsonQuery *parsedJSON) *string {
 	for i, relation := range jsonQuery.Relations {
 		relationName := fmt.Sprintf("r%v", i)
 
-		if relation.EntityFrom != -1 {
+		if relation.EntityFrom >= 0 {
 			// if there is a from-node
 			// create the let for this node
 			fromName := fmt.Sprintf("n%v", relation.EntityFrom)
+
 			ret += *createNodeLet(&jsonQuery.Entities[relation.EntityFrom], &fromName)
 
 			ret += *createRelationLetWithFromEntity(&relation, relationName, &jsonQuery.Entities, jsonQuery.Limit)
-		} else if relation.EntityTo != -1 {
+		} else if relation.EntityTo >= 0 {
 			// if there is only a to-node
 			toName := fmt.Sprintf("n%v", relation.EntityTo)
+
 			ret += *createNodeLet(&jsonQuery.Entities[relation.EntityTo], &toName)
 
 			ret += *createRelationLetWithOnlyToEntity(&relation, relationName, &jsonQuery.Entities, jsonQuery.Limit)
@@ -135,7 +167,7 @@ name is the autogenerated name of the node consisting of "n" + the index of the
 
 Return: a string containing a single LET-statement in AQL
 */
-func createNodeLet(node *entityStruct, name *string) *string {
+func createNodeLet(node *entity.QueryEntityStruct, name *string) *string {
 	header := fmt.Sprintf("LET %v = (\n\tFOR x IN %v \n", *name, node.Type)
 	footer := "\tRETURN x\n)\n"
 	constraints := *createConstraintStatements(&node.Constraints, "x", false)
@@ -151,7 +183,7 @@ entities is a list of entityStructs that are needed to form the relation LET-sta
 
 Return: a string containing a single LET-statement in AQL
 */
-func createRelationLetWithFromEntity(relation *relationStruct, name string, entities *[]entityStruct, limit int) *string {
+func createRelationLetWithFromEntity(relation *entity.QueryRelationStruct, name string, entities *[]entity.QueryEntityStruct, limit int) *string {
 	header := fmt.Sprintf("LET %v = (\n\tFOR x IN n%v \n", name, relation.EntityFrom)
 	forStatement := fmt.Sprintf("\tFOR v, e, p IN %v..%v OUTBOUND x %s \n", relation.Depth.Min, relation.Depth.Max, relation.Type)
 
@@ -185,7 +217,7 @@ entities is a list of entityStructs that are needed to form the relation LET-sta
 
 Return: a string containing a single LET-statement in AQL
 */
-func createRelationLetWithOnlyToEntity(relation *relationStruct, name string, entities *[]entityStruct, limit int) *string {
+func createRelationLetWithOnlyToEntity(relation *entity.QueryRelationStruct, name string, entities *[]entity.QueryEntityStruct, limit int) *string {
 	header := fmt.Sprintf("LET %v = (\n\tFOR x IN n%v \n", name, relation.EntityTo)
 	forStatement := fmt.Sprintf("\tFOR v, e, p IN %v..%v INBOUND x %s \n", relation.Depth.Min, relation.Depth.Max, relation.Type)
 
diff --git a/internal/usecases/convertquery/aqlStructs.go b/internal/usecases/convertquery/aqlStructs.go
index c9a042430588cc706503a59d8916476ea1ef26aa..ad1be5eeb27d258675af096fa1596c9711470cf5 100644
--- a/internal/usecases/convertquery/aqlStructs.go
+++ b/internal/usecases/convertquery/aqlStructs.go
@@ -8,55 +8,3 @@ type Service struct {
 func NewService() *Service {
 	return &Service{}
 }
-
-// Struct used for JSON conversion of the incoming byte array
-type parsedJSON struct {
-	Return    returnStruct
-	Entities  []entityStruct
-	Relations []relationStruct
-
-	// Limit is for limiting the amount of paths AQL will return in a relation let statement
-	Limit int
-}
-
-// returnStruct holds the indices of the entities and relations that need to be returned
-type returnStruct struct {
-	Entities  []int
-	Relations []int
-}
-
-// entityStruct encapsulates a single entity with its corresponding constraints
-type entityStruct struct {
-	Type        string
-	Constraints []constraintStruct
-}
-
-// relationStruct encapsulates a single relation with its corresponding constraints
-type relationStruct struct {
-	Type        string
-	EntityFrom  int
-	EntityTo    int
-	Depth       searchDepthStruct
-	Constraints []constraintStruct
-}
-
-// searchDepthStruct holds the range of traversals for the relation
-type searchDepthStruct struct {
-	Min int
-	Max int
-}
-
-/*
-constraintStruct holds the information of the constraint
-
-Constraint datatypes
-	text     MatchTypes: exact/contains/startswith/endswith
-	number   MatchTypes: GT/LT/EQ
-	bool     MatchTypes: EQ/NEQ
-*/
-type constraintStruct struct {
-	Attribute string
-	Value     string
-	DataType  string
-	MatchType string
-}
diff --git a/internal/usecases/convertquery/aql_test.go b/internal/usecases/convertquery/aql_test.go
index 8df31686eb7b29a92b403d94ddc894294d19af08..13f2c75bdf7025e4e489e51401d390a9ac959fba 100644
--- a/internal/usecases/convertquery/aql_test.go
+++ b/internal/usecases/convertquery/aql_test.go
@@ -1,249 +1,600 @@
 package convertquery
 
 import (
+	"errors"
+	"strings"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
 )
 
-func TestMock(t *testing.T) {
+func TestEmptyQueryConversion(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
 
-	// s := `{"Return":{"Entities":[0,1],"Relations":[0]},"Entities":[{"Type":"airports","Constraints":[{"Attribute":"country","Value":"USA","DataType":"text","MatchType":"exact"}]},{"Type":"airports","Constraints":[{"Attribute":"city","Value":"New York","DataType":"text","MatchType":"exact"},{"Attribute":"vip","Value":"true","DataType":"bool","MatchType":"exact"}]}],"Relations":[{"Type":"flights","Depth":{"min":1,"max":1},"EntityFrom":0,"EntityTo":1,"Constraints":[{"Attribute":"Month","Value":"1","DataType":"number","MatchType":"exact"},{"Attribute":"Day","Value":"15","DataType":"number","MatchType":"exact"}]}]}`
+	query := []byte(`{
+		"return": {
+			"entities": [],
+			"relations": []
+		},
+		"entities": [],
+		"relations": [],
+		"limit": 5000
+	}`)
 
-	// s3 := []byte(s)
+	convertedResult, err := service.ConvertQuery(&query)
 
-	// // Convert the json byte msg to a query string
-	// convertQueryService := NewService()
-	// query, err := convertQueryService.ConvertQuery(&s3)
-	// if err != nil {
-	// 	errorhandler.LogError(err, "failed to parse incoming msg to query language") // TODO: send error message to client
-	// 	return
-	// }
-	// fmt.Println("Query: " + *query)
+	// Assert that there is no error
+	assert.NoError(t, err)
 
-	// // Make request to database
-	// // TODO : Generate database seperately
-	// // execute and retrieve result
-	// // convert result to general (node-link (?)) format
-	// requestService := request.NewService()
-	// result, err := requestService.SendAQLQuery(*query)
-	// if err != nil {
-	// 	logger.Log(err.Error())
-	// 	return // TODO: Send message in queue notifying of error
-	// }
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `
+LET nodes = first(RETURN UNION_DISTINCT([],[]))
+LET edges = first(RETURN UNION_DISTINCT([],[]))
+RETURN {"vertices":nodes, "edges":edges }`
+	assert.Equal(t, correctConvertedResult, *convertedResult)
+}
+
+func TestEntityOneAttributeQuery(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+		"return": {
+			"entities": [
+				0
+			],
+			"relations": []
+		},
+		"entities": [
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "state",
+						"value": "HI",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			}
+		],
+		"relations": [],
+		"limit": 5000
+	}`)
+
+	convertedResult, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.NoError(t, err)
+
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `LET n0 = (FOR x IN airports FILTER x.state == "HI" RETURN x)LET nodes = first(RETURN UNION_DISTINCT(n0,[],[]))LET edges = first(RETURN UNION_DISTINCT([],[]))RETURN {"vertices":nodes, "edges":edges }`
+	cleanedResult := strings.ReplaceAll(*convertedResult, "\n", "")
+	cleanedResult = strings.ReplaceAll(cleanedResult, "\t", "")
+	assert.Equal(t, correctConvertedResult, cleanedResult)
+}
 
-	// fmt.Print("QueryResult: ")
-	// fmt.Println(*result)
+func TestRelationWithConstraint(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
 
-	assert.True(t, true, true)
+	query := []byte(`{
+		"return": {
+			"entities": [
+				0
+			],
+			"relations": [
+				0
+			]
+		},
+		"entities": [
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "state",
+						"value": "HI",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			}
+		],
+		"relations": [
+			{
+				"type": "flights",
+				"depth": {
+					"min": 1,
+					"max": 1
+				},
+				"entityFrom": 0,
+				"entityTo": -1,
+				"constraints": [
+					{
+						"attribute": "Day",
+						"value": "15",
+						"dataType": "number",
+						"matchType": "EQ"
+					}
+				]
+			}
+		],
+		"limit": 5000
+	}`)
+
+	convertedResult, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.NoError(t, err)
+
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `LET n0 = (FOR x IN airports FILTER x.state == "HI" RETURN x)LET r0 = (FOR x IN n0 FOR v, e, p IN 1..1 OUTBOUND x flights OPTIONS { uniqueEdges: "path" }FILTER p.edges[*].Day ALL == 15 LIMIT 5000 RETURN DISTINCT p )LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), [],[]))LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), [],[]))RETURN {"vertices":nodes, "edges":edges }`
+	cleanedResult := strings.ReplaceAll(*convertedResult, "\n", "")
+	cleanedResult = strings.ReplaceAll(cleanedResult, "\t", "")
+	assert.Equal(t, correctConvertedResult, cleanedResult)
 }
 
-// func TestHugeQuery(t *testing.T) {
-
-// 	s := `{
-// 		"Return": {
-// 		  "Entities": [
-// 			0,
-// 			1
-// 		  ],
-// 		  "Relations": [
-// 			0
-// 		  ]
-// 		},
-// 		"Entities": [
-// 		  {
-// 			"Type": "airports",
-// 			"Constraints": [
-// 			  {
-// 				"Attribute": "country",
-// 				"Value": "USA",
-// 				"DataType": "text",
-// 				"MatchType": "exact"
-// 			  }
-// 			]
-// 		  },
-// 		  {
-// 			"Type": "airports",
-// 			"Constraints": [
-// 			  {
-// 				"Attribute": "city",
-// 				"Value": "New York",
-// 				"DataType": "text",
-// 				"MatchType": "exact"
-// 			  },
-// 			  {
-// 				"Attribute": "vip",
-// 				"Value": "true",
-// 				"DataType": "bool",
-// 				"MatchType": "exact"
-// 			  }
-// 			]
-// 		  }
-// 		],
-// 		"Relations": [
-// 		  {
-// 			"Type": "flights",
-// 			"Depth": {
-// 			  "min": 1,
-// 			  "max": 1
-// 			},
-// 			"EntityFrom": 0,
-// 			"EntityTo": 1,
-// 			"Constraints": [
-// 			  {
-// 				"Attribute": "Month",
-// 				"Value": "1",
-// 				"DataType": "number",
-// 				"MatchType": "exact"
-// 			  },
-// 			  {
-// 				"Attribute": "Day",
-// 				"Value": "15",
-// 				"DataType": "number",
-// 				"MatchType": "exact"
-// 			  }
-// 			]
-// 		  }
-// 		]
-// 	  }`
-
-// 	s3 := []byte(s)
-// 	convertQueryService := NewService()
-// 	j, _ := convertQueryService.ConvertQuery(&s3)
-
-// 	expected := `LET n0 = (
-// 		FOR x IN airports
-// 		FILTER x.country == "USA"
-// 		RETURN x
-// 	)
-// 	LET r0 = (
-// 		FOR x IN n0
-// 		FOR v, e, p IN 1..1 OUTBOUND x flights
-// 		OPTIONS { uniqueEdges: "path" }
-// 		FILTER v.city == "New York"
-// 		AND v.vip == true
-// 		FILTER p.edges[*].Month ALL == 1
-// 		AND p.edges[*].Day ALL == 15
-// 		LIMIT 1000
-// 	RETURN DISTINCT p )
-
-// 	LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), [],[]))
-// 	LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), [],[]))
-// 	RETURN {"vertices":nodes, "edges":edges }`
-
-// 	assert.Equal(t, *j, expected)
-// }
-// func TestOnlyEntitiesQuery(t *testing.T) {
-
-// 	s := `{
-// 		"Return": {
-// 		  "Entities": [
-// 			0
-// 		  ],
-// 		  "Relations": []
-// 		},
-// 		"Entities": [
-// 		  {
-// 			"Type": "airports",
-// 			"Constraints": [
-// 			  {
-// 				"Attribute": "city",
-// 				"Value": "New York",
-// 				"DataType": "text",
-// 				"MatchType": "exact"
-// 			  },
-// 			  {
-// 				"Attribute": "country",
-// 				"Value": "USA",
-// 				"DataType": "text",
-// 				"MatchType": "exact"
-// 			  }
-// 			]
-// 		  }
-// 		],
-// 		"Relations": []
-// 	  }`
-
-// 	s3 := []byte(s)
-// 	convertQueryService := NewService()
-// 	j, _ := convertQueryService.ConvertQuery(&s3)
-
-// 	expected := `LET n0 = (
-// 		FOR x IN airports
-// 		FILTER x.city == "New York"
-// 		AND x.country == "USA"
-// 		RETURN x
-// 	)
-
-// 	LET nodes = first(RETURN UNION_DISTINCT(n0,[],[]))
-// 	LET edges = first(RETURN UNION_DISTINCT([],[]))
-// 	RETURN {"vertices":nodes, "edges":edges }`
-
-// 	assert.Equal(t, expected, *j)
-// }
-// func TestInboundQuery(t *testing.T) {
-
-// 	s := `{
-// 		"Return": {
-// 		  "Entities": [
-// 			0
-// 		  ],
-// 		  "Relations": [
-// 			0
-// 		  ]
-// 		},
-// 		"Entities": [
-// 		  {
-// 			"Type": "airports",
-// 			"Constraints": [
-// 					{
-// 						"Attribute": "city",
-// 						"Value": "New York",
-// 						"DataType": "text",
-// 						"MatchType": "exact"
-// 					}
-// 				]
-// 		  }
-// 		],
-// 		"Relations": [
-// 		  {
-// 			"Type": "flights",
-// 			"Depth": {
-// 			  "min": 1,
-// 			  "max": 1
-// 			},
-// 			"EntityFrom": -1,
-// 			"EntityTo": 0,
-// 			"Constraints": [{
-// 				"Attribute": "Day",
-// 				"Value": "15",
-// 				"DataType": "number",
-// 				"MatchType": "exact"
-// 			  }]
-// 		  }
-// 		]
-// 	  }`
-
-// 	s3 := []byte(s)
-// 	convertQueryService := NewService()
-// 	j, _ := convertQueryService.ConvertQuery(&s3)
-
-// 	expected := `LET n0 = (
-// 		FOR x IN airports
-// 		FILTER x.city == "New York"
-// 		RETURN x
-// 	)
-// 	LET r0 = (
-// 		FOR x IN n0
-// 		FOR v, e, p IN 1..1 INBOUND x flights
-// 		OPTIONS { uniqueEdges: "path" }
-// 		FILTER p.edges[*].Day ALL == 15
-// 		LIMIT 1000
-// 	RETURN DISTINCT p )
-
-// 	LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), [],[]))
-// 	LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), [],[]))
-// 	RETURN {"vertices":nodes, "edges":edges }`
-
-// 	assert.Equal(t, expected, *j)
-// }
+func TestRelationWithInOutConstraint(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+		"return": {
+			"entities": [
+				0,
+				1
+			],
+			"relations": [
+				0
+			]
+		},
+		"entities": [
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "city",
+						"value": "San Francisco",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			},
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "state",
+						"value": "HI",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			}
+		],
+		"relations": [
+			{
+				"type": "flights",
+				"depth": {
+					"min": 1,
+					"max": 3
+				},
+				"entityFrom": 1,
+				"entityTo": 0,
+				"constraints": [
+					{
+						"attribute": "Day",
+						"value": "15",
+						"dataType": "number",
+						"matchType": "EQ"
+					}
+				]
+			}
+		],
+		"limit": 5000
+	}`)
+
+	convertedResult, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.NoError(t, err)
+
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `LET n1 = (FOR x IN airports FILTER x.state == "HI" RETURN x)LET r0 = (FOR x IN n1 FOR v, e, p IN 1..3 OUTBOUND x flights OPTIONS { uniqueEdges: "path" }FILTER v.city == "San Francisco" FILTER p.edges[*].Day ALL == 15 LIMIT 5000 RETURN DISTINCT p )LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), [],[]))LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), [],[]))RETURN {"vertices":nodes, "edges":edges }`
+	cleanedResult := strings.ReplaceAll(*convertedResult, "\n", "")
+	cleanedResult = strings.ReplaceAll(cleanedResult, "\t", "")
+	assert.Equal(t, correctConvertedResult, cleanedResult)
+}
+
+func TestTwoRelations(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+		"return": {
+			"entities": [
+				0,
+				1,
+				2
+			],
+			"relations": [
+				0,
+				1
+			]
+		},
+		"entities": [
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "city",
+						"value": "New York",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			},
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "city",
+						"value": "San Francisco",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			},
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "state",
+						"value": "HI",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			}
+		],
+		"relations": [
+			{
+				"type": "flights",
+				"depth": {
+					"min": 1,
+					"max": 3
+				},
+				"entityFrom": 2,
+				"entityTo": 1,
+				"constraints": [
+					{
+						"attribute": "Day",
+						"value": "15",
+						"dataType": "number",
+						"matchType": "EQ"
+					}
+				]
+			},
+			{
+				"type": "flights",
+				"depth": {
+					"min": 1,
+					"max": 1
+				},
+				"entityFrom": 0,
+				"entityTo": -1,
+				"constraints": []
+			}
+		],
+		"limit": 5000
+	}`)
+
+	convertedResult, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.NoError(t, err)
+
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `LET n2 = (FOR x IN airports FILTER x.state == "HI" RETURN x)LET r0 = (FOR x IN n2 FOR v, e, p IN 1..3 OUTBOUND x flights OPTIONS { uniqueEdges: "path" }FILTER v.city == "San Francisco" FILTER p.edges[*].Day ALL == 15 LIMIT 5000 RETURN DISTINCT p )LET n0 = (FOR x IN airports FILTER x.city == "New York" RETURN x)LET r1 = (FOR x IN n0 FOR v, e, p IN 1..1 OUTBOUND x flights OPTIONS { uniqueEdges: "path" }LIMIT 5000 RETURN DISTINCT p )LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), flatten(r1[**].vertices), [],[]))LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), flatten(r1[**].edges), [],[]))RETURN {"vertices":nodes, "edges":edges }`
+	cleanedResult := strings.ReplaceAll(*convertedResult, "\n", "")
+	cleanedResult = strings.ReplaceAll(cleanedResult, "\t", "")
+	assert.Equal(t, correctConvertedResult, cleanedResult)
+}
+
+func TestRelationWithOnlyToNode(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+			"return": {
+				"entities": [
+					0
+				],
+				"relations": [
+					0
+				]
+			},
+			"entities": [
+				{
+					"type": "airports",
+					"constraints": [
+						{
+							"attribute": "city",
+							"value": "San Francisco",
+							"dataType": "text",
+							"matchType": "exact"
+						}
+					]
+				}
+			],
+			"relations": [
+				{
+					"type": "flights",
+					"depth": {
+						"min": 1,
+						"max": 1
+					},
+					"entityFrom": -1,
+					"entityTo": 0,
+					"constraints": []
+				}
+			],
+			"limit": 5000
+		}`)
+
+	convertedResult, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.NoError(t, err)
+
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `LET n0 = (FOR x IN airports FILTER x.city == "San Francisco" RETURN x)LET r0 = (FOR x IN n0 FOR v, e, p IN 1..1 INBOUND x flights OPTIONS { uniqueEdges: "path" }LIMIT 5000 RETURN DISTINCT p )LET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), [],[]))LET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), [],[]))RETURN {"vertices":nodes, "edges":edges }`
+	cleanedResult := strings.ReplaceAll(*convertedResult, "\n", "")
+	cleanedResult = strings.ReplaceAll(cleanedResult, "\t", "")
+	assert.Equal(t, correctConvertedResult, cleanedResult)
+}
+
+func TestTooManyReturnEntities(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+			"return": {
+				"entities": [
+					0,
+					1,
+					2
+				],
+				"relations": [
+					0
+				]
+			},
+			"entities": [
+				{
+					"type": "airports",
+					"constraints": [
+						{
+							"attribute": "city",
+							"value": "San Francisco",
+							"dataType": "text",
+							"matchType": "exact"
+						}
+					]
+				}
+			],
+			"relations": [
+				{
+					"type": "flights",
+					"depth": {
+						"min": 1,
+						"max": 1
+					},
+					"entityFrom": -1,
+					"entityTo": 0,
+					"constraints": []
+				}
+			],
+			"limit": 5000
+		}`)
+
+	_, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.Equal(t, errors.New("non-existing entity referenced in return"), err)
+}
+
+func TestTooManyReturnRelations(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+			"return": {
+				"entities": [
+					0
+				],
+				"relations": [
+					0,
+					1,
+					2
+				]
+			},
+			"entities": [
+				{
+					"type": "airports",
+					"constraints": [
+						{
+							"attribute": "city",
+							"value": "San Francisco",
+							"dataType": "text",
+							"matchType": "exact"
+						}
+					]
+				}
+			],
+			"relations": [
+				{
+					"type": "flights",
+					"depth": {
+						"min": 1,
+						"max": 1
+					},
+					"entityFrom": -1,
+					"entityTo": 0,
+					"constraints": []
+				}
+			],
+			"limit": 5000
+		}`)
+
+	_, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.Equal(t, errors.New("non-existing relation referenced in return"), err)
+}
+
+func TestNegativeReturnEntities(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+			"return": {
+				"entities": [
+					0,
+					-1
+				],
+				"relations": [
+					0,
+					1,
+					2
+				]
+			},
+			"entities": [
+				{
+					"type": "airports",
+					"constraints": [
+						{
+							"attribute": "city",
+							"value": "San Francisco",
+							"dataType": "text",
+							"matchType": "exact"
+						}
+					]
+				}
+			],
+			"relations": [
+				{
+					"type": "flights",
+					"depth": {
+						"min": 1,
+						"max": 1
+					},
+					"entityFrom": -1,
+					"entityTo": 0,
+					"constraints": []
+				}
+			],
+			"limit": 5000
+		}`)
+
+	_, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.Equal(t, errors.New("non-existing entity referenced in return"), err)
+}
+
+func TestNoRelationsField(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+			"return": {
+				"entities": [
+					0
+				]
+			},
+			"entities": [
+				{
+					"type": "airports",
+					"constraints": [
+						{
+							"attribute": "city",
+							"value": "San Francisco",
+							"dataType": "text",
+							"matchType": "exact"
+						}
+					]
+				}
+			],
+			"limit": 5000
+		}`)
+
+	convertedResult, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.NoError(t, err)
+
+	// Assert that the result and the expected result are the same
+	correctConvertedResult := `LET n0 = (FOR x IN airports FILTER x.city == "San Francisco" RETURN x)LET nodes = first(RETURN UNION_DISTINCT(n0,[],[]))LET edges = first(RETURN UNION_DISTINCT([],[]))RETURN {"vertices":nodes, "edges":edges }`
+	cleanedResult := strings.ReplaceAll(*convertedResult, "\n", "")
+	cleanedResult = strings.ReplaceAll(cleanedResult, "\t", "")
+	assert.Equal(t, correctConvertedResult, cleanedResult)
+}
+
+func TestEntityFromLowerThanNegativeOneInRelation(t *testing.T) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+			"return": {
+				"entities": [
+					0
+				],
+				"relations": [
+					0
+				]
+			},
+			"entities": [
+				{
+					"type": "airports",
+					"constraints": [
+						{
+							"attribute": "city",
+							"value": "San Francisco",
+							"dataType": "text",
+							"matchType": "exact"
+						}
+					]
+				}
+			],
+			"relations": [
+				{
+					"type": "flights",
+					"depth": {
+						"min": 1,
+						"max": 1
+					},
+					"entityFrom": -4,
+					"entityTo": 0,
+					"constraints": []
+				}
+			],
+			"limit": 5000
+		}`)
+
+	_, err := service.ConvertQuery(&query)
+
+	// Assert that there is no error
+	assert.NoError(t, err)
+}
diff --git a/internal/usecases/convertquery/benchmark_test.go b/internal/usecases/convertquery/benchmark_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..86da73b02be46cef4d15b4f7ec7bd5d75ac74de0
--- /dev/null
+++ b/internal/usecases/convertquery/benchmark_test.go
@@ -0,0 +1,152 @@
+package convertquery
+
+import "testing"
+
+func BenchmarkConvertEmptyQuery(b *testing.B) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+		"return": {
+			"entities": [],
+			"relations": []
+		},
+		"entities": [],
+		"relations": [],
+		"limit": 5000
+	}`)
+
+	b.ResetTimer()
+
+	for i := 0; i < b.N; i++ {
+		service.ConvertQuery(&query)
+	}
+}
+
+func BenchmarkConvertOneAttributeQuery(b *testing.B) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+		"return": {
+			"entities": [
+				0
+			],
+			"relations": []
+		},
+		"entities": [
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "state",
+						"value": "HI",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			}
+		],
+		"relations": [],
+		"limit": 5000
+	}`)
+
+	b.ResetTimer()
+
+	for i := 0; i < b.N; i++ {
+		service.ConvertQuery(&query)
+	}
+}
+
+func BenchmarkConvertTwoRelationQuery(b *testing.B) {
+	// Setup for test
+	// Create query conversion service
+	service := NewService()
+
+	query := []byte(`{
+		"return": {
+			"entities": [
+				0,
+				1,
+				2
+			],
+			"relations": [
+				0,
+				1
+			]
+		},
+		"entities": [
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "city",
+						"value": "New York",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			},
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "city",
+						"value": "San Francisco",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			},
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "state",
+						"value": "HI",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			}
+		],
+		"relations": [
+			{
+				"type": "flights",
+				"depth": {
+					"min": 1,
+					"max": 3
+				},
+				"entityFrom": 2,
+				"entityTo": 1,
+				"constraints": [
+					{
+						"attribute": "Day",
+						"value": "15",
+						"dataType": "number",
+						"matchType": "EQ"
+					}
+				]
+			},
+			{
+				"type": "flights",
+				"depth": {
+					"min": 1,
+					"max": 1
+				},
+				"entityFrom": 0,
+				"entityTo": -1,
+				"constraints": []
+			}
+		],
+		"limit": 5000
+	}`)
+
+	b.ResetTimer()
+
+	for i := 0; i < b.N; i++ {
+		service.ConvertQuery(&query)
+	}
+}
diff --git a/internal/usecases/convertquery/createConstraints.go b/internal/usecases/convertquery/createConstraints.go
index 2f92a5cb8adf20a9648c27d6404f7eb219a8b80a..b03d06f79342d39122612dd076eeedf5afe37f8b 100644
--- a/internal/usecases/convertquery/createConstraints.go
+++ b/internal/usecases/convertquery/createConstraints.go
@@ -1,6 +1,9 @@
 package convertquery
 
-import "fmt"
+import (
+	"fmt"
+	"query-service/internal/entity"
+)
 
 /* createConstraintStatements generates the appropriate amount of constraint lines calling createConstraingBoolExpression
 Parameters: constraints is a list of constraintStructs that specify the constraints of a node or relation,
@@ -9,7 +12,7 @@ isRelation is a boolean specifying if this constraint comes from a node or relat
 
 Return: a string containing a FILTER-statement with all the constraints
 */
-func createConstraintStatements(constraints *[]constraintStruct, name string, isRelation bool) *string {
+func createConstraintStatements(constraints *[]entity.QueryConstraintStruct, name string, isRelation bool) *string {
 	s := ""
 	if len(*constraints) == 0 {
 		return &s
@@ -34,7 +37,7 @@ isRelation is a boolean specifying if this constraint comes from a node or relat
 
 Return: a string containing an boolean expression of a single constraint
 */
-func createConstraintBoolExpression(constraint *constraintStruct, name string, isRelation bool) *string {
+func createConstraintBoolExpression(constraint *entity.QueryConstraintStruct, name string, isRelation bool) *string {
 	var (
 		match string
 		value string
diff --git a/internal/usecases/convertquery/mock/mockconvertquery.go b/internal/usecases/convertquery/mock/mockconvertquery.go
new file mode 100644
index 0000000000000000000000000000000000000000..f30767469f7a592d114bca3bebe69b32d61c8ebc
--- /dev/null
+++ b/internal/usecases/convertquery/mock/mockconvertquery.go
@@ -0,0 +1,30 @@
+package mockconvertquery
+
+import "errors"
+
+// A Service implements the query convert usecase interface (mock)
+type Service struct {
+	throwError bool
+}
+
+// NewService creates a new query convert service (mock)
+func NewService() *Service {
+	return &Service{
+		throwError: false,
+	}
+}
+
+// ConvertQuery returns a hard coded string message (mock)
+func (s *Service) ConvertQuery(jsonMsg *[]byte) (*string, error) {
+	mockQuery := "Query converted"
+
+	if !s.throwError {
+		return &mockQuery, nil
+	}
+	return nil, errors.New("Failed to convert query")
+}
+
+// ToggleError decides whether the convert function throws an error
+func (s *Service) ToggleError() {
+	s.throwError = !s.throwError
+}
diff --git a/internal/usecases/produce/produce.go b/internal/usecases/produce/produce.go
index 2bb3ef3efc0ed939ddbdf7d82137c21b3e27c84f..85bff2a1c15774a55a05982025aaeb4bc907f508 100644
--- a/internal/usecases/produce/produce.go
+++ b/internal/usecases/produce/produce.go
@@ -1,22 +1,19 @@
 package produce
 
 import (
-	"log"
 	"query-service/internal/drivers/brokerdriver"
 	"query-service/internal/drivers/keyvaluedriver"
-
-	"github.com/streadway/amqp"
 )
 
 // Service wraps consumer methods
 type Service struct {
 	brokerDriver   brokerdriver.Broker
-	keyValueStore  keyvaluedriver.KeyValueStore
+	keyValueStore  keyvaluedriver.KeyValueStoreInterface
 	producerDriver brokerdriver.Producer
 }
 
 // NewService creates a new service
-func NewService(broker brokerdriver.Broker, keyValueStore keyvaluedriver.KeyValueStore) *Service {
+func NewService(broker brokerdriver.Broker, keyValueStore keyvaluedriver.KeyValueStoreInterface) *Service {
 	return &Service{
 		brokerDriver:  broker,
 		keyValueStore: keyValueStore,
@@ -29,19 +26,4 @@ func (s *Service) Start() {
 	p := s.brokerDriver.CreateProducer()
 
 	s.producerDriver = p
-
-	// // Start consuming messages
-	// p.ConsumeMessages()
-}
-
-// PublishMessage will publish the message to the queue retrieved from the key value store, with the given sessionID
-func (s *Service) PublishMessage(data *[]byte, sessionID *string) {
-	clientUpdaterID := s.keyValueStore.Get(sessionID)
-
-	log.Println(string(*data))
-
-	headers := amqp.Table{}
-	headers["sessionID"] = *sessionID
-	headers["type"] = "queryResult"
-	s.producerDriver.PublishMessage(data, clientUpdaterID, &headers)
 }
diff --git a/internal/usecases/produce/produce_test.go b/internal/usecases/produce/produce_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..ff3f5fefde093ed8b0ba1c39be4c28444ac3b1ae
--- /dev/null
+++ b/internal/usecases/produce/produce_test.go
@@ -0,0 +1,77 @@
+package produce
+
+import (
+	"query-service/internal/adapters/brokeradapter"
+	mockbrokerdriver "query-service/internal/drivers/brokerdriver/mock"
+	mockkeyvaluedriver "query-service/internal/drivers/keyvaluedriver/mock"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+// Make sure a correct message gets published
+func TestPublishCorrectMessage(t *testing.T) {
+	// Create broker adapter
+	brokerAdapter := brokeradapter.CreateGateway()
+	// Create a mock broker
+	mockBroker := mockbrokerdriver.CreateBroker(brokerAdapter)
+	// Create mock key value store
+	keyValueStore := mockkeyvaluedriver.CreateKeyValueStore()
+	// Create new service and start it
+	service := NewService(mockBroker, keyValueStore)
+	service.Start()
+
+	// Create mock session and mock queue
+	mockSession := "mock-session"
+	mockQueue := "mock-queue"
+
+	// Set the test-session sessionID queue to mock-queue in key value store
+	keyValueStore.Set(&mockSession, &mockQueue)
+
+	// Create headers containing a sessionID
+	headers := make(map[string]interface{})
+	headers["sessionID"] = mockSession
+
+	// Assert that there have not been any messages sent yet
+	assert.Empty(t, mockBroker.Messages)
+
+	// Publish the message
+	mockMessage := []byte("Test message")
+	service.PublishMessage(&mockMessage, &mockSession)
+
+	// Assert that there is now 1 message
+	assert.Len(t, mockBroker.Messages[mockQueue], 1)
+
+	// Assert that this message contains the mockMessage
+	assert.Equal(t, mockBroker.Messages[mockQueue][0].Body, mockMessage)
+}
+
+// Test publishing message without setting routing in key value store
+func TestPublishMessageNoRouting(t *testing.T) {
+	// Create broker adapter
+	brokerAdapter := brokeradapter.CreateGateway()
+	// Create a mock broker
+	mockBroker := mockbrokerdriver.CreateBroker(brokerAdapter)
+	// Create mock key value store
+	keyValueStore := mockkeyvaluedriver.CreateKeyValueStore()
+	// Create new service and start it
+	service := NewService(mockBroker, keyValueStore)
+	service.Start()
+
+	// Create mock session and mock queue
+	mockSession := "mock-session"
+
+	// Create headers containing a sessionID
+	headers := make(map[string]interface{})
+	headers["sessionID"] = mockSession
+
+	// Assert that there have not been any messages sent yet
+	assert.Empty(t, mockBroker.Messages)
+
+	// Publish the message
+	mockMessage := []byte("Test message")
+	service.PublishMessage(&mockMessage, &mockSession)
+
+	// Assert that there are still 0 messages
+	assert.Empty(t, mockBroker.Messages)
+}
diff --git a/internal/usecases/produce/publishmessage.go b/internal/usecases/produce/publishmessage.go
new file mode 100644
index 0000000000000000000000000000000000000000..8e9b31e8cef943c1f75df320bce91b1c531a5a98
--- /dev/null
+++ b/internal/usecases/produce/publishmessage.go
@@ -0,0 +1,22 @@
+package produce
+
+import (
+	"github.com/streadway/amqp"
+)
+
+// PublishMessage will publish the message to the queue retrieved from the key value store, with the given sessionID
+func (s *Service) PublishMessage(data *[]byte, sessionID *string) {
+	// Use the sessionID to query the key value store to get the queue we need to send this message to
+	clientQueueID := s.keyValueStore.Get(sessionID)
+
+	// If this client has now disconnected
+	if clientQueueID == "" {
+		// TODO: Decide whether to throw away the message or perhaps cache it, for now throw it away
+		return
+	}
+
+	headers := amqp.Table{}
+	headers["sessionID"] = *sessionID
+	headers["type"] = "queryResult"
+	s.producerDriver.PublishMessage(data, &clientQueueID, &headers)
+}
diff --git a/internal/usecases/request/interface.go b/internal/usecases/request/interface.go
index 7a30fb2ece5001330752ae924eabad893fc37f2a..c54ca39d920bbcdc71452d14138e2603ed86a12b 100644
--- a/internal/usecases/request/interface.go
+++ b/internal/usecases/request/interface.go
@@ -1,6 +1,8 @@
 package request
 
+import "query-service/internal/entity"
+
 // UseCase is an interface describing the request usecases
 type UseCase interface {
-	SendAQLQuery(query string) (*map[string][]Document, error)
+	SendAQLQuery(query string) (*map[string][]entity.Document, error)
 }
diff --git a/internal/usecases/request/mock/mockrequest.go b/internal/usecases/request/mock/mockrequest.go
new file mode 100644
index 0000000000000000000000000000000000000000..758a0eaa4b83ba433efc97c472b64b911feda519
--- /dev/null
+++ b/internal/usecases/request/mock/mockrequest.go
@@ -0,0 +1,33 @@
+package mockrequest
+
+import (
+	"errors"
+	"query-service/internal/entity"
+)
+
+// A Service implements the request usecases (mock)
+type Service struct {
+	throwError bool
+}
+
+// NewService creates a new service (mock)
+func NewService() *Service {
+	return &Service{
+		throwError: false,
+	}
+}
+
+// SendAQLQuery sends the query to arangoDB and parses the result (mock)
+func (s *Service) SendAQLQuery(query string) (*map[string][]entity.Document, error) {
+	mockResult := make(map[string][]entity.Document)
+
+	if !s.throwError {
+		return &mockResult, nil
+	}
+	return nil, errors.New("Database error")
+}
+
+// ToggleError decides whether the convert function throws an error
+func (s *Service) ToggleError() {
+	s.throwError = !s.throwError
+}
diff --git a/internal/usecases/request/request.go b/internal/usecases/request/request.go
index 083150bda2981ddc309509d50ca2a143e50c0ee5..bfcf2b4368897c94d64035a0cb12eb97422ef92c 100644
--- a/internal/usecases/request/request.go
+++ b/internal/usecases/request/request.go
@@ -5,6 +5,7 @@ import (
 	"crypto/tls"
 	"log"
 	"os"
+	"query-service/internal/entity"
 
 	"encoding/json"
 	"io/ioutil"
@@ -25,10 +26,10 @@ Parameters: AQLQuery is a string containing the query that will be send to the d
 Return: a map with two entries: "nodes" with a list of vertices/nodes and "edges" with a list of edges
 that will be returned to the frontend
 */
-func (s *Service) SendAQLQuery(AQLQuery string) (*map[string][]Document, error) {
+func (s *Service) SendAQLQuery(AQLQuery string) (*map[string][]entity.Document, error) {
 	// Get ArangoDB url from environment variable
 	arangoURL := os.Getenv("ARANGO_HOST")
-	var queryResult = make(map[string][]Document)
+	var queryResult = make(map[string][]entity.Document)
 	conn, err := http.NewConnection(http.ConnectionConfig{
 		Endpoints: []string{arangoURL},
 		TLSConfig: &tls.Config{InsecureSkipVerify: true},
@@ -62,7 +63,7 @@ func (s *Service) SendAQLQuery(AQLQuery string) (*map[string][]Document, error)
 	defer cursor.Close()
 
 	//Loop through the resulting documents
-	listContainer := ListContainer{}
+	listContainer := entity.ListContainer{}
 	for {
 		var doc map[string][]interface{}
 		_, err := cursor.ReadDocument(ctx, &doc)
@@ -76,8 +77,8 @@ func (s *Service) SendAQLQuery(AQLQuery string) (*map[string][]Document, error)
 		parseResult(doc, &listContainer)
 	}
 
-	queryResult["nodes"] = listContainer.nodeList
-	queryResult["edges"] = listContainer.edgeList
+	queryResult["nodes"] = listContainer.NodeList
+	queryResult["edges"] = listContainer.EdgeList
 
 	//writeJSON(queryResult)
 	//file, err := json.MarshalIndent(queryResult, "", " ")
@@ -91,20 +92,20 @@ listContainer is a struct containing the nodelist and edgelist that will be retu
 
 Return: Nothing because the result is stored in the listContainer
 */
-func parseResult(doc map[string][]interface{}, listContainer *ListContainer) {
+func parseResult(doc map[string][]interface{}, listContainer *entity.ListContainer) {
 	vertices := doc["vertices"]
 	edges := doc["edges"]
 
 	for _, vertex := range vertices {
 		vertexDoc := vertex.(map[string]interface{})
 
-		(*listContainer).nodeList = append((*listContainer).nodeList, parseNode(vertexDoc))
+		(*listContainer).NodeList = append((*listContainer).NodeList, parseNode(vertexDoc))
 	}
 
 	for _, edge := range edges {
 		edgeDoc := edge.(map[string]interface{})
 
-		(*listContainer).edgeList = append((*listContainer).edgeList, parseEdge(edgeDoc))
+		(*listContainer).EdgeList = append((*listContainer).EdgeList, parseEdge(edgeDoc))
 	}
 }
 
@@ -113,10 +114,10 @@ Parameters: d is a single entry of an edge
 
 Return: a document with almost the same structure as before, but the attributes are grouped
 */
-func parseEdge(d map[string]interface{}) Document {
+func parseEdge(d map[string]interface{}) entity.Document {
 	doc := d //.(map[string]interface{})
 
-	data := make(Document)
+	data := make(entity.Document)
 	data["_id"] = doc["_id"]
 	delete(doc, "_id")
 	data["_key"] = doc["_key"]
@@ -138,7 +139,7 @@ func parseEdge(d map[string]interface{}) Document {
 }
 
 // writeJSON writes a json file for testing purposes
-func writeJSON(queryResult map[string][]Document) {
+func writeJSON(queryResult map[string][]entity.Document) {
 	file, _ := json.MarshalIndent(queryResult, "", " ")
 
 	_ = ioutil.WriteFile("result.json", file, 0644)
@@ -149,10 +150,10 @@ Parameters: d is a single entry of an node
 
 Return: a document with almost the same structure as before, but the attributes are grouped
 */
-func parseNode(d map[string]interface{}) Document {
+func parseNode(d map[string]interface{}) entity.Document {
 	doc := d //.(map[string]interface{})
 
-	data := make(Document)
+	data := make(entity.Document)
 	data["_id"] = doc["_id"]
 	delete(doc, "_id")
 	data["_key"] = doc["_key"]
diff --git a/internal/usecases/request/requestStructs.go b/internal/usecases/request/requestStructs.go
index 2479df8200a8ecefd505e6f300963d21d65be28a..b2a001fccd12cb691af698e826bb555d68f2b660 100644
--- a/internal/usecases/request/requestStructs.go
+++ b/internal/usecases/request/requestStructs.go
@@ -8,15 +8,3 @@ type Service struct {
 func NewService() *Service {
 	return &Service{}
 }
-
-// Document with Empty struct to retrieve all data from the DB Document
-type Document map[string]interface{}
-
-// GeneralFormat with Empty struct to retrieve all data from the DB Document
-type GeneralFormat map[string][]Document
-
-// ListContainer is a struct that keeps track of the nodes and edges that need to be returned
-type ListContainer struct {
-	nodeList []Document
-	edgeList []Document
-}