mirror of
https://github.com/vcscsvcscs/GenerationsHeritage.git
synced 2025-08-13 06:19:05 +02:00
implement family tree queries
This commit is contained in:
45
apps/db-adapter/internal/memgraph/family_tree.go
Normal file
45
apps/db-adapter/internal/memgraph/family_tree.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
)
|
||||
|
||||
// returned map has "people" which is a slice of OptimizedPersonNode and relationships wich a slice of Relatioship type.
|
||||
func GetFamilyTreeById(ctx context.Context, userId int) neo4j.ManagedTransactionWork {
|
||||
return func(tx neo4j.ManagedTransaction) (any, error) {
|
||||
result, err := tx.Run(ctx, GetBloodRelativesCypherQuery, map[string]any{
|
||||
"id": userId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
record, err := result.Single(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return record.AsMap(), nil
|
||||
}
|
||||
}
|
||||
|
||||
// returned map has "people" which is a slice of OptimizedPersonNode and relationships wich a slice of Relatioship type.
|
||||
func GetFamilyTreeWithSpousesById(ctx context.Context, userId int) neo4j.ManagedTransactionWork {
|
||||
return func(tx neo4j.ManagedTransaction) (any, error) {
|
||||
result, err := tx.Run(ctx, GetFamilyTreeWithSpousesCypherQuery, map[string]any{
|
||||
"id": userId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
record, err := result.Single(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return record.AsMap(), nil
|
||||
}
|
||||
}
|
145
apps/db-adapter/internal/memgraph/family_tree_test.go
Normal file
145
apps/db-adapter/internal/memgraph/family_tree_test.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package memgraph
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/internal/memgraph/mock"
|
||||
)
|
||||
|
||||
func TestGetFamilyTreeById(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
mockTxSetup func() *mock.Transaction
|
||||
expectedResult map[string]any
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
name: "Successful case",
|
||||
mockTxSetup: func() *mock.Transaction {
|
||||
mockTx := new(mock.Transaction)
|
||||
mockResult := new(mock.Result)
|
||||
mockRecord := &neo4j.Record{
|
||||
Values: []any{"value"},
|
||||
Keys: []string{"key"},
|
||||
}
|
||||
mockResult.On("Single", context.Background()).Return(mockRecord, nil)
|
||||
mockTx.On("Run", context.Background(), GetBloodRelativesCypherQuery, map[string]any{"id": 123}).Return(mockResult, nil)
|
||||
return mockTx
|
||||
},
|
||||
expectedResult: map[string]any{"key": "value"},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "Error during Run",
|
||||
mockTxSetup: func() *mock.Transaction {
|
||||
mockTx := new(mock.Transaction)
|
||||
mockTx.On("Run", context.Background(), GetBloodRelativesCypherQuery, map[string]any{"id": 123}).Return(nil, errors.New("run error"))
|
||||
return mockTx
|
||||
},
|
||||
expectedResult: nil,
|
||||
expectedError: errors.New("run error"),
|
||||
},
|
||||
{
|
||||
name: "Error during Single",
|
||||
mockTxSetup: func() *mock.Transaction {
|
||||
mockTx := new(mock.Transaction)
|
||||
mockResult := new(mock.Result)
|
||||
mockResult.On("Single", context.Background()).Return(nil, errors.New("single error"))
|
||||
mockTx.On("Run", context.Background(), GetBloodRelativesCypherQuery, map[string]any{"id": 123}).Return(mockResult, nil)
|
||||
return mockTx
|
||||
},
|
||||
expectedResult: nil,
|
||||
expectedError: errors.New("single error"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
userId := 123
|
||||
|
||||
mockTx := tc.mockTxSetup()
|
||||
work := GetFamilyTreeById(ctx, userId)
|
||||
result, err := work(mockTx)
|
||||
|
||||
if tc.expectedError != nil {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, result)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.expectedResult, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFamilyTreeWithSpousesById(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
mockTxSetup func() *mock.Transaction
|
||||
expectedResult map[string]any
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
name: "Successful case",
|
||||
mockTxSetup: func() *mock.Transaction {
|
||||
mockTx := new(mock.Transaction)
|
||||
mockResult := new(mock.Result)
|
||||
mockRecord := &neo4j.Record{
|
||||
Values: []any{"value"},
|
||||
Keys: []string{"key"},
|
||||
}
|
||||
mockResult.On("Single", context.Background()).Return(mockRecord, nil)
|
||||
mockTx.On("Run", context.Background(), GetFamilyTreeWithSpousesCypherQuery, map[string]any{"id": 123}).Return(mockResult, nil)
|
||||
return mockTx
|
||||
},
|
||||
expectedResult: map[string]any{"key": "value"},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "Error during Run",
|
||||
mockTxSetup: func() *mock.Transaction {
|
||||
mockTx := new(mock.Transaction)
|
||||
mockTx.On("Run", context.Background(), GetFamilyTreeWithSpousesCypherQuery, map[string]any{"id": 123}).Return(nil, errors.New("run error"))
|
||||
return mockTx
|
||||
},
|
||||
expectedResult: nil,
|
||||
expectedError: errors.New("run error"),
|
||||
},
|
||||
{
|
||||
name: "Error during Single",
|
||||
mockTxSetup: func() *mock.Transaction {
|
||||
mockTx := new(mock.Transaction)
|
||||
mockResult := new(mock.Result)
|
||||
mockResult.On("Single", context.Background()).Return(nil, errors.New("single error"))
|
||||
mockTx.On("Run", context.Background(), GetFamilyTreeWithSpousesCypherQuery, map[string]any{"id": 123}).Return(mockResult, nil)
|
||||
return mockTx
|
||||
},
|
||||
expectedResult: nil,
|
||||
expectedError: errors.New("single error"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
userId := 123
|
||||
|
||||
mockTx := tc.mockTxSetup()
|
||||
work := GetFamilyTreeWithSpousesById(ctx, userId)
|
||||
result, err := work(mockTx)
|
||||
|
||||
if tc.expectedError != nil {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, result)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.expectedResult, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -88,10 +88,12 @@ var CreateSpouseRelationshipCypherQuery string
|
||||
//go:embed queries/delete_relationship.cypher
|
||||
var DeleteRelationshipCypherQuery string
|
||||
|
||||
// Requires id parameter.
|
||||
// Requires id1, id2, relationship parameter.
|
||||
//
|
||||
//go:embed queries/get_family_tree_by_id.cypher
|
||||
var GetFamilyTreeByIdCypherQuery string
|
||||
// return relationship
|
||||
//
|
||||
//go:embed queries/update_relationship.cypher
|
||||
var UpdateRelationshipCypherQuery string
|
||||
|
||||
// Requires id1, id2 parameter.
|
||||
//
|
||||
|
@@ -8,7 +8,7 @@ WITH collections.to_set(collect(n)+collect(family)+collect(children)+collect(dir
|
||||
collections.to_set(collect(c) + collect(p) + collect(s) + collect(ds)) as relationships
|
||||
UNWIND people as ppl
|
||||
RETURN collect({
|
||||
id: id(ppl),
|
||||
id: id(ppl),
|
||||
first_name: ppl.first_name,
|
||||
middle_name: ppl.middle_name,
|
||||
last_name: ppl.last_name,
|
||||
|
@@ -1,3 +1,3 @@
|
||||
MATCH (n)-[r]-(o)
|
||||
MATCH (n)-[r]->(o)
|
||||
WHERE id(n) = $id1 AND id(o) = $id2
|
||||
RETURN r as relationship
|
@@ -0,0 +1,4 @@
|
||||
MATCH (n)-[r]->(o)
|
||||
WHERE id(n) = $id1 AND id(o) = $id2
|
||||
SET r += $relationship
|
||||
RETURN r as relationship
|
Reference in New Issue
Block a user