Class: Chef::SolrQuery

Inherits:
Object show all
Includes:
Mixin::XMLEscape
Defined in:
lib/chef/solr_query.rb,
lib/chef/solr_query/query_transform.rb,
lib/chef/solr_query/solr_http_request.rb

Defined Under Namespace

Classes: QueryTransform, SolrHTTPRequest

Constant Summary collapse

ID_KEY =
"X_CHEF_id_CHEF_X"
DEFAULT_PARAMS =
Mash.new(:start => 0, :rows => 1000, :sort => "#{ID_KEY} asc", :wt => 'json', :indent => 'off').freeze
FILTER_PARAM_MAP =
{:database => 'X_CHEF_database_CHEF_X', :type => "X_CHEF_type_CHEF_X", :data_bag  => 'data_bag'}
VALID_PARAMS =
[:start,:rows,:sort,:q,:type]
BUILTIN_SEARCH_TYPES =
["role","node","client","environment"]
DATA_BAG_ITEM =
'data_bag_item'
START_XML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".freeze
START_DELETE_BY_QUERY =
"<delete><query>".freeze
END_DELETE_BY_QUERY =
"</query></delete>\n".freeze
COMMIT =
"<commit/>\n".freeze

Constants included from Mixin::XMLEscape::PureRuby

Mixin::XMLEscape::PureRuby::CP1252, Mixin::XMLEscape::PureRuby::PREDEFINED, Mixin::XMLEscape::PureRuby::VALID

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Mixin::XMLEscape::FastXS

#xml_escape

Methods included from Mixin::XMLEscape::PureRuby

#xml_escape

Constructor Details

#initialize(couchdb = nil) ⇒ SolrQuery

Create a new Query object - takes the solr_url and optional Chef::CouchDB object to inflate objects into.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/chef/solr_query.rb', line 45

def initialize(couchdb = nil)
  @filter_query = {}
  @params = {}

  if couchdb.nil?
    @database = Chef::Config[:couchdb_database]
    @couchdb = Chef::CouchDB.new(nil, Chef::Config[:couchdb_database])
  else
    unless couchdb.respond_to?(:couchdb_database)
      Chef::Log.warn("Passing the database name to Chef::Solr::Query initialization is deprecated. Please pass in the Chef::CouchDB object instead.")
      @database = couchdb
      @couchdb = Chef::CouchDB.new(nil, couchdb)
    else
      @database = couchdb.couchdb_database
      @couchdb = couchdb
    end
  end
end

Instance Attribute Details

#paramsObject

Returns the value of attribute params.



41
42
43
# File 'lib/chef/solr_query.rb', line 41

def params
  @params
end

#queryObject

Returns the value of attribute query.



40
41
42
# File 'lib/chef/solr_query.rb', line 40

def query
  @query
end

Class Method Details

.from_params(params, couchdb = nil) ⇒ Object



64
65
66
67
68
69
70
71
72
73
# File 'lib/chef/solr_query.rb', line 64

def self.from_params(params, couchdb=nil)
  query = new(couchdb)
  query.params = VALID_PARAMS.inject({}) do |p, param_name|
    p[param_name] = params[param_name] if params.key?(param_name)
    p
  end
  query.update_filter_query_from_params
  query.update_query_from_params
  query
end

Instance Method Details

#commit(opts = {}) ⇒ Object



140
141
142
# File 'lib/chef/solr_query.rb', line 140

def commit(opts={})
  SolrHTTPRequest.update("#{START_XML}#{COMMIT}")
end

#delete_database(db) ⇒ Object



144
145
146
147
148
149
# File 'lib/chef/solr_query.rb', line 144

def delete_database(db)
  query_data = xml_escape("X_CHEF_database_CHEF_X:#{db}")
  xml = "#{START_XML}#{START_DELETE_BY_QUERY}#{query_data}#{END_DELETE_BY_QUERY}"
  SolrHTTPRequest.update(xml)
  commit
end

#filter_by(filter_query_params) ⇒ Object



75
76
77
78
79
# File 'lib/chef/solr_query.rb', line 75

def filter_by(filter_query_params)
  filter_query_params.each do |key, value|
    @filter_query[FILTER_PARAM_MAP[key]] = value
  end
end

#filter_by_type(type) ⇒ Object



85
86
87
88
89
90
91
92
# File 'lib/chef/solr_query.rb', line 85

def filter_by_type(type)
  case type
  when *BUILTIN_SEARCH_TYPES
    filter_by(:type => type)
  else
    filter_by(:type => DATA_BAG_ITEM, :data_bag => type)
  end
end

#filter_queryObject



81
82
83
# File 'lib/chef/solr_query.rb', line 81

def filter_query
  @filter_query.map { |param, value| "+#{param}:#{value}" }.join(' ')
end

#object_idsObject



114
115
116
# File 'lib/chef/solr_query.rb', line 114

def object_ids
  @object_ids ||= results["response"]["docs"].map { |d| d[ID_KEY] }
end

#objectsObject



104
105
106
107
108
109
110
111
112
# File 'lib/chef/solr_query.rb', line 104

def objects
  if !object_ids.empty?
    @bulk_objects ||= @couchdb.bulk_get(object_ids)
    Chef::Log.debug { "Bulk get of objects: #{@bulk_objects.inspect}" }
    @bulk_objects
  else
    []
  end
end

#rebuild_index(db = ) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/chef/solr_query.rb', line 151

def rebuild_index(db=Chef::Config[:couchdb_database])
  delete_database(db)

  results = {}
  [Chef::ApiClient, Chef::Node, Chef::Role, Chef::Environment].each do |klass|
    results[klass.name] = reindex_all(klass) ? "success" : "failed"
  end
  databags = Chef::DataBag.cdb_list(true)
  Chef::Log.info("Reloading #{databags.size.to_s} #{Chef::DataBag} objects into the indexer")
  databags.each { |i| i.add_to_index; i.list(true).each { |x| x.add_to_index } }
  results[Chef::DataBag.name] = "success"
  results
end

#reindex_all(klass, metadata = {}) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/chef/solr_query.rb', line 165

def reindex_all(klass, ={})
  begin
    items = klass.cdb_list(true)
    Chef::Log.info("Reloading #{items.size.to_s} #{klass.name} objects into the indexer")
    items.each { |i| i.add_to_index }
  rescue Net::HTTPServerException => e
    # 404s are okay, there might not be any of that kind of object...
    if e.message =~ /Not Found/
      Chef::Log.warn("Could not load #{klass.name} objects from couch for re-indexing (this is ok if you don't have any of these)")
      return false
    else
      raise e
    end
  rescue Exception => e
    Chef::Log.fatal("Chef encountered an error while attempting to load #{klass.name} objects back into the index")
    raise e
  end
  true
end

#resultsObject



118
119
120
# File 'lib/chef/solr_query.rb', line 118

def results
  @results ||= SolrHTTPRequest.select(self.to_hash)
end

#searchObject

Search Solr for objects of a given type, for a given query.



123
124
125
126
# File 'lib/chef/solr_query.rb', line 123

def search
  { "rows" => objects, "start" => results["response"]["start"],
    "total" => results["response"]["numFound"] }
end

#to_hashObject



128
129
130
131
132
133
# File 'lib/chef/solr_query.rb', line 128

def to_hash
  options = DEFAULT_PARAMS.merge(params)
  options[:fq] = filter_query
  options[:q] = @query
  options
end

#update_filter_query_from_paramsObject



94
95
96
97
# File 'lib/chef/solr_query.rb', line 94

def update_filter_query_from_params
  filter_by(:database => @database)
  filter_by_type(params.delete(:type))
end

#update_query_from_paramsObject



99
100
101
102
# File 'lib/chef/solr_query.rb', line 99

def update_query_from_params
  original_query = URI.decode(params.delete(:q) || "*:*")
  @query = Chef::SolrQuery::QueryTransform.transform(original_query)
end