Newer
Older
import (
"context"
"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
// NewService creates a new instantion of this use case
// 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{
TLSConfig: &tls.Config{InsecureSkipVerify: true},
})
if err != nil {
log.Println("could not connect to database") // Handle error
}
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
}
ctx := context.Background()
db, err := c.Database(ctx, "_system")
if err != nil {
// handle error
//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{}
var doc map[string][]interface{}
_, err := cursor.ReadDocument(ctx, &doc)
if driver.IsNoMoreDocuments(err) {
break
} else if err != nil {
// handle other errors
//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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// 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")
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
// 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
}