package goneo
import (
"fmt"
"github.com/neo4j/neo4j-go-driver/v4/neo4j"
"strings"
)
/* Instance */
type authType = int
const (
noAuth authType = iota
basic
)
type neo4JDriver struct {
engine neo4j.Driver
uri, username, password string
realm string
uniqueNodes bool
auth authType
}
/* Options */
type Option = func(*neo4JDriver)
func WithRealm(realm string) Option {
return func(d *neo4JDriver) {
d.realm = realm
}
}
func WithUniqueNodes() Option {
return func(d *neo4JDriver) {
d.uniqueNodes = true
}
}
func WithNoAuth() Option {
return func(driver *neo4JDriver) {
driver.auth = noAuth
}
}
func WithBasicAuth(username, password string) Option {
return func(driver *neo4JDriver) {
driver.auth = basic
driver.username, driver.password = username, password
}
}
func NewNeo4JDriver(uri string, opts ...Option) *neo4JDriver {
instance := &neo4JDriver{uri: uri}
for _, opt := range opts {
opt(instance)
}
return instance
}
func (d *neo4JDriver) Connect() (err error) {
switch d.auth {
case basic:
d.engine, err = neo4j.NewDriver(d.uri, neo4j.BasicAuth(d.username, d.password, d.realm))
case noAuth:
d.engine, err = neo4j.NewDriver(d.uri, neo4j.NoAuth())
}
return
}
func (d *neo4JDriver) Disconnect() error {
return d.engine.Close()
}
func (d *neo4JDriver) create(in interface{}) (*neo4j.Record, error) {
// @TODO - Extend w/ the options pattern
session := d.engine.NewSession(neo4j.SessionConfig{})
defer func() { _ = session.Close() }()
verb := "CREATE"
if d.uniqueNodes {
verb = "MERGE"
}
records, err := session.WriteTransaction(func(tx neo4j.Transaction) (interface{}, error) {
result, err := tx.Run(fmt.Sprintf(`%s (%s:%s %s) RETURN %s`,
verb,
identifier(in),
strings.Title(identifier(in)),
marshal(in),
returns(in)), nil)
if err != nil {
return nil, err
}
if result.Next() {
return result.Record(), nil
}
return nil, result.Err()
})
if err != nil {
return nil, err
}
return records.(*neo4j.Record), nil
}
func (d *neo4JDriver) list(identifier string) ([]*neo4j.Record, error) {
session := d.engine.NewSession(neo4j.SessionConfig{})
defer func() { _ = session.Close() }()
records, err := session.ReadTransaction(func(tx neo4j.Transaction) (interface{}, error) {
result, err := tx.Run(fmt.Sprintf("MATCH (n:%s) RETURN n", identifier), nil)
if err != nil {
return nil, err
}
var records []*neo4j.Record
for result.Next() {
records = append(records, result.Record())
}
return records, result.Err()
})
if err != nil {
return nil, err
}
return records.([]*neo4j.Record), nil
}
func (d *neo4JDriver) link(a, b interface{}, linkName string) error {
session := d.engine.NewSession(neo4j.SessionConfig{})
defer func() { _ = session.Close() }()
_, err := session.WriteTransaction(func(tx neo4j.Transaction) (interface{}, error) {
result, err := tx.Run(fmt.Sprintf("MATCH (%s:%s), (%s:%s) WHERE %s AND %s CREATE(%s)-[:%s]->(%s)",
identifierWithSuffix(a, "_a"), strings.Title(identifier(a)),
identifierWithSuffix(b, "_b"), strings.Title(identifier(b)),
filterWithSuffix(a, "_a"), filterWithSuffix(b, "_b"),
identifierWithSuffix(a, "_a"),
linkName,
identifierWithSuffix(b, "_b")), nil)
if err != nil {
return nil, err
}
return nil, result.Err()
})
return err
}
// @TODO - Refactor all this
func (d *neo4JDriver) delete(in interface{}) error {
session := d.engine.NewSession(neo4j.SessionConfig{})
defer func() { _ = session.Close() }()
_, err := session.WriteTransaction(func(tx neo4j.Transaction) (interface{}, error) {
result, err := tx.Run(fmt.Sprintf("MATCH (%s:%s) WHERE %s DETACH DELETE(%s)",
identifier(in), strings.Title(identifier(in)),
filter(in),
identifier(in)), nil)
if err != nil {
return nil, err
}
return nil, result.Err()
})
return err
}
func (d *neo4JDriver) find(in interface{}) ([]*neo4j.Record, error) {
session := d.engine.NewSession(neo4j.SessionConfig{})
defer func() { _ = session.Close() }()
records, err := session.ReadTransaction(func(tx neo4j.Transaction) (interface{}, error) {
result, err := tx.Run(fmt.Sprintf("MATCH (%s:%s) WHERE %s RETURN %s",
identifier(in),
strings.Title(identifier(in)),
finder(in),
identifier(in),
), nil)
if err != nil {
return nil, err
}
var records []*neo4j.Record
for result.Next() {
records = append(records, result.Record())
}
return records, result.Err()
})
if err != nil {
return nil, err
}
return records.([]*neo4j.Record), nil
}
func (d *neo4JDriver) getLeafs(rootType interface{}, leafType, linkName string) ([]*neo4j.Record, error) {
session := d.engine.NewSession(neo4j.SessionConfig{})
defer func() { _ = session.Close() }()
rootTypeId := identifier(rootType)
records, err := session.ReadTransaction(func(tx neo4j.Transaction) (interface{}, error) {
result, err := tx.Run(fmt.Sprintf("MATCH (n:%s)-[:%s*]->(%s:%s) WHERE %s RETURN n",
leafType,
linkName,
rootTypeId, strings.Title(rootTypeId),
filter(rootType)), nil)
if err != nil {
return nil, err
}
var records []*neo4j.Record
for result.Next() {
records = append(records, result.Record())
}
return records, result.Err()
})
if err != nil {
return nil, err
}
return records.([]*neo4j.Record), nil
}
|
The pages are generated with Golds v0.4.2. (GOOS=darwin GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |