Graph
DSE 5.0 introduced Graph. session#execute_graph
and session#execute_graph_async
can be used to send Gremlin
graph queries to DSE Graph. The results (DSE::Graph::ResultSet
) returned to the driver can include vertices
(DSE::Graph::Vertex
), edges (DSE::Graph::Edge
), or a generic DSE::Graph::Result
containing paths or other
arbitrary objects.
Background
- Given
- a running dse cluster with graph enabled
- And
- an existing graph called “user_connections” with schema:
schema.propertyKey('name').Text().ifNotExists().create(); schema.propertyKey('age').Int().ifNotExists().create(); schema.propertyKey('lang').Text().ifNotExists().create(); schema.propertyKey('weight').Float().ifNotExists().create(); schema.vertexLabel('person').properties('name', 'age').ifNotExists().create(); schema.vertexLabel('software').properties('name', 'lang').ifNotExists().create(); schema.edgeLabel('created').properties('weight').connection('person', 'software').ifNotExists().create(); schema.edgeLabel('knows').properties('weight').connection('person', 'person').ifNotExists().create(); schema.propertyKey('country').Text().ifNotExists().create(); schema.propertyKey('origin').Text().multiple().properties('country').ifNotExists().create(); schema.vertexLabel('master').properties('name', 'origin').ifNotExists().create(); schema.vertexLabel('character').properties('name').ifNotExists().create();
Using graph options
- Given
- the following example:
require 'dse' cluster = Dse.cluster(graph_name: 'user_connections', graph_source: 'g', graph_language: 'gremlin-groovy', graph_read_consistency: :quorum, graph_write_consistency: :one ) default_graph_profile = cluster.execution_profile(:default_graph) puts "Graph name: #{default_graph_profile.graph_name}" puts "Graph source: #{default_graph_profile.graph_source}" puts "Graph language: #{default_graph_profile.graph_language}" puts "Graph read consistency: #{default_graph_profile.graph_read_consistency}" puts "Graph write consistency: #{default_graph_profile.graph_write_consistency}" puts ""
- When
- it is executed
- Then
- its output should contain:
Graph name: user_connections Graph source: g Graph language: gremlin-groovy Graph read consistency: quorum Graph write consistency: one
Using execution profiles
- Given
- the following example:
require 'dse' profile = Dse::Graph::ExecutionProfile.new(graph_name: 'user_connections') cluster = Dse.cluster(execution_profiles: {my_profile: profile}) session = cluster.connect # Execute a graph statement with the default profile, which will fail because the graph name is not set # in that profile begin session.execute_graph('g.V()') rescue => e puts 'Got an exception when running query without a graph name set' end rs = session.execute_graph('g.V()', execution_profile: :my_profile) puts "Found #{rs.size} vertices"
- When
- it is executed
- Then
- its output should match:
Got an exception when running query without a graph name set Found \d+ vertices
Inspecting vertices
- Given
- the following example:
require 'dse' cluster = Dse.cluster(graph_name: 'user_connections') session = cluster.connect session.execute_graph("yoda = graph.addVertex(label, 'master', 'name', 'Yoda'); yoda.property('origin', 'unknown', 'country', 'Galactic Republic'); yoda.property('origin', 'secret', 'country', 'Jedi Order')") vertex = session.execute_graph("g.V().has('master', 'name', 'Yoda')").first puts "The result is a: #{vertex.class}" puts "" puts "Vertex has id?: #{!vertex.id.nil?}" puts "Vertex label: #{vertex.id['~label']}" puts "" vertex.properties.each_pair do |property_name, property_values| puts "Vertex property name: #{property_name}" property_values.each do |property_value| puts "Property value has id?: #{!property_value.id.nil?}" puts "Property value: #{property_value.value}" puts "Property's properties: #{property_value.properties}" end puts "" end
- When
- it is executed
- Then
- its output should contain:
The result is a: Dse::Graph::Vertex Vertex has id?: true Vertex label: master Vertex property name: origin Property value has id?: true Property value: unknown Property's properties: {"country"=>"Galactic Republic"} Property value has id?: true Property value: secret Property's properties: {"country"=>"Jedi Order"} Vertex property name: name Property value has id?: true Property value: Yoda Property's properties: {}
Using graph statements
- Given
- the following example:
require 'dse' cluster = Dse.cluster session = cluster.connect graph_query = 'g.V().limit(my_limit)' graph_statement = Dse::Graph::Statement.new(graph_query, parameters = {my_limit: 1}, graph_name: 'user_connections', graph_language: 'gremlin-groovy') puts "Statement parameters: #{graph_statement.parameters}" puts "Statement has graph options? #{!graph_statement.graph_name.nil?}" puts "Graph query result size: #{session.execute_graph(graph_statement).size}"
- When
- it is executed
- Then
- its output should contain:
Statement parameters: {:my_limit=>1} Statement has graph options? true Graph query result size: 1
Inspecting edges
- Given
- the following example:
require 'dse' cluster = Dse.cluster(graph_name: 'user_connections') session = cluster.connect session.execute_graph(<<-GREMLIN) Vertex marko = graph.addVertex(label, 'person', 'name', 'marko', 'age', 29); Vertex josh = graph.addVertex(label, 'person', 'name', 'josh', 'age', 32); Vertex lop = graph.addVertex(label, 'software', 'name', 'lop', 'lang', 'java'); Vertex ripple = graph.addVertex(label, 'software', 'name', 'ripple', 'lang', 'java'); marko.addEdge('knows', josh, 'weight', 1.0f); josh.addEdge('created', ripple, 'weight', 1.0f); josh.addEdge('created', lop, 'weight', 0.4f); GREMLIN edge = session.execute_graph("g.E()").first puts "The result is a: #{edge.class}" puts "" puts "Edge has id?: #{!edge.id.nil?}" puts "Edge incoming vertex label: #{edge.in_v_label}" puts "Edge outgoing vertex label: #{edge.out_v_label}" puts "Edge properties: #{edge.properties}"
- When
- it is executed
- Then
- its output should contain:
The result is a: Dse::Graph::Edge Edge has id?: true Edge incoming vertex label: software Edge outgoing vertex label: person Edge properties: {"weight"=>0.4}
Inspecting paths
- Given
- the following example:
require 'dse' cluster = Dse.cluster(graph_name: 'user_connections') session = cluster.connect paths = session.execute_graph("g.V().hasLabel('person').has('name', 'marko').as('a')" \ ".outE('knows').inV().as('c', 'd').outE('created').as('e', 'f', 'g').inV().path()") puts "Total paths found: #{paths.size}" puts "" first_path = paths[0].as_path puts "Path labels: #{first_path.labels}" path_objects = first_path.objects puts "Length of path: #{path_objects.size}" puts "Object 1 is a #{path_objects[0].class}, value: #{path_objects[0].properties['name'].first.value}" puts "Object 2 is a #{path_objects[1].class}, value: #{path_objects[1].label}" puts "Object 3 is a #{path_objects[2].class}, value: #{path_objects[2].properties['name'].first.value}" puts "Object 4 is a #{path_objects[3].class}. value: #{path_objects[3].label}" puts "Object 5 is a #{path_objects[4].class}, value: #{path_objects[4].properties['name'].first.value}" puts "" second_path = paths[1].as_path puts "Path labels: #{second_path.labels}" path_objects = second_path.objects puts "Length of path: #{path_objects.size}" puts "Object 1 is a #{path_objects[0].class}, value: #{path_objects[0].properties['name'].first.value}" puts "Object 2 is a #{path_objects[1].class}, value: #{path_objects[1].label}" puts "Object 3 is a #{path_objects[2].class}, value: #{path_objects[2].properties['name'].first.value}" puts "Object 4 is a #{path_objects[3].class}. value: #{path_objects[3].label}" puts "Object 5 is a #{path_objects[4].class}, value: #{path_objects[4].properties['name'].first.value}"
- When
- it is executed
- Then
- its output should contain:
Total paths found: 2 Path labels: [["a"], [], ["c", "d"], ["e", "f", "g"], []] Length of path: 5 Object 1 is a Dse::Graph::Vertex, value: marko Object 2 is a Dse::Graph::Edge, value: knows Object 3 is a Dse::Graph::Vertex, value: josh Object 4 is a Dse::Graph::Edge. value: created Object 5 is a Dse::Graph::Vertex, value: lop Path labels: [["a"], [], ["c", "d"], ["e", "f", "g"], []] Length of path: 5 Object 1 is a Dse::Graph::Vertex, value: marko Object 2 is a Dse::Graph::Edge, value: knows Object 3 is a Dse::Graph::Vertex, value: josh Object 4 is a Dse::Graph::Edge. value: created Object 5 is a Dse::Graph::Vertex, value: ripple
Inspecting arbitrary results
- Given
- the following example:
require 'dse' cluster = Dse.cluster(graph_name: 'user_connections') session = cluster.connect result = session.execute_graph('g.V().count()').first puts "The result is a: #{result.class}" puts "The value of the result is: #{result.value}"
- When
- it is executed
- Then
- its output should contain:
The result is a: Dse::Graph::Result The value of the result is: 5
Using graph query parameters
- Given
- the following example:
require 'dse' cluster = Dse.cluster(graph_name: 'user_connections') session = cluster.connect # Simple parameter results = session.execute_graph('g.V().limit(my_limit)', arguments: {my_limit: 1}) puts "Returned #{results.size} result(s)" puts "" # List as parameter characters = ['Mario', 'Luigi', 'Toad', 'Bowser', 'Peach', 'Wario', 'Waluigi'] insert = "characters.each { character -> \n" + " graph.addVertex(label, 'character', 'name', character);\n" + "}" session.execute_graph(insert, arguments: {characters: characters}) results = session.execute_graph("g.V().hasLabel('character').values('name')") puts "There are #{results.size} characters total" results.map { |result| puts result.value } puts "" # Map as parameter input_map = { name: 'Yoda2', origin: 'unknown', origin_properties: ['Galactic Republic'] } session.execute_graph("yoda = graph.addVertex(label, 'master', 'name', input_map.name); yoda.property('origin', input_map.origin, 'country', input_map.origin_properties[0])", arguments: {input_map: input_map} ) vertex = session.execute_graph("g.V().has('master', 'name', 'Yoda2')").first puts "Vertex label: #{vertex.id['~label']}" vertex.properties.each_pair do |property_name, property_values| puts "Vertex property name: #{property_name}" property_values.each do |property_value| puts "Property value: #{property_value.value}" puts "Property's properties: #{property_value.properties}" end end
- When
- it is executed
- Then
- its output should contain:
Returned 1 result(s) There are 7 characters total Mario Luigi Toad Bowser Peach Wario Waluigi Vertex label: master Vertex property name: origin Property value: unknown Property's properties: {"country"=>"Galactic Republic"} Vertex property name: name Property value: Yoda2 Property's properties: {}