search_index_backend.rb 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. # Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
  2. class SearchIndexBackend
  3. =begin
  4. create/update/delete index
  5. SearchIndexBackend.index(
  6. :action => 'create', # create/update/delete
  7. :data => {
  8. :mappings => {
  9. :Ticket => {
  10. :properties => {
  11. :articles_all => {
  12. :type => 'nested',
  13. :properties => {
  14. 'attachments' => { :type => 'attachment' }
  15. }
  16. }
  17. }
  18. }
  19. }
  20. }
  21. )
  22. SearchIndexBackend.index(
  23. :action => 'delete', # create/update/delete
  24. :name => 'Ticket', # optional
  25. )
  26. SearchIndexBackend.index(
  27. :action => 'delete', # create/update/delete
  28. )
  29. =end
  30. def self.index(data)
  31. url = build_url( data[:name] )
  32. return if !url
  33. if data[:action] && data[:action] == 'delete'
  34. return SearchIndexBackend.remove( data[:name] )
  35. end
  36. puts "# curl -X PUT \"#{url}\" -d '#{data[:data].to_json}'"
  37. conn = connection( url )
  38. response = conn.put do |req|
  39. req.url url
  40. req.headers['Content-Type'] = 'application/json'
  41. req.body = data[:data].to_json
  42. end
  43. puts "# #{response.status.to_s}"
  44. return true if response.success?
  45. data = JSON.parse( response.body )
  46. raise data.inspect
  47. end
  48. =begin
  49. add new object to search index
  50. SearchIndexBackend.add( 'Ticket', some_data_object )
  51. =end
  52. def self.add(type, data)
  53. url = build_url( type, data['id'] )
  54. return if !url
  55. puts "# curl -X POST \"#{url}\" -d '#{data.to_json}'"
  56. conn = connection( url )
  57. response = conn.post do |req|
  58. req.url url
  59. req.headers['Content-Type'] = 'application/json'
  60. req.body = data.to_json
  61. end
  62. puts "# #{response.status.to_s}"
  63. return true if response.success?
  64. data = JSON.parse( response.body )
  65. raise data.inspect
  66. end
  67. =begin
  68. remove whole data from index
  69. SearchIndexBackend.remove( 'Ticket', 123 )
  70. SearchIndexBackend.remove( 'Ticket' )
  71. =end
  72. def self.remove( type, o_id = nil )
  73. url = build_url( type, o_id )
  74. return if !url
  75. puts "# curl -X DELETE \"#{url}\""
  76. conn = connection( url )
  77. response = conn.delete( url )
  78. puts "# #{response.status.to_s}"
  79. return false if !response.success?
  80. data = JSON.parse( response.body )
  81. # raise data.inspect
  82. return { :data => data, :response => response }
  83. end
  84. =begin
  85. return search result
  86. result = SearchIndexBackend.search( 'search query', limit, 'User' )
  87. =end
  88. def self.search( query, limit = 10, index = nil, query_extention = {} )
  89. return [] if !query
  90. url = build_url()
  91. return if !url
  92. if index
  93. url += "/#{index}/_search"
  94. else
  95. url += '/_search'
  96. end
  97. data = {}
  98. data['from'] = 0
  99. data['size'] = 10
  100. data['sort'] =
  101. [
  102. {
  103. :updated_at => {
  104. :order => 'desc'
  105. }
  106. },
  107. "_score"
  108. ]
  109. data['query'] = query_extention || {}
  110. if !data['query']['bool']
  111. data['query']['bool'] = {}
  112. end
  113. if !data['query']['bool']['must']
  114. data['query']['bool']['must'] = []
  115. end
  116. # real search condition
  117. condition = {
  118. 'query_string' => {
  119. 'query' => query
  120. }
  121. }
  122. data['query']['bool']['must'].push condition
  123. puts "# curl -X POST \"#{url}\" -d '#{data.to_json}'"
  124. conn = connection( url )
  125. response = conn.get do |req|
  126. req.headers['Content-Type'] = 'application/json'
  127. req.body = data.to_json
  128. end
  129. puts "# #{response.status.to_s}"
  130. data = JSON.parse( response.body )
  131. if !response.success?
  132. return []
  133. # raise data.inspect
  134. end
  135. ids = []
  136. return ids if !data
  137. return ids if !data['hits']
  138. return ids if !data['hits']['hits']
  139. data['hits']['hits'].each { |item|
  140. puts "... #{item['_type'].to_s} #{item['_id'].to_s}"
  141. ids.push item['_id']
  142. }
  143. ids
  144. end
  145. =begin
  146. return true if backend is configured
  147. result = SearchIndexBackend.enabled?
  148. =end
  149. def self.enabled?
  150. return if !Setting.get('es_url')
  151. return if Setting.get('es_url').empty?
  152. true
  153. end
  154. private
  155. def self.build_url( type = nil, o_id = nil )
  156. return if !SearchIndexBackend.enabled?
  157. index = Setting.get('es_index').to_s + "_#{Rails.env}"
  158. url = Setting.get('es_url')
  159. if type
  160. if o_id
  161. url = "#{url}/#{index}/#{type}/#{o_id}"
  162. else
  163. url = "#{url}/#{index}/#{type}"
  164. end
  165. else
  166. url = "#{url}/#{index}"
  167. end
  168. url
  169. end
  170. def self.connection( url )
  171. conn = Faraday.new( :url => url )
  172. user = Setting.get('es_user')
  173. pw = Setting.get('es_password')
  174. if user && !user.empty? && pw && !pw.empty?
  175. conn.basic_auth( user, pw )
  176. end
  177. conn
  178. end
  179. end