Skip to content

neo4j go ogm

codingfinest edited this page Mar 3, 2020 · 6 revisions

Overview

neo4j-go-ogm is a Golang object graph mapper for Neo4j. This object graph mapper provides developers a quick way to create, update, load and delete Neo4j database entities represented by Golang objects at runtime.

Connecting to the database

//Set up the Session
var config = &gogm.Config{
		"uri",
		"username",
		"password",
		gogm.NONE/*log level*/,
		false/*allow cyclic ref*/}

var ogm = gogm.New(config)
var session, err = ogm.OpenSession(true /*AccessModeWrite*/)

if err != nil {
    //handle err
}

Config

The config object used to initiaize the OGM takes the following fields:

  • uri: This is the databse connection string. Since neo4j-go-ogm depends on the official Neo4j driver, you can also connect to a cluster. See Neo4j driver
  • username: username to use to establish the database connection
  • passowrd: password
  • Log Level: Specifies the log level. Value of NONE turns logging off
  • Allow cyclic ref: Determine if cyclic references should be allowed on load of database entities. For example:
type Person struct {
	gogm.Node
	Blog *Blog
}

type Blog struct {
	gogm.Node
    Author  *Person  
}

If the value of allow Allow cyclic ref is true on load of a Person, Person will contain Blog which references Person, which references Blog and so on. This will lead to errors when marshalling Person as the Go JSON package doesn't support cyclic reference. Setting this value to false will prevent cyclic reference.

Using neo4j-go-ogm methods

All neo4j-go-ogm methods which take an object as a parameter expects the pointer to the pointer of that object. For example: if actor is a pointer to an instance of Actor, the neo4j-go-ogm methods such as: Save(), will expect &actor as a parameter.

actor := &Actor{}
session.Save(&actor, nil)

If at anytime you're unsure about how to use a method, have a look at the extensive package test.

Entities

The 2 database entities Node and Relationship can be represented by a Golang struct which embeds the gogm.Node and gogm.Relationship objects respectively. gogm.Node or gogm.Relationship MUST be embedded directly or indirectly on the first field of the struct.

Nodes:

Nodes are structs that embed gogm.Node directly or indirectly on the first field of the struct.

Labels: By default, neo4j-go-ogm uses the object struct to determine the node labels. For example, Person will have a Person label while Actor will have Actor:Person label due to "inheritance".

type Person struct {
	gogm.Node
}

type Actor struct {
	Person
}

By using the label tag on the field embedding gogm.Node directly or indirectly, the default label can be overwritten. This tag can be used multiple times on this field. For example,

type Star struct {
	Actor `gogm:"label:SUPER,label:RICH"`
}

Runtime managed labels: Labels can also be managed at runtime. A slice of strings ([]string) property tagged with label can be used to manage the label of the node at runtime. This slice cannot contain any label which can be found in another node contained within the parent node. For example:

type Blog struct {
	gogm.Node
    Author  *Person
	Tags    []string  `gogm:"label"`
}

At runtime, on a create or update of an instance of Blog, the labels of the struct will be computed and combined with the values in the Tags field to form the final labels of the node instance. The Tags slice cannot contain a Person value at runtime.

Relationships:

A relationship is created when a Node has another Node or Relationship entity as a field. For example, in the Blog struct above, a relationship will be created between the Blog instance and the Person instance pointed to by the Author field. By default, the relationship will have a type of Blog_Person and a direction of Outgoing. To change relationship type created from Node fields, use the relType tag on the Node field. To denote the direction of the relationship, use -> for Outgoing, <- for Incoming and -- for Undirected on the direction tag. For example: In the below Blog struct, the relationship has been updated to be of type WROTE and direction Incoming. Basically (Blog)<-[:WROTE]-(Person) or (Person)-[:WROTE]->(Blog)

type Blog struct {
	gogm.Node
    Author  *Person  `gogm:"reltype:WROTE,direction:<-"`
	Tags    []string  `gogm:"label"`
}

Relationships created by having a Node struct embed another Node struct can't have properties. These are simple relationships and have just a type and direction. To create relationships with properties, use relationship entity.

Relationship Entities:

A relationship entity is created by embedding gogm.Relationship directly or indirectly on the first field of the struct. The struct must contain a Node tagged startNode and another Node tagged endNode.

type Blog struct {
	gogm.Node
    About   *BlogInfo
	Tags    []string  `gogm:"label"`
}

type BlogInfo struct {
	gogm.Relationship
    Author  *Person `gogm:"startNode"`
	Blog    *Blog `gogm:"endNode"`
    Created *time.Time
}

By default, the struct name uppercased is used as the relationship type. To change the relationship type, use the reltype tag on the first struct field

type BlogInfo struct {
	gogm.Relationship `gogm:"reltype:WROTE"`
    Author  *Person `gogm:"startNode"`
	Blog    *Blog `gogm:"endNode"`
    Created *time.Time
}

Properties

All non-entities within the Node or Relationship entities are considered properties. The property names of the mapped database objects are derived by using the lowercase of the field name. To use a custom property name, use the name tag on the struct field. Example:

type Person struct {
	gogm.Node
    Name  string
	DateOfBirth int `gogm:"name:dob"`
}

The above struct will be backed by a Node with properties name and dob

Mapped properties

Fields with a Map of string to valid property type are backed by a prefix, delmiter and keys in the map. Example:

type Person struct {
	gogm.Node
    Name  map[string]string
	DateOfBirth int `gogm:"name:dob"`
}

person.Name["first"] = "kevin"
person.Name["last"] = "little"
person.Name["other"] = "foo"


//Backed proprties:

name.first = "kevin"
name.last = "little"
name.other = "foo"

Use the name tag on the field to change the prefix

when working with temporal properties, use a pointer. Example:

    property *time.Time

Load and Save

Entities can be loaded with the Load method and saved with the Save method. Both method take options which can specify the depth of Load or Save. More docs to come

Custom queries

More docs to come

Persistence events

The package tests cases use events to keep track of time events such as; create, update, load and delete occurred. See the test package for usage. More docs to come on this.

Transactions

See test case TestTransactions on how to use trasactions. More docs to come