gremlin

package module
v1.0.11 Latest Latest
Warning

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

Go to latest
Published: Jan 10, 2020 License: MIT Imports: 20 Imported by: 0

README

Gremlin Server Client for Go

This library will allow you to connect to any graph database that supports TinkerPop3 using Go. This includes databases like JanusGraph and Neo4J. TinkerPop3 uses Gremlin Server to communicate with clients using either WebSockets or REST API. This library talks to Gremlin Server using WebSockets.

This library developed by the engineering department at CB Insights

Table of Contents

  1. Installation
  2. Usage
    1. Gremlin Stack
      1. Creating the Gremlin Stack
      2. Stack Options
    2. Querying the Database
    3. Reading the Response
    4. Locking
      1. Local Lock
      2. Consul Lock
      3. Consul Combination Lock
    5. Authentication
    6. Limitations
  3. Go-Gremlin Usage Notes

Installation

go get github.com/cbinsights/gremlin

Usage

Gremlin Stack

Using the Gremlin Stack allows you to include a number of features on top of the Websocket that connects to your Gremlin server:

  1. Connection Pooling & maintenance to keep connections alive.

  2. Query re-trying.

  3. Optional tracing, logging and instrumentation features to your Gremlin queries.

  4. Locking features designed to handle concurrent modification

The stack sits on top of a pool of connections to Gremlin, which wrap the Websocket connections defined by "github.com/gorilla/websocket"

Creating the Gremlin Stack

You can instantiate it using NewGremlinStack or NewGremlinStackSimple (which excludes tracing, logging, instrumentation and the non-local locking mechanism):

	gremlinServer := "ws://server1:8182/gremlin"
	maxPoolCapacity := 10
	maxRetries := 3
	verboseLogging := true
	pingInterval := 5

	myStack, err := gremlin.NewGremlinStackSimple(gremlinServer, maxPoolCapacity, maxRetries, verboseLogging, pingInterval)
	if err != nil {
		// handle error here
	}

Note: The arguments for NewGremlinStack perform the following functions:

  • maxPoolCapacity sets the number connections to keep in the pool

  • maxRetries sets the number of retries to use on a connection before trying another

  • verboseLogging denotes the verbosity of logs received from your gremlin server

  • pingInterval denotes how often (in seconds) the gremlin pool should refresh itself

    • This keeps the Websocket connections alive; otherwise, if left inactive, they will close
Stack Options

In addition to the NewGremlinStackSimple, you can call a stack that includes tracing, logging, instrumentation and locking elements, using a helper struct: GremlinStackOptions:

The struct is defined as below:

	type GremlinStackOptions struct {
		MaxCap         int
		MaxRetries     int
		VerboseLogging bool
		PingInterval   int
		Logger         Logger_i
		Tracer         opentracing.Tracer
		Instr          InstrumentationProvider_i
		LockClient     lock.LockClient_i
	}

Note that any of MaxCap, MaxRetries, VerboseLogging and PingInterval left nil will be set to defaults.

If the LockClient is nil, it will default to using the LocalLockClient.

Logger, Tracer and Instr are ignored if nil.

Querying the Database

To query the database, using your stack, call ExecQueryF(), which requires a Context.context object:


	ctx, _ := context.WithCancel(context.Background())
	query := g.V("vertexID")
	response, err := myStack.ExecQueryF(ctx, query)
	if err != nil {
		// handle error here
	}

Optionally, you may parameterize the query and pass arguments into ExecQueryF():

	var args []interface{
		"vertexID",
		"10"
	}
	query := "g.V().hasLabel("%s").limit(%d)"
	response, err := myStack.ExecQueryF(ctx, query)
	if err != nil {
		// handle error here
	}

The gremlin client will handle the interpolation of the query, and escaping any characters that might be necessary.

Reading the Response

ExecQueryF() will return the string response returned by your Gremlin instance, which may look something like this:

	[
	  {
	    "@type": "g:Vertex",
	    "@value": {
	      "id": "test-id",
	      "label": "label",
	      "properties": {
	        "health": [
	          {
	            "@type": "g:VertexProperty",
	            "@value": {
	              "id": {
	                "@type": "Type",
	                "@value": 1
	              },
	              "value": "1",
	              "label": "health"
	            }
	          }
	        ]
	      }
	    }
	  }
	]

This library provides a few helpers to serialize this response into Go structs. There are specific helpers for serializing a list of vertexes and for a list of edges, and there is additionally a generic vertex that serializes the response into a struct with a type & a value interface{}.

SerializeVertexes() would turn the response above into the following, which is considerably easier to manipulate:

	Vertex{
		Type: "g:Vertex",
		Value: VertexValue{
			ID:    "test-id",
			Label: "label",
			Properties: map[string][]VertexProperty{
				"health": []VertexProperty{
					VertexProperty{
						Type: "g:VertexProperty",
						Value: VertexPropertyValue{
							ID: GenericValue{
								Type:  "Type",
								Value: 1,
							},
							Value: "1",
							Label: "health",
						},
					},
				},
			},
		},
	}

In addition, there are provided utilities to convert to "CleanVertexes" and "CleanEdges."

ConvertToCleanVertexes() converts a Vertex object as seen above into a much simpler CleanVertex with only an ID and a Label ConvertToCleanEdges() converts an Edge object as seen above into a much simpler CleanEdge with only an ID and a Label

Locking

The Gremlin client is designed to accept a LockClient interface, with a client that implements a LockKey(key string) function to retrieve a Lock from the client.

The Lock interface implements 3 functions:

  • Lock() which locks the corresponding key. If another Lock has locked the key, then the Lock will wait until the key is free.
  • Unlock() which unlocks the corresponding key.
  • Destroy() which removes the corresponding key from the client store.

In addition to the generic interface, two implementations have been provided, a local implementation and one for Consul.

Local Lock

The local lock uses a Cache of Mutexes (from go-cache, so that for a given LocalKey passed in by the query, the Mutex will lock writes on that key. For instance, if we are operating on a Vertex and expect simultaneous writes to that Vertex's properties, we can lock the Mutex corresponding to the Vertex ID to avoid a ConcurrentModificationException.

However, this system only works for a single client, so a distributed system, or a system with multiple writer clients will still be at risk of concurrency exceptions.

Consul Lock

The Consul lock uses the Consul API to prevent ConcurrentModificationExceptions. Similar to the Local Lock, we can pass in a Vertex ID to avoid a ConcurrentModificationException. But, instead of writing to a local Map, it writes to Consul's KV configs, acquiring and releasing the corresponding configs as necessary, with a timeout to ensure that operations running too long, or operations that have been cancelled, do not retain their lock on the key.

For more information about Consul Distributed Key implementations, check the Consul API docs and this quick implementation guide

Consul Combination Lock

The Consul Combination lock is a union of both the Local and Consul Locks, designed to handle the speed issues inherent in polling Consul.

Like the local lock, it implements a

Authentication

For authentication, you can set environment variables GREMLIN_USER and GREMLIN_PASS and create a Client, passing functional parameter OptAuthEnv

	auth := gremlin.OptAuthEnv()
	myStack, err := gremlin.NewGremlinStackSimple("ws://server1:8182/gremlin", maxPoolCapacity, maxRetries, verboseLogging, auth)
	data, err = client.ExecQueryF(`g.V()`)
	if err != nil {
		panic(err)
	}
	doStuffWith(data)

If you don't like environment variables you can authenticate passing username and password string in the following way:

	auth := gremlin.OptAuthUserPass("myusername", "mypass")
	myStack, err := gremlin.NewGremlinStackSimple("ws://server1:8182/gremlin", maxPoolCapacity, maxRetries, verboseLogging, auth)
	data, err = client.ExecQueryF(`g.V()`)
	if err != nil {
		panic(err)
	}
	doStuffWith(data)

Limitations

The Gremlin client forces some restraints on the characters allowed in a gremlin query to avoid issues with the query syntax and the database.

Currently only characters that fall under 'Other' code points are excluded.

These include invisible control characters, invisible formatting indicators, private and unassigned code points, and halves of UTF-16 surrogate pairs.

For more information on these code points, check out the descriptions of Unicode Character Categories and their Regex Definitions.

Go-Gremlin Usage Notes

Note: This is the usage defined by the library from which this is forked (github.com/go-gremlin/gremlin) Export the list of databases you want to connect to as GREMLIN_SERVERS like so:-

export GREMLIN_SERVERS="ws://server1:8182/gremlin, ws://server2:8182/gremlin"

Import the library eg import "github.com/go-gremlin/gremlin".

Parse and save your cluster of services. You only need to do this once before submitting any queries (Perhaps in main()):-

	if err := gremlin.NewCluster(); err != nil {
		// handle error here
	}

Instead of using an environment variable, you can also pass the servers directly to NewCluster(). This is more convenient in development. For example:-

	if err := gremlin.NewCluster("ws://dev.local:8182/gremlin", "ws://staging.local:8182/gremlin"); err != nil {
		// handle error
	}

To actually run queries against the database, make sure the package is imported and issue a gremlin query like this:-

	data, err := gremlin.Query(`g.V()`).Exec()
	if err != nil  {
		// handle error
	}

data is a JSON array in bytes []byte if any data is returned otherwise it is nil. For example you can print it using:-

	fmt.Println(string(data))

or unmarshal it as desired.

You can also execute a query with bindings like this:-

	data, err := gremlin.Query(`g.V().has("name", userName).valueMap()`).Bindings(gremlin.Bind{"userName": "john"}).Exec()

You can also execute a query with Session, Transaction and Aliases

	aliases := make(map[string]string)
	aliases["g"] = fmt.Sprintf("%s.g", "demo-graph")
	session := "de131c80-84c0-417f-abdf-29ad781a7d04"  //use UUID generator
	data, err := gremlin.Query(`g.V().has("name", userName).valueMap()`).Bindings(gremlin.Bind{"userName": "john"}).Session(session).ManageTransaction(true).SetProcessor("session").Aliases(aliases).Exec()

Documentation

Index

Constants

View Source
const (

	// Gremlin client does not allow Other characters
	ARG_REGEX = "\\p{C}+"

	// Gremlin stack defaults
	DEFAULT_MAX_CAP             = 10
	DEFAULT_MAX_GREMLIN_RETRIES = 2
	DEFAULT_VERBOSE_LOGGING     = false
	DEFAULT_PING_INTERVAL       = 5
)
View Source
const (
	StatusSuccess                  = 200
	StatusNoContent                = 204
	StatusPartialContent           = 206
	StatusUnauthorized             = 401
	StatusAuthenticate             = 407
	StatusMalformedRequest         = 498
	StatusInvalidRequestArguments  = 499
	StatusServerError              = 500
	StatusScriptEvaluationError    = 597
	StatusServerTimeout            = 598
	StatusServerSerializationError = 599
)

Variables

View Source
var ESCAPE_CHARS_GREMLIN = CharSliceToMap([]rune{
	singleQuote,
	backslash,
	pctSymbol,
	doubleQuote,
})
View Source
var ErrClosed = errors.New("pool is closed")
View Source
var ErrorMsg = map[int]string{
	StatusUnauthorized:             "Unauthorized",
	StatusAuthenticate:             "Authenticate",
	StatusMalformedRequest:         "Malformed Request",
	StatusInvalidRequestArguments:  "Invalid Request Arguments",
	StatusServerError:              "Server Error",
	StatusScriptEvaluationError:    "Script Evaluation Error",
	StatusServerTimeout:            "Server Timeout",
	StatusServerSerializationError: "Server Serialization Error",
}

Functions

func CharSliceToMap

func CharSliceToMap(chars []rune) map[rune]bool

func CoalesceStrings

func CoalesceStrings(s ...string) string

func ContextWithOpName

func ContextWithOpName(ctx context.Context, name string) context.Context

func CreateConnection

func CreateConnection() (conn net.Conn, server *url.URL, err error)

func EdgesMatch

func EdgesMatch(edge1, edge2 Edge) bool

func EmptyTags

func EmptyTags() []string

func EscapeGremlin

func EscapeGremlin(value string) string

func GenericValuesMatch

func GenericValuesMatch(gv1, gv2 GenericValue) bool

func GraphSONSerializer

func GraphSONSerializer(req *Request) ([]byte, error)

func InterfaceToString

func InterfaceToString(i interface{}) string

func InterfacesMatch

func InterfacesMatch(interface1, interface2 interface{}) bool

func MakeGremlinQuery

func MakeGremlinQuery(gremlinQuery GremlinQuery, argRegexP *regexp.Regexp) (string, error)

func NewCluster

func NewCluster(s ...string) (err error)

func OpNameFromContext

func OpNameFromContext(ctx context.Context) string

func PrepareArgs

func PrepareArgs(args []interface{}, escapeFn func(string) string) []interface{}

func SerializeListInterface

func SerializeListInterface(rawResponse string) ([]interface{}, error)

func SplitServers

func SplitServers(connString string) (servers []*url.URL, err error)

func StartSpanFromParent

func StartSpanFromParent(ctx context.Context, tracer opentracing.Tracer, method string, opts ...opentracing.StartSpanOption) (opentracing.Span, context.Context)

func VertexesMatch

func VertexesMatch(vertex1, vertex2 Vertex) bool

Types

type AuthInfo

type AuthInfo struct {
	ChallengeId string
	User        string
	Pass        string
}

AuthInfo includes all info related with SASL authentication with the Gremlin server ChallengeId is the requestID in the 407 status (AUTHENTICATE) response given by the server. We have to send an authentication request with that same RequestID in order to solve the challenge.

func NewAuthInfo

func NewAuthInfo(options ...OptAuth) (*AuthInfo, error)

Constructor for different authentication possibilities

type Bind

type Bind map[string]interface{}

type CleanEdge

type CleanEdge struct {
	Source string `json:"source"`
	Target string `json:"target"`
}

func ConvertToCleanEdges

func ConvertToCleanEdges(edges Edges) []CleanEdge

type CleanResponse

type CleanResponse struct {
	V []CleanVertex
	E []CleanEdge
}

type CleanVertex

type CleanVertex struct {
	Id    int    `json:"id"`
	Label string `json:"label"`
}

func ConvertToCleanVertexes

func ConvertToCleanVertexes(vertexes Vertexes) []CleanVertex

type EdIdType added in v1.0.7

type EdIdType struct {
	Type  string          `json:"@type"`
	Value EdgeIdValueType `json:"@value"`
}

type Edge

type Edge struct {
	Type  string    `json:"@type"`
	Value EdgeValue `json:"@value"`
}

func MakeDummyEdge

func MakeDummyEdge(edgeID, edgeLabel, inVLabel, outVLabel, inV, outV string, params map[string]interface{}) Edge

type EdgeIdValueType added in v1.0.7

type EdgeIdValueType struct {
	RelationId string
}

type EdgeProperty

type EdgeProperty struct {
	Type  string            `json:"@type"`
	Value EdgePropertyValue `json:"@value"`
}

func MakeDummyProperty

func MakeDummyProperty(label string, value interface{}) EdgeProperty

type EdgePropertyValue

type EdgePropertyValue struct {
	Label string      `json:"key"`
	Value interface{} `json:"value"`
}

type EdgeV2 added in v1.0.8

type EdgeV2 struct {
	Type  string      `json:"@type"`
	Value EdgeValueV2 `json:"@value"`
}

type EdgeValue

type EdgeValue struct {
	ID         string // TODO: does this need to be a GenericValue? interface{}?
	Label      string
	InVLabel   string
	OutVLabel  string
	InV        string
	OutV       string
	Properties map[string]EdgeProperty
}

type EdgeValueType added in v1.0.10

type EdgeValueType struct {
	Type  string `json:"@type"`
	Value int64  `json:"@value"`
}

type EdgeValueV2 added in v1.0.7

type EdgeValueV2 struct {
	ID         EdIdType
	Label      string
	InVLabel   string
	OutVLabel  string
	InV        EdgeValueType
	OutV       EdgeValueType
	Properties map[string]EdgeProperty
}

type Edges

type Edges []Edge

func DeserializeEdges added in v1.0.8

func DeserializeEdges(rawResponse string) (Edges, error)

type EdgesV2 added in v1.0.8

type EdgesV2 []EdgeV2

func DeserializeEdgesV2 added in v1.0.8

func DeserializeEdgesV2(rawResponse string) (EdgesV2, error)

type FormattedReq

type FormattedReq struct {
	Op        string       `json:"op"`
	RequestId interface{}  `json:"requestId"`
	Args      *RequestArgs `json:"args"`
	Processor string       `json:"processor"`
}

Formats the requests in the appropriate way

func NewFormattedReq

func NewFormattedReq(req *Request) FormattedReq

type GenericValue

type GenericValue struct {
	Type  string      `json:"@type"`
	Value interface{} `json:"@value"`
}

func MakeDummyGenericValue

func MakeDummyGenericValue(gvType string, value interface{}) GenericValue

func (GenericValue) Equals

func (g1 GenericValue) Equals(g2 GenericValue) bool

type GenericValues

type GenericValues []GenericValue

func SerializeGenericValues

func SerializeGenericValues(rawResponse string) (GenericValues, error)

type GoGremlin

type GoGremlin interface {
	ExecQuery(query string) ([]byte, error)
	Close() error
	Reconnect(urlStr string) error
	MaintainConnection(urlStr string) error
}

type GremlinClient

type GremlinClient struct {
	LockClient lock.LockClient_i
	// contains filtered or unexported fields
}

func NewGremlinClient

func NewGremlinClient(urlStr string, maxCap int, maxRetries int, verboseLogging bool, lockClient lock.LockClient_i, options ...OptAuth) (*GremlinClient, error)

func (*GremlinClient) Close

func (c *GremlinClient) Close(ctx context.Context) error

func (*GremlinClient) ExecQueryF

func (c *GremlinClient) ExecQueryF(ctx context.Context, gremlinQuery GremlinQuery) (string, error)

func (*GremlinClient) StartMonitor

func (c *GremlinClient) StartMonitor(ctx context.Context, interval time.Duration) error

type GremlinConnection

type GremlinConnection struct {
	Remote         *url.URL
	Ws             *websocket.Conn
	Auth           []OptAuth
	VerboseLogging bool
}

GremlinConnections include the necessary info to connect to the server and the underlying socket

func NewGremlinConnection

func NewGremlinConnection(urlStr string, options ...OptAuth) (*GremlinConnection, error)

func NewVerboseGremlinConnection

func NewVerboseGremlinConnection(urlStr string, verboseLogging bool, options ...OptAuth) (*GremlinConnection, error)

func (*GremlinConnection) Authenticate

func (c *GremlinConnection) Authenticate(requestId string) ([]byte, error)

Authenticates the connection

func (*GremlinConnection) Close

func (c *GremlinConnection) Close() error

func (*GremlinConnection) Exec

func (c *GremlinConnection) Exec(req *Request) ([]byte, error)

func (*GremlinConnection) ExecQuery

func (c *GremlinConnection) ExecQuery(query string) ([]byte, error)

GremlinConnection executes the provided request

func (*GremlinConnection) MaintainConnection

func (c *GremlinConnection) MaintainConnection(urlStr string) error

Send a dummy query to neptune If there is a network error, attempt to reconnect

func (*GremlinConnection) ReadResponse

func (c *GremlinConnection) ReadResponse() (data []byte, err error)

func (*GremlinConnection) Reconnect

func (c *GremlinConnection) Reconnect(urlStr string) error

func (*GremlinConnection) SetLogVerbosity

func (c *GremlinConnection) SetLogVerbosity(verboseLogging bool)

type GremlinInstr

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

func NewGremlinInstr

func NewGremlinInstr(next Gremlin_i, instr InstrumentationProvider_i) GremlinInstr

func (GremlinInstr) Close

func (g GremlinInstr) Close(ctx context.Context) (err error)

func (GremlinInstr) ExecQueryF

func (g GremlinInstr) ExecQueryF(ctx context.Context, gremlinQuery GremlinQuery) (response string, err error)

func (GremlinInstr) StartMonitor

func (g GremlinInstr) StartMonitor(ctx context.Context, interval time.Duration) (err error)

type GremlinLogger

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

func NewGremlinLogger

func NewGremlinLogger(next Gremlin_i, logger Logger_i) GremlinLogger

func (GremlinLogger) Close

func (g GremlinLogger) Close(ctx context.Context) (err error)

func (GremlinLogger) ExecQueryF

func (g GremlinLogger) ExecQueryF(ctx context.Context, gremlinQuery GremlinQuery) (response string, err error)

func (GremlinLogger) StartMonitor

func (g GremlinLogger) StartMonitor(ctx context.Context, interval time.Duration) (err error)

type GremlinQuery

type GremlinQuery struct {
	Query   string
	Args    []interface{}
	LockKey string
}

type GremlinResponse

type GremlinResponse struct {
	V VertexesV2
	E Edges
}

cbi made up, not a real graphson or gremlin thing

type GremlinStackOptions

type GremlinStackOptions struct {
	MaxCap         int
	MaxRetries     int
	VerboseLogging bool
	PingInterval   int
	Logger         Logger_i
	Tracer         opentracing.Tracer
	Instr          InstrumentationProvider_i
	LockClient     lock.LockClient_i
}

type GremlinTracer

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

func NewGremlinTracer

func NewGremlinTracer(next Gremlin_i, tracer opentracing.Tracer) GremlinTracer

func (GremlinTracer) Close

func (g GremlinTracer) Close(ctx context.Context) (err error)

func (GremlinTracer) ExecQueryF

func (g GremlinTracer) ExecQueryF(ctx context.Context, gremlinQuery GremlinQuery) (response string, err error)

func (GremlinTracer) StartMonitor

func (g GremlinTracer) StartMonitor(ctx context.Context, interval time.Duration) (err error)

type Gremlin_i

type Gremlin_i interface {
	ExecQueryF(ctx context.Context, gremlinQuery GremlinQuery) (response string, err error)
	StartMonitor(ctx context.Context, interval time.Duration) (err error)
	Close(ctx context.Context) (err error)
}

func NewGremlinStack

func NewGremlinStack(urlStr string, gremlinStackOptions GremlinStackOptions, authOptions ...OptAuth) (Gremlin_i, error)

func NewGremlinStackSimple

func NewGremlinStackSimple(urlStr string, maxCap int, maxRetries int, verboseLogging bool, pingInterval int, options ...OptAuth) (Gremlin_i, error)

type IdType added in v1.0.4

type IdType IdTypeStruct

type IdTypeStruct added in v1.0.4

type IdTypeStruct struct {
	Type  string `json:"@type"`
	Value int    `json:"@value"`
}

type InstrumentationProvider_i

type InstrumentationProvider_i interface {
	Incr(name string, tags []string, rate float64) error
}

type Logger_i

type Logger_i interface {
	Log(keyvals ...interface{}) error
}

type OptAuth

type OptAuth func(*AuthInfo) error

func OptAuthEnv

func OptAuthEnv() OptAuth

Sets authentication info from environment variables GREMLIN_USER and GREMLIN_PASS

func OptAuthUserPass

func OptAuthUserPass(user, pass string) OptAuth

Sets authentication information from username and password

type Request

type Request struct {
	RequestId string       `json:"requestId"`
	Op        string       `json:"op"`
	Processor string       `json:"processor"`
	Args      *RequestArgs `json:"args"`
}

func Query

func Query(query string) (*Request, error)

func (*Request) Aliases

func (req *Request) Aliases(aliases map[string]string) *Request

func (*Request) Bindings

func (req *Request) Bindings(bindings Bind) *Request

func (*Request) ManageTransaction

func (req *Request) ManageTransaction(flag bool) *Request

func (*Request) Session

func (req *Request) Session(session string) *Request

func (*Request) SetProcessor

func (req *Request) SetProcessor(processor string) *Request

type RequestArgs

type RequestArgs struct {
	Gremlin           string            `json:"gremlin,omitempty"`
	Session           string            `json:"session,omitempty"`
	Bindings          Bind              `json:"bindings,omitempty"`
	Language          string            `json:"language,omitempty"`
	Rebindings        Bind              `json:"rebindings,omitempty"`
	Sasl              string            `json:"sasl,omitempty"`
	BatchSize         int               `json:"batchSize,omitempty"`
	ManageTransaction bool              `json:"manageTransaction,omitempty"`
	Aliases           map[string]string `json:"aliases,omitempty"`
}

type Response

type Response struct {
	RequestId string          `json:"requestId"`
	Status    *ResponseStatus `json:"status"`
	Result    *ResponseResult `json:"result"`
}

func (Response) String

func (r Response) String() string

Implementation of the stringer interface. Useful for exploration

type ResponseResult

type ResponseResult struct {
	Data json.RawMessage        `json:"data"`
	Meta map[string]interface{} `json:"meta"`
}

type ResponseStatus

type ResponseStatus struct {
	Code       int                    `json:"code"`
	Attributes map[string]interface{} `json:"attributes"`
	Message    string                 `json:"message"`
}

type Vertex

type Vertex struct {
	Type  string      `json:"@type"`
	Value VertexValue `json:"@value"`
}

func MakeDummyVertex

func MakeDummyVertex(vertexID string, vertexLabel string, params map[string]interface{}) Vertex

func (Vertex) Equals

func (v1 Vertex) Equals(v2 Vertex) bool

type VertexProperty

type VertexProperty struct {
	Type  string              `json:"@type"`
	Value VertexPropertyValue `json:"@value"`
}

func MakeDummyVertexProperty

func MakeDummyVertexProperty(label string, value interface{}) VertexProperty

func (VertexProperty) Equals

func (v1 VertexProperty) Equals(v2 VertexProperty) bool

type VertexPropertyValue

type VertexPropertyValue struct {
	ID    GenericValue `json:"id"`
	Label string       `json:"label"`
	Value interface{}  `json:"value"`
}

func (VertexPropertyValue) Equals

type VertexV2 added in v1.0.6

type VertexV2 struct {
	Type  string        `json:"@type"`
	Value VertexValueV2 `json:"@value"`
}

type VertexValue

type VertexValue struct {
	ID         string                      `json:"id"`
	Label      string                      `json:"label"`
	Properties map[string][]VertexProperty `json:"properties"`
}

func (VertexValue) Equals

func (v1 VertexValue) Equals(v2 VertexValue) bool

type VertexValueV2 added in v1.0.6

type VertexValueV2 struct {
	ID         IdType                      `json:"id"`
	Label      string                      `json:"label"`
	Properties map[string][]VertexProperty `json:"properties"`
}

type Vertexes

type Vertexes []Vertex

func DeserializeVertices added in v1.0.7

func DeserializeVertices(rawResponse string) (Vertexes, error)

type VertexesV2 added in v1.0.6

type VertexesV2 []VertexV2

func DeserializeVerticesV2 added in v1.0.6

func DeserializeVerticesV2(rawResponse string) (VertexesV2, error)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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