diff --git a/cypherv2/convertQuery.go b/cypherv2/convertQuery.go index 4ae2957c08f15927514aff8e7d8fdb51a09d8fae..6aa971d3275ff8e8c325061fbb2c2b363fa31c32 100644 --- a/cypherv2/convertQuery.go +++ b/cypherv2/convertQuery.go @@ -39,12 +39,17 @@ func createCypher(JSONQuery *entityv2.IncomingQueryJSON) (*string, error) { } func getNodeCypher(JSONQuery *entityv2.NodeStruct) (string, error){ - cypher := "" - if JSONQuery.ID == ""{ - cypher += fmt.Sprintf("(:%s)", JSONQuery.Label) - } else { - cypher += fmt.Sprintf("(%s:%s)", JSONQuery.ID, JSONQuery.Label) + label := "" + if JSONQuery.Label != "" { + label = fmt.Sprintf(":%s", JSONQuery.Label) + } + id := "" + if JSONQuery.ID != "" { + id = JSONQuery.ID } + + cypher := fmt.Sprintf("(%s%s)", id, label) + if JSONQuery.Relation != (entityv2.RelationStruct{}){ relationCypher, err := getRelationCypher(&JSONQuery.Relation) if err != nil { @@ -60,18 +65,21 @@ func getNodeCypher(JSONQuery *entityv2.NodeStruct) (string, error){ } func getRelationCypher(JSONQuery *entityv2.RelationStruct) (string, error){ - cypher := "" + label := "" + if JSONQuery.Label != "" { + label = fmt.Sprintf(":%s", JSONQuery.Label) + } + id := "" + if JSONQuery.ID != "" { + id = JSONQuery.ID + } depth := "" if JSONQuery.Depth != (entityv2.QuerySearchDepthStruct{}) { depth = fmt.Sprintf("*%d..%d", JSONQuery.Depth.Min, JSONQuery.Depth.Max) } - if JSONQuery.ID == "" { - cypher += fmt.Sprintf("[:%s%s]", JSONQuery.Label, depth) - } else { - cypher += fmt.Sprintf("[%s:%s%s]", JSONQuery.ID, JSONQuery.Label, depth) - } - + cypher := fmt.Sprintf("[%s%s%s]", id, label, depth) + if JSONQuery.Node == (&entityv2.NodeStruct{}){ return "", errors.New("relation must have a node") } diff --git a/cypherv2/convertQuery_test.go b/cypherv2/convertQuery_test.go index 202391900b112b4146a2cbcca5f5f627f676734d..96e76688a69b2d91f2023babb276afbe0d2e2f1c 100644 --- a/cypherv2/convertQuery_test.go +++ b/cypherv2/convertQuery_test.go @@ -161,6 +161,133 @@ func TestV2GroupBy(t *testing.T) { assert.Equal(t, trimmedAnswer, trimmedCypher) } + +func TestV2NoLabel(t *testing.T) { + query := []byte(`{ + "databaseName": "TweedeKamer", + "limit": 5000, + "query": [ + { + "ID": "path1", + "node": { + "ID": "p1", + "filter": [], + "export": [{ "ID": "path1_age", "attribute": "age" }], + "relation": { + "ID": "acted", + "depth": { "min": 1, "max": 1 }, + "direction": "TO", + "node": { + "label": "Movie", + "ID": "movie", + "filter": [{ "attribute": "imdbRating", "operation": "LT", "value": "7.5" }] + } + } + } + }, + { + "ID": "path2", + "node": { + "ID": "p2", + "filter": [{ "attribute": "age", "operation": "IN", "value": "@path1_age" }] + } + } + ], + "return": ["@path2"] + }`) + + var JSONQuery entityv2.IncomingQueryJSON + err := json.Unmarshal(query, &JSONQuery) + if err != nil { + fmt.Println(err) + t.Log(err) + } + + s := NewService() + cypher, _, err := s.ConvertQuery(&JSONQuery) + if err != nil { + fmt.Println(err) + t.Log(err) + } + t.Log(*cypher) + + answer := `MATCH path1 = ((p1)<-[acted*1..1]-(movie:Movie)) + WHERE movie.imdbRating < 7.5 + WITH p1.age as path1_age + MATCH path2 = ((p2)) + WHERE p2.age IN path1_age + RETURN path2 LIMIT 5000` + + fmt.Printf("Cypher: %s\n", answer) + trimmedCypher := fixCypherSpaces(cypher) + trimmedAnswer := fixCypherSpaces(&answer) + + assert.Equal(t, trimmedAnswer, trimmedCypher) +} + + +func TestV2NoDepth(t *testing.T) { + query := []byte(`{ + "databaseName": "TweedeKamer", + "limit": 5000, + "query": [ + { + "ID": "path1", + "node": { + "ID": "p1", + "filter": [], + "export": [{ "ID": "path1_age", "attribute": "age" }], + "relation": { + "ID": "acted", + "direction": "TO", + "node": { + "label": "Movie", + "ID": "movie", + "filter": [{ "attribute": "imdbRating", "operation": "LT", "value": "7.5" }] + } + } + } + }, + { + "ID": "path2", + "node": { + "ID": "p2", + "filter": [{ "attribute": "age", "operation": "IN", "value": "@path1_age" }] + } + } + ], + "return": ["@path2"] + }`) + + var JSONQuery entityv2.IncomingQueryJSON + err := json.Unmarshal(query, &JSONQuery) + if err != nil { + fmt.Println(err) + t.Log(err) + } + + s := NewService() + cypher, _, err := s.ConvertQuery(&JSONQuery) + if err != nil { + fmt.Println(err) + t.Log(err) + } + t.Log(*cypher) + + answer := `MATCH path1 = ((p1)<-[acted]-(movie:Movie)) + WHERE movie.imdbRating < 7.5 + WITH p1.age as path1_age + MATCH path2 = ((p2)) + WHERE p2.age IN path1_age + RETURN path2 LIMIT 5000` + + fmt.Printf("Cypher: %s\n", answer) + trimmedCypher := fixCypherSpaces(cypher) + trimmedAnswer := fixCypherSpaces(&answer) + + assert.Equal(t, trimmedAnswer, trimmedCypher) +} + // func TestSmallChain(t *testing.T) { // query := []byte(`{ // "databaseName": "TweedeKamer", diff --git a/go.mod b/go.mod index e219c43cb901bb274f69033591ae3b5bc08dbaf5..71f1f18bf3a89b1239467864c68d5a11d62c07f2 100644 --- a/go.mod +++ b/go.mod @@ -2,10 +2,13 @@ module git.science.uu.nl/graphpolaris/query-conversion go 1.18 +require github.com/stretchr/testify v1.7.0 + require ( github.com/boumenot/gocover-cobertura v1.2.0 // indirect - github.com/stretchr/testify v1.7.0 golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect + golang.org/x/mod v0.12.0 // indirect + golang.org/x/sys v0.10.0 // indirect golang.org/x/tools v0.11.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect )