Class: QueryResult

Inherits:
Object
  • Object
show all
Defined in:
lib/redisgraph/query_result.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(response, opts = {}) ⇒ QueryResult

Returns a new instance of QueryResult.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/redisgraph/query_result.rb', line 22

def initialize(response, opts = {})
  # The response for any query is expected to be a nested array.
  # If compact (RedisGraph protocol v2)
  # The resultset is an array w/ three elements:
  # 0] Node/Edge key names w/ the ordinal position used in [1]
  #    en lieu of the name to compact the result set.
  # 1] Node/Edge key/value pairs as an array w/ two elements:
  #  0] node/edge name id from [0]
  #  1..matches] node/edge values
  # 2] Statistics as an array of strings

  @metadata = opts[:metadata]

  @resultset = parse_resultset(response)
  @stats = parse_stats(response)
end

Instance Attribute Details

#columnsObject

Returns the value of attribute columns.



18
19
20
# File 'lib/redisgraph/query_result.rb', line 18

def columns
  @columns
end

#resultsetObject

Returns the value of attribute resultset.



19
20
21
# File 'lib/redisgraph/query_result.rb', line 19

def resultset
  @resultset
end

#statsObject

Returns the value of attribute stats.



20
21
22
# File 'lib/redisgraph/query_result.rb', line 20

def stats
  @stats
end

Instance Method Details

#map_prop(prop) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/redisgraph/query_result.rb', line 99

def map_prop(prop)
  # maximally a single @metadata.invalidate should occur

  property_keys = @metadata.property_keys
  prop_index = prop[0]
  if prop_index >= property_keys.length
    @metadata.invalidate
    property_keys = @metadata.property_keys
  end
  { property_keys[prop_index] => map_scalar(prop[1], prop[2]) }
end

#map_scalar(type, val) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/redisgraph/query_result.rb', line 74

def map_scalar(type, val)
  map_func = case type
             when ValueType::NULL
               return nil
             when ValueType::STRING
               :to_s
             when ValueType::INTEGER
               :to_i
             when ValueType::BOOLEAN
               # no :to_b
               return val == 'true'
             when ValueType::DOUBLE
               :to_f
             when ValueType::ARRAY
               return val.map { |it| map_scalar(it[0], it[1]) }
             when ValueType::EDGE
               props = val[4]
               return props.sort_by { |prop| prop[0] }.map { |prop| map_prop(prop) }
             when ValueType::NODE
               props = val[2]
               return props.sort_by { |prop| prop[0] }.map { |prop| map_prop(prop) }
             end
  val.send(map_func)
end

#parse_resultset(response) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/redisgraph/query_result.rb', line 48

def parse_resultset(response)
  # In the v2 protocol, CREATE does not contain an empty row preceding statistics
  return unless response.length > 1

  # Any non-empty result set will have multiple rows (arrays)

  # First row is header describing the returned records, corresponding
  # precisely in order and naming to the RETURN clause of the query.
  header = response[0]
  @columns = header.map { |(_type, name)| name }

  # Second row is the actual data returned by the query
  # note handling for encountering an id for propertyKey that is out of
  # the cached set.
  data = response[1].map do |row|
    i = -1
    header.reduce([]) do |agg, (type, _it)|
      i += 1
      el = row[i]
      agg << map_scalar(el[0], el[1])
    end
  end

  data
end

#parse_stats(response) ⇒ Object

Read metrics about internal query handling



112
113
114
115
116
117
118
119
# File 'lib/redisgraph/query_result.rb', line 112

def parse_stats(response)
  # In the v2 protocol, CREATE does not contain an empty row preceding statistics
  stats_offset = response.length == 1 ? 0 : 2

  return nil unless response[stats_offset]

  parse_stats_row(response[stats_offset])
end

#parse_stats_row(response_row) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/redisgraph/query_result.rb', line 121

def parse_stats_row(response_row)
  stats = {}

  response_row.each do |stat|
    line = stat.split(': ')
    val = line[1].split(' ')[0].to_i

    case line[0]
    when /^Labels added/
      stats[:labels_added] = val
    when /^Nodes created/
      stats[:nodes_created] = val
    when /^Nodes deleted/
      stats[:nodes_deleted] = val
    when /^Relationships deleted/
      stats[:relationships_deleted] = val
    when /^Properties set/
      stats[:properties_set] = val
    when /^Relationships created/
      stats[:relationships_created] = val
    when /^Query internal execution time/
      stats[:internal_execution_time] = val
    end
  end
  stats
end


39
40
41
42
43
44
45
46
# File 'lib/redisgraph/query_result.rb', line 39

def print_resultset
  return unless columns

  pretty = Terminal::Table.new headings: columns do |t|
    resultset.each { |record| t << record }
  end
  puts pretty
end