package request import ( "context" "crypto/tls" "fmt" "log" "encoding/json" "io/ioutil" driver "github.com/arangodb/go-driver" "github.com/arangodb/go-driver/http" ) // Service is a struct used to store this use case in type Service struct { } // NewService creates a new instantion of this use case 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 } //attr interface{} //map[1 , 2 , 3 map [ .. ]] // SendAQLQuery send AQL string query to database and returns a JSON object in a general format func (s *Service) SendAQLQuery(AQLQuery string) (*map[string][]Document, error) { var queryResult = make(map[string][]Document) conn, err := http.NewConnection(http.ConnectionConfig{ Endpoints: []string{"https://aae8f5c054da.arangodb.cloud:8529"}, TLSConfig: &tls.Config{InsecureSkipVerify: true}, }) if err != nil { log.Println("could not connect to database") // Handle error return nil, err } c, err := driver.NewClient(driver.ClientConfig{ Connection: conn, Authentication: driver.BasicAuthentication("root", "kXR0PFepIVm3EqgQ2MVc"), }) if err != nil { log.Println("Could not log in to the ArangoDB") // Handle error return nil, err } ctx := context.Background() db, err := c.Database(ctx, "_system") if err != nil { // handle error log.Println(err) return nil, err } // CHANGED TO OTHER FORMAT //fmt.Println(AQLQuery) // query := ` // LET n0 = ( // FOR x IN airports // FILTER x.country == 'USA' // RETURN x // ) // FOR n in n0 // RETURN n // ` cursor, err := db.Query(ctx, AQLQuery, nil) if err != nil { log.Println("Invalid query") // handle error return nil, err } defer cursor.Close() lcontainer := ListContainer{} for { var doc map[string][]interface{} _, err := cursor.ReadDocument(ctx, &doc) if driver.IsNoMoreDocuments(err) { break } else if err != nil { // handle other errors return nil, err } //fmt.Printf("%s\n", doc) //GEDACHTEGANG TIJD: //Normaal een lijst van n0, n1. Nu kan er ook e0 bij zitten, die heeft een andere structuur //Dus nu een returnstruct maken met een nodelist en edgelist //Vervolgens door de keys van de doc (n0 e0 etc) loopen en een verschillende parser aanroepen die de //returnstruct vult. Daarna de returnstruct omzetten tot een nodelist (en maybe edgelist) //ret = parseDocToReturn() { // for key in doc: // if key starts with n: Nodeparsen // if key starts with e: Edgeparsen // return listContainer {nodelist edgelist} //} // //result = parseContainerToString(ret) parseResult(doc, &lcontainer) } queryResult["nodes"] = lcontainer.nodeList queryResult["edges"] = lcontainer.edgeList //writeJSON(queryResult) //file, err := json.MarshalIndent(queryResult, "", " ") return &queryResult, nil } // parseResult takes the result of the query and translates this to two lists: a nodelist and an edgelist, stored in a listcontainer func parseResult(doc map[string][]interface{}, lcontainer *ListContainer) { for k, v := range doc { switch letter := []byte(k)[0]; letter { case 'e': //fmt.Println(v) //Parsing of edges for _, j := range v { //fmt.Println(j) //fmt.Printf("\n%T\n", j) d := j.(map[string]interface{}) //fmt.Printf("\n%T\n", d["vertices"]) vert := d["vertices"].([]interface{}) edg := d["edges"].([]interface{}) lcontainer.nodeList = append(lcontainer.nodeList, parseNode(vert[0])) lcontainer.nodeList = append(lcontainer.nodeList, parseNode(vert[1])) lcontainer.edgeList = append(lcontainer.edgeList, parseEdge(edg[0])) } case 'n': //Parsing of nodes for _, j := range v { //fmt.Printf("\n%T\n", j) doc := j.(map[string]interface{}) lcontainer.nodeList = append(lcontainer.nodeList, parseNode(doc)) } default: //Error fmt.Println("Empty document") } } } // parseEdge parses the data of an edge to an output-friendly format func parseEdge(d interface{}) Document { doc := d.(map[string]interface{}) data := make(Document) data["_id"] = doc["_id"] delete(doc, "_id") data["_key"] = doc["_key"] delete(doc, "_key") data["_rev"] = doc["_rev"] delete(doc, "_rev") data["_from"] = doc["_from"] delete(doc, "_from") data["_to"] = doc["_to"] delete(doc, "_to") data["attributes"] = doc //delete(doc, "_key") //data.rev = fmt.Sprintf("%v", doc["_rev"]) // delete(doc, "_rev") // data.attr = doc return data } // func formatToJSON(doc GeneralFormat) []Document { // //b, err := json.Marshal(doc) // //if err != nil { // //handle error // //} // fmt.Println(doc) // var nodeList []Document // for _, v := range doc { // for _, j := range v { // nodeList = append(nodeList, parseNode(j)) // } // } // // fmt.Println(nodeList) // return nodeList // } // writeJSON writes a json file for testing purposes func writeJSON(queryResult map[string][]Document) { file, _ := json.MarshalIndent(queryResult, "", " ") _ = ioutil.WriteFile("result.json", file, 0644) } // parseNode parses the data of a node to an output-friendly format func parseNode(d interface{}) Document { doc := d.(map[string]interface{}) data := make(Document) data["_id"] = doc["_id"] delete(doc, "_id") data["_key"] = doc["_key"] delete(doc, "_key") data["_rev"] = doc["_rev"] delete(doc, "_rev") data["attributes"] = doc //delete(doc, "_key") //data.rev = fmt.Sprintf("%v", doc["_rev"]) // delete(doc, "_rev") // data.attr = doc return data }