From 12e74013953d36bd017da0248946b2c2e93743ff Mon Sep 17 00:00:00 2001 From: Kieran van Gaalen <kieran.van.gaalen@casema.nl> Date: Tue, 16 Nov 2021 12:09:22 +0100 Subject: [PATCH] Implemented modifiers --- aql/convertQuery.go | 58 ++++++++++++++++++++++++++++++++++++++++--- entity/queryStruct.go | 2 +- main/main.go | 2 +- realtest.json | 10 +++++++- 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/aql/convertQuery.go b/aql/convertQuery.go index 4d57360..9764071 100644 --- a/aql/convertQuery.go +++ b/aql/convertQuery.go @@ -87,6 +87,14 @@ 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, tree []entity.Tree, topNode entity.QueryEntityStruct) *string { + modName := "" + if len(JSONQuery.Modifiers) > 0 { + modifier := JSONQuery.Modifiers[0] + fmt.Println(modifier.SelectedType + ", " + strconv.Itoa(modifier.SelectedTypeID)) + if modifier.SelectedType == "entity" && modifier.SelectedTypeID == topNode.ID { + modName = fmt.Sprintf("e_%v", topNode.ID) + } + } output := createLetFor("result", fmt.Sprintf("e_%v", topNode.ID), topNode.Name, 0) for constraint := range topNode.Constraints { output += createFilter(topNode.Constraints[constraint], fmt.Sprintf("e_%v", topNode.ID)) @@ -95,15 +103,42 @@ func createQuery(JSONQuery *entity.IncomingQueryJSON, tree []entity.Tree, topNod subNames := []string{subName} output += subQuery output += createZeroFilter(append(subNames, fmt.Sprintf("e_%v", topNode.ID))) - output += createReturn(fmt.Sprintf("e_%v", topNode.ID), "", subNames) + output += createReturn(fmt.Sprintf("e_%v", topNode.ID), "", modName, subNames) output += ")\n" - output += "let nodes = union_distinct(flatten(result[**].nodes),[])\nlet edges = union_distinct(flatten(result[**].rel),[])\nreturn {\"vertices\":nodes,\"edges\":edges}" + //output += "LET nodes = union_distinct(flatten(result[**].nodes),[])\nLET edges = union_distinct(flatten(result[**].rel),[])\nLET modif = union_distinct(flatten(result[**].mod),[])\n" + if len(JSONQuery.Modifiers) == 0 { + output += "LET nodes = union_distinct(flatten(result[**].nodes),[])\nLET edges = union_distinct(flatten(result[**].rel),[])\nRETURN {\"vertices\":nodes,\"edges\":edges}" + } else { + output += "LET modif = union_distinct(flatten(result[**].mod),[])\n" + modifier := JSONQuery.Modifiers[0] + if modifier.AttributeIndex == -1 { + output += "RETURN " + getModifierType(modifier) + "(modif)" + } else { + var attribute string + // Selecting the right attribute from either the entity constraint or relation constraint + if modifier.SelectedType == "entity" { + attribute = JSONQuery.Entities[modifier.SelectedTypeID].Constraints[modifier.AttributeIndex].Attribute + } else { + attribute = JSONQuery.Relations[modifier.SelectedTypeID].Constraints[modifier.AttributeIndex].Attribute + } + output += "RETURN " + getModifierType(modifier) + "(modif[**]." + attribute + ")" + } + } return &output } func createQueryRecurse(JSONQuery *entity.IncomingQueryJSON, tree []entity.Tree, currentindex int, topNode entity.QueryEntityStruct, indentindex int) (string, string) { currentTree := tree[currentindex] newNode := getTreeNewNode(currentTree, tree, topNode) + modName := "" + if len(JSONQuery.Modifiers) > 0 { + modifier := JSONQuery.Modifiers[0] + if modifier.SelectedType == "entity" && modifier.SelectedTypeID == newNode.ID { + modName = fmt.Sprintf("e_%v", newNode.ID) + } else if modifier.SelectedType == "relation" && modifier.SelectedTypeID == currentTree.Self.Rel.ID { + modName = fmt.Sprintf("r%v", currentTree.Self.Rel.ID) + } + } output := "" output += fixIndent(createLetFor(fmt.Sprintf("e%v", newNode.ID), fmt.Sprintf("e_%v", newNode.ID), newNode.Name, indentindex), indentindex) output += fixIndent(fmt.Sprintf("\tFOR r%v IN %v\n", currentTree.Self.Rel.ID, currentTree.Self.Rel.Name), indentindex) @@ -121,7 +156,7 @@ func createQueryRecurse(JSONQuery *entity.IncomingQueryJSON, tree []entity.Tree, subNames = append(subNames, subName) } output += fixIndent(createZeroFilter(append(subNames, fmt.Sprintf("e_%v", newNode.ID), fmt.Sprintf("r%v", currentTree.Self.Rel.ID))), indentindex) - output += fixIndent(createReturn(fmt.Sprintf("e_%v", newNode.ID), fmt.Sprintf("r%v", currentTree.Self.Rel.ID), subNames), indentindex) + output += fixIndent(createReturn(fmt.Sprintf("e_%v", newNode.ID), fmt.Sprintf("r%v", currentTree.Self.Rel.ID), modName, subNames), indentindex) output += fixIndent(")\n", indentindex) return output, fmt.Sprintf("e%v", newNode.ID) } @@ -184,7 +219,7 @@ func createZeroFilter(subNames []string) string { return output } -func createReturn(nodeName string, relName string, subNames []string) string { +func createReturn(nodeName string, relName string, modName string, subNames []string) string { output := "\tRETURN {\"nodes\":union_distinct(" for i := range subNames { output += fmt.Sprintf("flatten(%v[**].nodes), ", subNames[i]) @@ -201,6 +236,14 @@ func createReturn(nodeName string, relName string, subNames []string) string { if len(subNames) == 0 { output += ", []" } + output += "), \"mod\": union_distinct(" + for i := range subNames { + output += fmt.Sprintf("flatten(%v[**].mod), ", subNames[i]) + } + output += "[" + modName + "]" + if len(subNames) == 0 { + output += ", []" + } output += ")}\n" return output } @@ -253,3 +296,10 @@ func fixIndent(input string, indentCount int) string { output += input return output } + +func getModifierType(modifier entity.QueryModifierStruct) string { + if modifier.Type == "COUNT" { + return "LENGTH" + } + return modifier.Type +} diff --git a/entity/queryStruct.go b/entity/queryStruct.go index 9cf011e..b74e4f5 100644 --- a/entity/queryStruct.go +++ b/entity/queryStruct.go @@ -75,7 +75,7 @@ type QueryMLStruct struct { // QueryModifierStruct encapsulates a single modifier with its corresponding constraints type QueryModifierStruct struct { Type string // SUM COUNT AVG - SelectedType string // node relation + SelectedType string // entity relation SelectedTypeID int // ID of the enitity or relation AttributeIndex int // = -1 if its the node or relation, = > -1 if an attribute is selected } diff --git a/main/main.go b/main/main.go index 90f0c6e..18a0f92 100644 --- a/main/main.go +++ b/main/main.go @@ -20,7 +20,7 @@ The main function that calls the appropriate functions */ func main() { queryservice := aql.NewService() - jsonFile, err := os.Open("../test.json") + jsonFile, err := os.Open("../realtest.json") // if we os.Open returns an error then handle it if err != nil { log.Println(err) diff --git a/realtest.json b/realtest.json index 5aa9061..b4122c1 100644 --- a/realtest.json +++ b/realtest.json @@ -136,5 +136,13 @@ "constraints": [] } ], - "limit": 5000 + "limit": 5000, + "modifiers": [ + { + "type": "SUM", + "selectedType": "entity", + "selectedTypeID": 3, + "attributeIndex": 0 + } + ] } \ No newline at end of file -- GitLab