Closed fbiville closed 1 year ago
Example:
package users
// [...]
//go:generate go run github.com/neo4j/neo4j-go-driver/v5/cmd/mapper "Person"
type Person struct {
Labels []string `json:"labello" neo4j:"mapping_type=labels"`
ElementId string `neo4j:"mapping_type=element_id"`
Id int64 `neo4j:"mapping_type=id" json:"id_please"`
Name string `neo4j:"mapping_type=property,name=name"`
Props map[string]any `neo4j:"mapping_type=properties"`
Ignored bool `json:"-"`
}
The generated code looks like:
// Code generated by neo4j-mapper-gen DO NOT EDIT
package users
import "github.com/neo4j/neo4j-go-driver/v5/neo4j"
func MapPersonFromRecord(record *neo4j.Record) (*Person, error) {
value := record.Values[0]
result := &Person{}
result.Labels = value.(neo4j.Node).Labels
result.ElementId = value.(neo4j.Entity).GetElementId()
result.Id = value.(neo4j.Entity).GetId()
result.Name = value.(neo4j.Entity).GetProperties()["name"].(string)
result.Props = value.(neo4j.Entity).GetProperties()
return result, nil
}
Error handling is completely skipped here since this PR is only a POC.
Similar to #420, I ran a small benchmark on my machine against a local Neo4j instance (via Neo4j Desktop):
//go:generate go run github.com/neo4j/neo4j-go-driver/v5/cmd/mapper "APerson"
type APerson struct {
Labels []string `neo4j:"mapping_type=labels"`
Id int64 `neo4j:"mapping_type=id"`
BetterId string `neo4j:"mapping_type=element_id"`
Name string `neo4j:"mapping_type=property,name=name"`
}
func BenchmarkMapSingle(b *testing.B) {
ctx := context.Background()
auth := neo4j.BasicAuth("neo4j", "admin", "")
driver, err := neo4j.NewDriverWithContext("neo4j://localhost", auth)
if err != nil {
b.Fatal(err)
}
b.Cleanup(func() {
if err := driver.Close(ctx); err != nil {
b.Error(err)
}
})
session := driver.NewSession(ctx, neo4j.SessionConfig{})
b.Cleanup(func() {
if err := session.Close(ctx); err != nil {
b.Error(err)
}
})
b.ResetTimer()
for i := 0; i < b.N; i++ {
result, err := session.Run(ctx, "MATCH (p:Person) RETURN p LIMIT 1", nil)
if err != nil {
b.Error(err)
continue
}
record, err := result.Single(ctx)
if err != nil {
b.Error(err)
continue
}
_, err = MapAPersonFromRecord(record)
if err != nil {
b.Error(err)
}
}
}
The generated code looks as follows:
// Code generated by neo4j-mapper-gen DO NOT EDIT
package neo4j_test
import "github.com/neo4j/neo4j-go-driver/v5/neo4j"
func MapAPersonFromRecord(record *neo4j.Record) (*APerson, error) {
value := record.Values[0]
result := &APerson{}
result.Labels = value.(neo4j.Node).Labels
result.Id = value.(neo4j.Entity).GetId()
result.BetterId = value.(neo4j.Entity).GetElementId()
result.Name = value.(neo4j.Entity).GetProperties()["name"].(string)
return result, nil
}
goos: darwin
goarch: arm64
pkg: github.com/neo4j/neo4j-go-driver/v5/neo4j
BenchmarkMapSingle
BenchmarkMapSingle-10 4344 232505 ns/op
PASS
Note, this is much "quick'n'dirtier" than https://github.com/neo4j/neo4j-go-driver/pull/420.
Pros (compared to the other PR)
Cons
go generate
which must be explicitly invoked by the user