-
Lelieveld,J.R.J. (Joris) authoredLelieveld,J.R.J. (Joris) authored
request.go 5.72 KiB
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
}