{"id":21658161,"url":"https://github.com/z5labs/gogm","last_synced_at":"2026-02-05T08:06:42.332Z","repository":{"id":38896937,"uuid":"194922072","full_name":"z5labs/gogm","owner":"z5labs","description":"Golang Object Graph Mapper for Neo4j","archived":false,"fork":false,"pushed_at":"2023-05-11T20:41:56.000Z","size":890,"stargazers_count":133,"open_issues_count":22,"forks_count":31,"subscribers_count":5,"default_branch":"master","last_synced_at":"2023-11-07T20:35:04.008Z","etag":null,"topics":["cli","cypher","edges","go","golang","graph-mapper","neo4j","ogm"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/z5labs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-07-02T19:20:00.000Z","updated_at":"2023-09-28T19:26:22.000Z","dependencies_parsed_at":"2023-02-09T09:32:18.933Z","dependency_job_id":null,"html_url":"https://github.com/z5labs/gogm","commit_stats":null,"previous_names":[],"tags_count":33,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/z5labs%2Fgogm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/z5labs%2Fgogm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/z5labs%2Fgogm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/z5labs%2Fgogm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/z5labs","download_url":"https://codeload.github.com/z5labs/gogm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226304424,"owners_count":17603588,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","cypher","edges","go","golang","graph-mapper","neo4j","ogm"],"created_at":"2024-11-25T09:28:48.386Z","updated_at":"2026-02-05T08:06:42.291Z","avatar_url":"https://github.com/z5labs.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"[![Go Report Card](https://goreportcard.com/badge/github.com/mindstand/gogm/v2)](https://goreportcard.com/report/github.com/mindstand/gogm/v2)\n[![Actions Status](https://github.com/mindstand/gogm/workflows/Go/badge.svg)](https://github.com/mindstand/gogm/actions)\n[![GoDoc](https://godoc.org/github.com/mindstand/gogm/v2?status.svg)](https://godoc.org/github.com/mindstand/gogm/v2)\n# GoGM Golang Object Graph Mapper v2\n\n## Installation\n```\ngo get github.com/mindstand/gogm/v2\n```\nNote: Do not use `-u` when installing. If you do, gogm will not compile.\n\nThis is caused by a dependency being updated to go1.18 making it incompatable with go1.17. In a future update, gogm will be updated to go1.18 eliminating this issue.\n\n## Features\n- Struct Mapping through the `gogm` struct decorator\n- Full support for ACID transactions\n- Underlying connection pooling\n- Support for HA Casual Clusters using `bolt+routing` through the [Official Neo4j Go Driver](https://github.com/neo4j/neo4j-go-driver)\n- Custom queries in addition to built in functionality\n- Builder pattern cypher queries using [MindStand's cypher dsl package](https://github.com/mindstand/go-cypherdsl)\n- CLI to generate link and unlink functions for gogm structs.\n- Multi database support with Neo4j v4\n\n## What's new in V2\n- GoGM is an object now! This means you can have multiple instances of GoGM at a time\n- OpenTracing and Context Support\n- Driver has been updated from v1.6 to v4\n- Log interface, so anyone can use the logger of their choice instead of being forced to use logrus\n- Primary Key strategies to use any type of primary key. GoGM is no longer UUID only!\n- TLS now supported\n\n| Note: GoGM v1 has been deprecated.\n\n## Usage\n\n### Primary Key Strategy\nPrimary key strategies allow more customization over primary keys. A strategy is provided to gogm on initialization.\n\u003cbr/\u003e\nBuilt in primary key strategies are:\n- `gogm.DefaultPrimaryKeyStrategy` -- just use the graph id from neo4j as the primary key\n- `gogm.UUIDPrimaryKeyStrategy` -- uuid's as primary keys\n```go\n// Example of the internal UUID strategy\nPrimaryKeyStrategy{\n\t// StrategyName is the name to reference the strategy\n    StrategyName: \"UUID\",\n    // DBName is the name of the field in the database\n    DBName:       \"uuid\",\n    // FieldName is the name of the field in go, this will validate to make sure all pk's use the same field name\n    FieldName:    \"UUID\",\n    // Type is the reflect type of the primary key, in this case it's a string but it can be any primitive\n    Type:         reflect.TypeOf(\"\"),\n    // GenIDFunc defines how new ids are generated, in this case we're using googles uuid library\n    GenIDFunc: func() (id interface{}) {\n        return uuid.New().String()\n    },\n}\n```\n\n### Load Strategy\nLoad strategies allow control over the queries generated by `Load` operations.\nDifferent strategies change the size of the queries sent to the database as well as the amount of work the database has to do.\nA load strategy is provided to gomg on initialization.\n\nThe defined load strategies are:\n- `gogm.PATH_LOAD_STRATEGY` -- Use cypher path queries to generate simple queries for load operations.\n- `gogm.SCHEMA_LOAD_STRATEGY` -- Leverage the GoGM schema to generate more complex queries for load operations which results in less work for the database.\n\nDepending on your use case, `PATH_LOAD_STRATEGY` may result in higher latency.\n\n### Struct Configuration\n##### \u003cs\u003etext\u003c/s\u003e notates deprecation\n\nDecorators that can be used\n- `name=\u003cname\u003e` -- used to set the field name that will show up in neo4j.\n- `relationship=\u003cedge_name\u003e` -- used to set the name of the edge on that field.\n- `direction=\u003cINCOMING|OUTGOING|BOTH|NONE\u003e` -- used to specify direction of that edge field.\n- `index` -- marks field to have an index applied to it.\n- `unique` -- marks field to have unique constraint.\n- `pk=\u003cstrategy_name\u003e` -- marks field as a primary key and specifies which pk strategy to use. Can only have one pk, composite pk's are not supported.\n- `properties` -- marks that field is using a map. GoGM only supports properties fields of `map[string]interface{}`, `map[string]\u003cprimitive\u003e`, `map[string][]\u003cprimitive\u003e` and `[]\u003cprimitive\u003e`\n- `-` -- marks that field will be ignored by the ogm\n\n#### Not on relationship member variables\nAll relationships must be defined as either a pointer to a struct or a slice of struct pointers `*SomeStruct` or `[]*SomeStruct`\n\nUse `;` as delimiter between decorator tags.\n\nEx.\n\n```go\ntype TdString string\n\ntype MyNeo4jObject struct {\n  // provides required node field\n  // use gogm.BaseUUIDNode if you want to use UUIDs\n  gogm.BaseNode\n\n  Field string `gogm:\"name=field\"`\n  Props map[string]interface{} `gogm:\"properties;name=props\"` //note that this would show up as `props.\u003ckey\u003e` in neo4j\n  IgnoreMe bool `gogm=\"-\"`\n  UniqueTypeDef TdString `gogm:\"name=unique_type_def\"`\n  Relation *SomeOtherStruct `gogm=\"relationship=SOME_STRUCT;direction=OUTGOING\"`\n  ManyRelation []*SomeStruct `gogm=\"relationship=MANY;direction=INCOMING\"`\n}\n\n```\n\n### GOGM Usage\n- Edges must implement the [Edge interface](https://github.com/mindstand/gogm/blob/master/interface.go#L28). View the complete example [here](https://github.com/mindstand/gogm/blob/master/examples/example.go). \n```go\npackage main\n\nimport (\n\t\"github.com/mindstand/gogm/v2\"\n\t\"time\"\n)\n\ntype tdString string\ntype tdInt int\n\n//structs for the example (can also be found in decoder_test.go)\ntype VertexA struct {\n\t// provides required node fields\n\tgogm.BaseNode\n\n    TestField         string                `gogm:\"name=test_field\"`\n\tTestTypeDefString tdString          `gogm:\"name=test_type_def_string\"`\n\tTestTypeDefInt    tdInt             `gogm:\"name=test_type_def_int\"`\n\tMapProperty       map[string]string `gogm:\"name=map_property;properties\"`\n\tSliceProperty     []string          `gogm:\"name=slice_property;properties\"`\n    SingleA           *VertexB          `gogm:\"direction=incoming;relationship=test_rel\"`\n\tManyA             []*VertexB        `gogm:\"direction=incoming;relationship=testm2o\"`\n\tMultiA            []*VertexB        `gogm:\"direction=incoming;relationship=multib\"`\n\tSingleSpecA       *EdgeC            `gogm:\"direction=outgoing;relationship=special_single\"`\n\tMultiSpecA        []*EdgeC          `gogm:\"direction=outgoing;relationship=special_multi\"`\n}\n\ntype VertexB struct {\n\t// provides required node fields\n\tgogm.BaseNode\n\n\tTestField  string     `gogm:\"name=test_field\"`\n\tTestTime   time.Time  `gogm:\"name=test_time\"`\n\tSingle     *VertexA   `gogm:\"direction=outgoing;relationship=test_rel\"`\n\tManyB      *VertexA   `gogm:\"direction=outgoing;relationship=testm2o\"`\n\tMulti      []*VertexA `gogm:\"direction=outgoing;relationship=multib\"`\n\tSingleSpec *EdgeC     `gogm:\"direction=incoming;relationship=special_single\"`\n\tMultiSpec  []*EdgeC   `gogm:\"direction=incoming;relationship=special_multi\"`\n}\n\ntype EdgeC struct {\n\t// provides required node fields\n\tgogm.BaseNode\n\n\tStart *VertexA\n\tEnd   *VertexB\n\tTest  string `gogm:\"name=test\"`\n}\n\nfunc main() {\n\t// define your configuration\n\tconfig := gogm.Config{\n\t\tHost:                      \"0.0.0.0\",\n\t\tPort:                      7687,\n\t\t// deprecated in favor of protocol\n\t    // IsCluster:                 false,\n\t    Protocol:                  \"neo4j\", //also supports neo4j+s, neo4j+ssc, bolt, bolt+s and bolt+ssc\n\t    // Specify CA Public Key when using +ssc or +s\n\t    CAFileLocation: \"my-ca-public.crt\",\n\t\tUsername:                  \"neo4j\",\n\t\tPassword:                  \"password\",\n\t\tPoolSize:                  50,\n\t\tIndexStrategy:             gogm.VALIDATE_INDEX, //other options are ASSERT_INDEX and IGNORE_INDEX\n\t\tTargetDbs:                 nil,\n\t\t// default logger wraps the go \"log\" package, implement the Logger interface from gogm to use your own logger\n\t\tLogger:             gogm.GetDefaultLogger(),\n\t\t// define the log level\n\t\tLogLevel:           \"DEBUG\",\n\t\t// enable neo4j go driver to log\n\t\tEnableDriverLogs:   false,\n\t\t// enable gogm to log params in cypher queries. WARNING THIS IS A SECURITY RISK! Only use this when debugging\n\t\tEnableLogParams:    false,\n\t\t// enable open tracing. Ensure contexts have spans already. GoGM does not make root spans, only child spans\n\t\tOpentracingEnabled: false,\n\t\t// specify the method gogm will use to generate Load queries\n\t\tLoadStrategy: gogm.PATH_LOAD_STRATEGY // set to SCHEMA_LOAD_STRATEGY for schema-aware queries which may reduce load on the database\n\t}\n\n\t// register all vertices and edges\n\t// this is so that GoGM doesn't have to do reflect processing of each edge in real time\n\t// use nil or gogm.DefaultPrimaryKeyStrategy if you only want graph ids\n\t// we are using the default key strategy since our vertices are using BaseNode\n\t_gogm, err := gogm.New(\u0026config, gogm.DefaultPrimaryKeyStrategy, \u0026VertexA{}, \u0026VertexB{}, \u0026EdgeC{})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t//param is readonly, we're going to make stuff so we're going to do read write\n\tsess, err := _gogm.NewSessionV2(gogm.SessionConfig{AccessMode: gogm.AccessModeWrite})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t//close the session\n\tdefer sess.Close()\n\n\taVal := \u0026VertexA{\n\t\tTestField: \"woo neo4j\",\n\t}\n\n\tbVal := \u0026VertexB{\n\t\tTestTime: time.Now().UTC(),\n\t}\n\n\t//set bi directional pointer\n\tbVal.Single = aVal\n\taVal.SingleA = bVal\n\n\terr = sess.SaveDepth(context.Background(), aVal, 2)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t//load the object we just made (save will set the uuid)\n\tvar readin VertexA\n\terr = sess.Load(context.Background(), \u0026readin, aVal.UUID)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Printf(\"%+v\", readin)\n}\n\n\n```\n\n## Migrating from V1 to V2\n\n### Initialization\nInitialization in gogm v1\n```go\nconfig := gogm.Config{\n    IndexStrategy: gogm.VALIDATE_INDEX, //other options are ASSERT_INDEX and IGNORE_INDEX\n    PoolSize:      50,\n    Port:          7687,\n    IsCluster:     false, //tells it whether or not to use `bolt+routing`\n    Host:          \"0.0.0.0\",\n    Password:      \"password\",\n    Username:      \"neo4j\",\n}\n\nerr := gogm.Init(\u0026config, \u0026VertexA{}, \u0026VertexB{}, \u0026EdgeC{})\nif err != nil {\n    panic(err)\n}\n```\n\nEquivalent in GoGM v2\n```go\n// define your configuration\nconfig := gogm.Config{\n    IndexStrategy: gogm.VALIDATE_INDEX, //other options are ASSERT_INDEX and IGNORE_INDEX\n    PoolSize:      50,\n    Port:          7687,\n    IsCluster:     false, //tells it whether or not to use `bolt+routing`\n    Host:          \"0.0.0.0\",\n    Password:      \"password\",\n    Username:      \"neo4j\",\n}\n\n\t// register all vertices and edges\n\t// this is so that GoGM doesn't have to do reflect processing of each edge in real time\n\t// use nil or gogm.DefaultPrimaryKeyStrategy if you only want graph ids\n\t_gogm, err := gogm.New(\u0026config, gogm.UUIDPrimaryKeyStrategy, \u0026VertexA{}, \u0026VertexB{}, \u0026EdgeC{})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\t\n\tgogm.SetGlobalGoGM(_gogm)\n```\n\n\n##### Note that we call gogm.SetGloablGogm so that we can still access it from a package level\n\n### Create a session\nCreating a session in GoGM v1\n```go\nsess, err := gogm.NewSession(false)\n```\n##### Note this still works in v2, its using the global gogm to create the session. Also note this is making an instance of the deprecated `ISession`\nEquivalent in GoGM v2\n```go\n// this would also work with a local instance of gogm (localGogm.NewSessionV2)\nsess, err := gogm.G().NewSessionV2(gogm.SessionConfig{AccessMode: gogm.AccessModeWrite})\n```\n\n### Summary\n- Minimal change requires creating a global gogm, everything else should still work with ISession (gogm v1 session object)\n- `ISession` is now deprecated but still supported\n- SessionV2 is the new standard\n### GoGM CLI\n\n## CLI Installation\n```\ngo get -u github.com/mindstand/gogm/v2/cmd/gogmcli\n```\n\n## CLI Usage\n```\nNAME:\n   gogmcli - used for neo4j operations from gogm schema\n\nUSAGE:\n   gogmcli [global options] command [command options] [arguments...]\n\nVERSION:\n   2.1.1\n\nCOMMANDS:\n   generate, g, gen  to generate link and unlink functions for nodes\n   help, h           Shows a list of commands or help for one command\n\nGLOBAL OPTIONS:\n   --debug, -d    execute in debug mode (default: false)\n   --help, -h     show help (default: false)\n   --version, -v  print the version (default: false)\n```\n\n## Inspiration\nInspiration came from the Java OGM implementation by Neo4j.\n\n## Road Map\n- Schema Migration\n- Errors overhaul using go 1.13 error wrapping\n\n## How you can help\n- Report Bugs\n- Fix bugs\n- Contribute (refer to contribute.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fz5labs%2Fgogm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fz5labs%2Fgogm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fz5labs%2Fgogm/lists"}