gogm

package module
v1.5.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 30, 2021 License: MIT Imports: 13 Imported by: 0

README

Go Report Card Actions Status GoDoc

GoGM Golang Object Graph Mapper

go get -u github.com/mindstand/gogm
Documentation updates will be coming periodically as this project matures

Features

  • Struct Mapping through the gogm struct decorator
  • Full support for ACID transactions
  • Underlying connection pooling
  • Support for HA Casual Clusters using bolt+routing through the Official Neo4j Go Driver
  • Custom queries in addition to built in functionality
  • Builder pattern cypher queries using MindStand's cypher dsl package
  • CLI to generate link and unlink functions for gogm structs.
  • Multi database support with Neo4j v4

Usage

Struct Configuration
text notates deprecation

Decorators that can be used

  • name=<name> -- used to set the field name that will show up in neo4j.
  • relationship=<edge_name> -- used to set the name of the edge on that field.
  • direction=<INCOMING|OUTGOING|BOTH|NONE> -- used to specify direction of that edge field.
  • index -- marks field to have an index applied to it.
  • unique -- marks field to have unique constraint.
  • pk -- marks field as a primary key. Can only have one pk, composite pk's are not supported.
  • properties -- marks that field is using a map. GoGM only supports properties fields of map[string]interface{}, map[string]<primitive>, map[string][]<primitive> and []<primitive>
  • - -- marks that field will be ignored by the ogm
Not on relationship member variables

All relationships must be defined as either a pointer to a struct or a slice of struct pointers *SomeStruct or []*SomeStruct

Use ; as delimiter between decorator tags.

Ex.

type TdString string

type MyNeo4jObject struct {
  // provides required node fields
  gogm.BaseNode

  Field string `gogm:"name=field"`
  Props map[string]interface{} `gogm:"properties;name=props"` //note that this would show up as `props.<key>` in neo4j
  IgnoreMe bool `gogm="-"`
  UniqueTypeDef TdString `gogm:"name=unique_type_def"`
  Relation *SomeOtherStruct `gogm="relationship=SOME_STRUCT;direction=OUTGOING"`
  ManyRelation []*SomeStruct `gogm="relationship=MANY;direction=INCOMING"`
}

GOGM Usage
package main

import (
	"github.com/mindstand/gogm"
	"time"
)

type tdString string
type tdInt int

//structs for the example (can also be found in decoder_test.go)
type VertexA struct {
	// provides required node fields
	gogm.BaseNode

TestField         string                `gogm:"name=test_field"`
	TestTypeDefString tdString          `gogm:"name=test_type_def_string"`
	TestTypeDefInt    tdInt             `gogm:"name=test_type_def_int"`
	MapProperty       map[string]string `gogm:"name=map_property;properties"`
	SliceProperty     []string          `gogm:"name=slice_property;properties"`
    SingleA           *VertexB          `gogm:"direction=incoming;relationship=test_rel"`
	ManyA             []*VertexB        `gogm:"direction=incoming;relationship=testm2o"`
	MultiA            []*VertexB        `gogm:"direction=incoming;relationship=multib"`
	SingleSpecA       *EdgeC            `gogm:"direction=outgoing;relationship=special_single"`
	MultiSpecA        []*EdgeC          `gogm:"direction=outgoing;relationship=special_multi"`
}

type VertexB struct {
	// provides required node fields
	gogm.BaseNode

	TestField  string     `gogm:"name=test_field"`
	TestTime   time.Time  `gogm:"name=test_time"`
	Single     *VertexA   `gogm:"direction=outgoing;relationship=test_rel"`
	ManyB      *VertexA   `gogm:"direction=outgoing;relationship=testm2o"`
	Multi      []*VertexA `gogm:"direction=outgoing;relationship=multib"`
	SingleSpec *EdgeC     `gogm:"direction=incoming;relationship=special_single"`
	MultiSpec  []*EdgeC   `gogm:"direction=incoming;relationship=special_multi"`
}

type EdgeC struct {
	// provides required node fields
	gogm.BaseNode

	Start *VertexA
	End   *VertexB
	Test  string `gogm:"name=test"`
}

func main() {
	config := gogm.Config{
		IndexStrategy: gogm.VALIDATE_INDEX, //other options are ASSERT_INDEX and IGNORE_INDEX
		PoolSize:      50,
		Port:          7687,
		IsCluster:     false, //tells it whether or not to use `bolt+routing`
		Host:          "0.0.0.0",
		Password:      "password",
		Username:      "neo4j",
	}

	err := gogm.Init(&config, &VertexA{}, &VertexB{}, &EdgeC{})
	if err != nil {
		panic(err)
	}

	//param is readonly, we're going to make stuff so we're going to do read write
	sess, err := gogm.NewSession(false)
	if err != nil {
		panic(err)
	}
	
	//close the session
	defer sess.Close()

	aVal := &VertexA{
		TestField: "woo neo4j",
	}

	bVal := &VertexB{
		TestTime: time.Now().UTC(),
	}

	//set bi directional pointer
	bVal.Single = aVal
	aVal.SingleA = bVal

	err = sess.SaveDepth(aVal, 2)
	if err != nil {
		panic(err)
	}

	//load the object we just made (save will set the uuid)
	var readin VertexA
	err = sess.Load(&readin, aVal.UUID)
	if err != nil {
		panic(err)
	}

}


GoGM CLI

CLI Installation

go get -u github.com/mindstand/gogm/cli/gogmcli

CLI Usage

NAME:
   gogmcli - used for neo4j operations from gogm schema

USAGE:
   gogmcli [global options] command [command options] [arguments...]

VERSION:
   1.0.0

COMMANDS:
   generate, g, gen  to generate link and unlink functions for nodes
   help, h           Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --debug, -d    execute in debug mode (default: false)
   --help, -h     show help (default: false)
   --version, -v  print the version (default: false)

Inspiration

Inspiration came from the Java OGM implementation by Neo4j.

Road Map

  • Schema Migration
  • Errors overhaul using go 1.13 error wrapping
  • TLS Support
  • Documentation (obviously)

How you can help

  • Report Bugs
  • Fix bugs
  • Contribute (refer to contribute.md)

Documentation

Index

Constants

View Source
const AccessModeRead = neo4j.AccessModeRead
View Source
const AccessModeWrite = neo4j.AccessModeWrite

Variables

View Source
var ErrConfiguration = errors.New("gogm: configuration was malformed")
View Source
var ErrConnection = errors.New("gogm: connection error")
View Source
var ErrInternal = errors.New("gogm: internal error")
View Source
var ErrInvalidParams = errors.New("gogm: invalid params")
View Source
var ErrNotFound = errors.New("gogm: data not found")

base errors for gogm 1.13 errors, these are pretty self explanatory

View Source
var ErrTransaction = errors.New("gogm: transaction error")
View Source
var ErrValidation = errors.New("gogm: struct validation error")

Functions

func Init

func Init(conf *Config, mapTypes ...interface{}) error

Init sets up gogm. Takes in config object and variadic slice of gogm nodes to map. Note: Must pass pointers to nodes!

func PathLoadStrategyEdgeConstraint

func PathLoadStrategyEdgeConstraint(startVariable, startLabel, endLabel, endTargetField string, minJumps, maxJumps, depth int, additionalConstraints dsl.ConditionOperator) (dsl.Cypher, error)

PathLoadStrategyEdgeConstraint is similar to load many, but requires that it is related to another node via some edge

func PathLoadStrategyMany

func PathLoadStrategyMany(variable, label string, depth int, additionalConstraints dsl.ConditionOperator) (dsl.Cypher, error)

PathLoadStrategyMany loads many using path strategy

func PathLoadStrategyOne

func PathLoadStrategyOne(variable, label string, depth int, additionalConstraints dsl.ConditionOperator) (dsl.Cypher, error)

PathLoadStrategyOne loads one object using path strategy

func Reset

func Reset()

Reset Resets GoGM configuration

Types

type BaseNode

type BaseNode struct {
	// Id is the GraphId that neo4j uses internally
	Id int64 `json:"-" gogm:"name=id"`
	// UUID is the unique identifier GoGM uses as a primary key
	UUID string `json:"uuid" gogm:"pk;name=uuid"`

	// LoadMap represents the state of how a node was loaded for neo4j.
	// This is used to determine if relationships are removed on save
	// field -- relations
	LoadMap map[string]*RelationConfig `json:"-" gogm:"-"`
}

BaseNode contains fields that ALL GoGM nodes are required to have

type Config

type Config struct {
	// Host is the neo4j host
	Host string `yaml:"host" json:"host" mapstructure:"host"`
	// Port is the neo4j port
	Port int `yaml:"port" json:"port" mapstructure:"port"`

	// IsCluster specifies whether GoGM is connecting to a casual cluster or not
	IsCluster bool `yaml:"is_cluster" json:"is_cluster" mapstructure:"is_cluster"`

	// Username is the GoGM username
	Username string `yaml:"username" json:"username" mapstructure:"username"`
	// Password is the GoGM password
	Password string `yaml:"password" json:"password" mapstructure:"password"`

	// PoolSize is the size of the connection pool for GoGM
	PoolSize int `yaml:"pool_size" json:"pool_size" mapstructure:"pool_size"`

	Realm string `yaml:"realm" json:"realm" mapstructure:"realm"`

	Encrypted bool `yaml:"encrypted" json:"encrypted" mapstructure:"encrypted"`

	// Index Strategy defines the index strategy for GoGM
	IndexStrategy IndexStrategy `yaml:"index_strategy" json:"index_strategy" mapstructure:"index_strategy"`
	TargetDbs     []string      `yaml:"target_dbs" json:"target_dbs" mapstructure:"target_dbs"`

	Logger logrus.FieldLogger `yaml:"-" json:"-" mapstructure:"-"`
	// if logger is not nil log level will be ignored
	LogLevel string `json:"log_level" yaml:"log_level" mapstructure:"log_level"`
}

Config Defined GoGM config

func (*Config) ConnectionString

func (c *Config) ConnectionString() string

ConnectionString builds the neo4j bolt/bolt+routing connection string

type IEdge

type IEdge interface {
	// GetStartNode gets start node of edge
	GetStartNode() interface{}
	// GetStartNodeType gets reflect type of start node
	GetStartNodeType() reflect.Type
	// SetStartNode sets start node of edge
	SetStartNode(v interface{}) error

	// GetEndNode gets end node of edge
	GetEndNode() interface{}
	// GetEndNodeType gets reflect type of end node
	GetEndNodeType() reflect.Type
	// SetEndNode sets end node of edge
	SetEndNode(v interface{}) error
}

IEdge specifies required functions for special edge nodes

type ISession

type ISession interface {
	//transaction functions
	ITransaction

	//load single object
	Load(respObj interface{}, id string) error

	//load object with depth
	LoadDepth(respObj interface{}, id string, depth int) error

	//load with depth and filter
	LoadDepthFilter(respObj interface{}, id string, depth int, filter *dsl.ConditionBuilder, params map[string]interface{}) error

	//load with depth, filter and pagination
	LoadDepthFilterPagination(respObj interface{}, id string, depth int, filter dsl.ConditionOperator, params map[string]interface{}, pagination *Pagination) error

	//load slice of something
	LoadAll(respObj interface{}) error

	//load all of depth
	LoadAllDepth(respObj interface{}, depth int) error

	//load all of type with depth and filter
	LoadAllDepthFilter(respObj interface{}, depth int, filter dsl.ConditionOperator, params map[string]interface{}) error

	//load all with depth, filter and pagination
	LoadAllDepthFilterPagination(respObj interface{}, depth int, filter dsl.ConditionOperator, params map[string]interface{}, pagination *Pagination) error

	//load all edge query
	LoadAllEdgeConstraint(respObj interface{}, endNodeType, endNodeField string, edgeConstraint interface{}, minJumps, maxJumps, depth int, filter dsl.ConditionOperator) error

	//save object
	Save(saveObj interface{}) error

	//save object with depth
	SaveDepth(saveObj interface{}, depth int) error

	//delete
	Delete(deleteObj interface{}) error

	//delete uuid
	DeleteUUID(uuid string) error

	//specific query, responds to slice and single objects
	Query(query string, properties map[string]interface{}, respObj interface{}) error

	//similar to query, but returns raw rows/cols
	QueryRaw(query string, properties map[string]interface{}) ([][]interface{}, error)

	//delete everything, this will literally delete everything
	PurgeDatabase() error

	// closes session
	Close() error
}

session object for ogm interactions

type ITransaction

type ITransaction interface {
	// Begin begins transaction
	Begin() error
	// Rollback rolls back transaction
	Rollback() error
	// RollbackWithError wraps original error into rollback error if there is one
	RollbackWithError(err error) error
	// Commit commits transaction
	Commit() error
}

ITransaction specifies functions for Neo4j ACID transactions

type IndexStrategy

type IndexStrategy int

IndexStrategy Index Strategy typedefs int to define different index approaches

const (
	// ASSERT_INDEX ensures that all indices are set and sets them if they are not there
	ASSERT_INDEX IndexStrategy = 0
	// VALIDATE_INDEX ensures that all indices are set
	VALIDATE_INDEX IndexStrategy = 1
	// IGNORE_INDEX skips the index step of setup
	IGNORE_INDEX IndexStrategy = 2
)

type InvalidDecoratorConfigError

type InvalidDecoratorConfigError struct {
	Field string
	Issue string
}

func NewInvalidDecoratorConfigError

func NewInvalidDecoratorConfigError(issue, field string) *InvalidDecoratorConfigError

func (*InvalidDecoratorConfigError) Error

type InvalidStructConfigError

type InvalidStructConfigError struct {
	// contains filtered or unexported fields
}

func NewInvalidStructConfigError

func NewInvalidStructConfigError(issue string) *InvalidStructConfigError

func (*InvalidStructConfigError) Error

func (i *InvalidStructConfigError) Error() string

type LoadStrategy

type LoadStrategy int

Specifies query based load strategy

const (
	// PathLoadStrategy uses cypher path
	PATH_LOAD_STRATEGY LoadStrategy = iota
	// SchemaLoadStrategy generates queries specifically from generated schema
	SCHEMA_LOAD_STRATEGY
)

type NodeWrap

type NodeWrap struct {
	Id     int64                  `json:"id"`
	Labels []string               `json:"labels"`
	Props  map[string]interface{} `json:"props"`
}

NodeWrap wraps the neo4j node struct because it is private

type Pagination

type Pagination struct {
	// specifies which page number to load
	PageNumber int
	// limits how many records per page
	LimitPerPage int
	// specifies variable to order by
	OrderByVarName string
	// specifies field to order by on
	OrderByField string
	// specifies whether orderby is desc or asc
	OrderByDesc bool
}

pagination configuration

func (*Pagination) Validate

func (p *Pagination) Validate() error

type PathWrap

type PathWrap struct {
	Nodes    []*NodeWrap         `json:"nodes"`
	RelNodes []*RelationshipWrap `json:"rel_nodes"`
}

PathWrap wraps the neo4j path struct because it is private

type RelationConfig

type RelationConfig struct {
	// stores graph ids
	Ids []int64 `json:"-" gomg:"-"`
	// specifies relationship type
	RelationType RelationType `json:"-"  gomg:"-"`
}

RelationConfig specifies how relationships are loaded

type RelationType

type RelationType int

RelationType Specifies Type of testRelationship

const (
	// Single Side of relationship can only point to 0 or 1 other nodes
	Single RelationType = 0

	// Multi Side of relationship can point to 0+ other nodes
	Multi RelationType = 1
)

type RelationshipWrap

type RelationshipWrap struct {
	Id      int64                  `json:"id"`
	StartId int64                  `json:"start_id"`
	EndId   int64                  `json:"end_id"`
	Type    string                 `json:"type"`
	Props   map[string]interface{} `json:"props"`
}

RelationshipWrap wraps the neo4j relationship struct because it is private

type Session

type Session struct {
	DefaultDepth int
	LoadStrategy LoadStrategy
	// contains filtered or unexported fields
}

func NewSession

func NewSession(readonly bool) (*Session, error)

func NewSessionWithConfig

func NewSessionWithConfig(conf SessionConfig) (*Session, error)

func (*Session) Begin

func (s *Session) Begin() error

func (*Session) Close

func (s *Session) Close() error

func (*Session) Commit

func (s *Session) Commit() error

func (*Session) Delete

func (s *Session) Delete(deleteObj interface{}) error

func (*Session) DeleteUUID

func (s *Session) DeleteUUID(uuid string) error

func (*Session) Load

func (s *Session) Load(respObj interface{}, id string) error

func (*Session) LoadAll

func (s *Session) LoadAll(respObj interface{}) error

func (*Session) LoadAllDepth

func (s *Session) LoadAllDepth(respObj interface{}, depth int) error

func (*Session) LoadAllDepthFilter

func (s *Session) LoadAllDepthFilter(respObj interface{}, depth int, filter dsl.ConditionOperator, params map[string]interface{}) error

func (*Session) LoadAllDepthFilterPagination

func (s *Session) LoadAllDepthFilterPagination(respObj interface{}, depth int, filter dsl.ConditionOperator, params map[string]interface{}, pagination *Pagination) error

func (*Session) LoadAllEdgeConstraint

func (s *Session) LoadAllEdgeConstraint(respObj interface{}, endNodeType, endNodeField string, edgeConstraint interface{}, minJumps, maxJumps, depth int, filter dsl.ConditionOperator) error

func (*Session) LoadDepth

func (s *Session) LoadDepth(respObj interface{}, id string, depth int) error

func (*Session) LoadDepthFilter

func (s *Session) LoadDepthFilter(respObj interface{}, id string, depth int, filter *dsl.ConditionBuilder, params map[string]interface{}) error

func (*Session) LoadDepthFilterPagination

func (s *Session) LoadDepthFilterPagination(respObj interface{}, id string, depth int, filter dsl.ConditionOperator, params map[string]interface{}, pagination *Pagination) error

func (*Session) PurgeDatabase

func (s *Session) PurgeDatabase() error

func (*Session) Query

func (s *Session) Query(query string, properties map[string]interface{}, respObj interface{}) error

func (*Session) QueryRaw

func (s *Session) QueryRaw(query string, properties map[string]interface{}) ([][]interface{}, error)

func (*Session) Rollback

func (s *Session) Rollback() error

func (*Session) RollbackWithError

func (s *Session) RollbackWithError(originalError error) error

func (*Session) Save

func (s *Session) Save(saveObj interface{}) error

func (*Session) SaveDepth

func (s *Session) SaveDepth(saveObj interface{}, depth int) error

type SessionConfig

type SessionConfig neo4j.SessionConfig

Directories

Path Synopsis
cmd
gogmcli/gen
gen provides code to generate link and unlink functions for gogm structs
gen provides code to generate link and unlink functions for gogm structs
Code generated by GoGM v1.0.1.
Code generated by GoGM v1.0.1.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL