search_index_es.rake 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. $LOAD_PATH << './lib'
  2. require 'rubygems'
  3. namespace :searchindex do
  4. task :drop, [:opts] => :environment do |_t, _args|
  5. # drop indexes
  6. print 'drop indexes...'
  7. SearchIndexBackend.index(
  8. action: 'delete',
  9. )
  10. puts 'done'
  11. Rake::Task['searchindex:drop_pipeline'].execute
  12. end
  13. task :create, [:opts] => :environment do |_t, _args|
  14. print 'create indexes...'
  15. # es with mapper-attachments plugin
  16. info = SearchIndexBackend.info
  17. number = nil
  18. if info.present?
  19. number = info['version']['number'].to_s
  20. end
  21. mapping = {}
  22. Models.searchable.each do |local_object|
  23. mapping.merge!(get_mapping_properties_object(local_object))
  24. end
  25. # create indexes
  26. SearchIndexBackend.index(
  27. action: 'create',
  28. data: {
  29. mappings: mapping
  30. }
  31. )
  32. if number.blank? || number =~ /^[2-4]\./ || number =~ /^5\.[0-5]\./
  33. Setting.set('es_pipeline', '')
  34. end
  35. puts 'done'
  36. Rake::Task['searchindex:create_pipeline'].execute
  37. end
  38. task :create_pipeline, [:opts] => :environment do |_t, _args|
  39. # es with mapper-attachments plugin
  40. info = SearchIndexBackend.info
  41. number = nil
  42. if info.present?
  43. number = info['version']['number'].to_s
  44. end
  45. next if number.blank? || number =~ /^[2-4]\./ || number =~ /^5\.[0-5]\./
  46. # update processors
  47. pipeline = Setting.get('es_pipeline')
  48. if pipeline.blank?
  49. pipeline = "zammad#{rand(999_999_999_999)}"
  50. Setting.set('es_pipeline', pipeline)
  51. end
  52. print 'create pipeline (pipeline)... '
  53. SearchIndexBackend.processors(
  54. "_ingest/pipeline/#{pipeline}": [
  55. {
  56. action: 'delete',
  57. },
  58. {
  59. action: 'create',
  60. description: 'Extract zammad-attachment information from arrays',
  61. processors: [
  62. {
  63. foreach: {
  64. field: 'article',
  65. ignore_failure: true,
  66. processor: {
  67. foreach: {
  68. field: '_ingest._value.attachment',
  69. ignore_failure: true,
  70. processor: {
  71. attachment: {
  72. target_field: '_ingest._value',
  73. field: '_ingest._value._content',
  74. ignore_failure: true,
  75. }
  76. }
  77. }
  78. }
  79. }
  80. }
  81. ]
  82. }
  83. ]
  84. )
  85. puts 'done'
  86. end
  87. task :drop_pipeline, [:opts] => :environment do |_t, _args|
  88. # es with mapper-attachments plugin
  89. info = SearchIndexBackend.info
  90. number = nil
  91. if info.present?
  92. number = info['version']['number'].to_s
  93. end
  94. next if number.blank? || number =~ /^[2-4]\./ || number =~ /^5\.[0-5]\./
  95. # update processors
  96. pipeline = Setting.get('es_pipeline')
  97. next if pipeline.blank?
  98. print 'delete pipeline (pipeline)... '
  99. SearchIndexBackend.processors(
  100. "_ingest/pipeline/#{pipeline}": [
  101. {
  102. action: 'delete',
  103. },
  104. ]
  105. )
  106. puts 'done'
  107. end
  108. task :reload, [:opts] => :environment do |_t, _args|
  109. puts 'reload data...'
  110. Models.searchable.each do |model_class|
  111. puts " reload #{model_class}"
  112. started_at = Time.zone.now
  113. puts " - started at #{started_at}"
  114. model_class.search_index_reload
  115. took = Time.zone.now - started_at
  116. puts " - took #{took.to_i} seconds"
  117. end
  118. end
  119. task :rebuild, [:opts] => :environment do |_t, _args|
  120. Rake::Task['searchindex:drop'].execute
  121. Rake::Task['searchindex:create'].execute
  122. Rake::Task['searchindex:reload'].execute
  123. end
  124. end
  125. =begin
  126. This function will return a index mapping based on the
  127. attributes of the database table of the existing object.
  128. mapping = get_mapping_properties_object(Ticket)
  129. Returns:
  130. mapping = {
  131. User: {
  132. properties: {
  133. firstname: {
  134. type: 'keyword',
  135. },
  136. }
  137. }
  138. }
  139. =end
  140. def get_mapping_properties_object(object)
  141. result = {
  142. object.name => {
  143. properties: {}
  144. }
  145. }
  146. store_columns = %w[preferences data]
  147. object.columns_hash.each do |key, value|
  148. if value.type == :string && value.limit && value.limit <= 5000 && store_columns.exclude?(key)
  149. result[object.name][:properties][key] = {
  150. type: 'text',
  151. fields: {
  152. raw: { 'type': 'string', 'index': 'not_analyzed' }
  153. }
  154. }
  155. elsif value.type == :integer
  156. result[object.name][:properties][key] = {
  157. type: 'integer',
  158. }
  159. elsif value.type == :datetime
  160. result[object.name][:properties][key] = {
  161. type: 'date',
  162. }
  163. elsif value.type == :boolean
  164. result[object.name][:properties][key] = {
  165. type: 'boolean',
  166. fields: {
  167. raw: { 'type': 'boolean', 'index': 'not_analyzed' }
  168. }
  169. }
  170. elsif value.type == :binary
  171. result[object.name][:properties][key] = {
  172. type: 'binary',
  173. }
  174. elsif value.type == :bigint
  175. result[object.name][:properties][key] = {
  176. type: 'long',
  177. }
  178. elsif value.type == :decimal
  179. result[object.name][:properties][key] = {
  180. type: 'float',
  181. }
  182. elsif value.type == :date
  183. result[object.name][:properties][key] = {
  184. type: 'date',
  185. }
  186. end
  187. end
  188. # es with mapper-attachments plugin
  189. info = SearchIndexBackend.info
  190. number = nil
  191. if info.present?
  192. number = info['version']['number'].to_s
  193. end
  194. if object.name == 'Ticket'
  195. result[object.name][:_source] = {
  196. excludes: ['article.attachment']
  197. }
  198. if number.blank? || number =~ /^[2-4]\./ || number =~ /^5\.[0-5]\./
  199. result[object.name][:_source] = {
  200. excludes: ['article.attachment']
  201. }
  202. result[object.name][:properties][:article] = {
  203. type: 'nested',
  204. include_in_parent: true,
  205. properties: {
  206. attachment: {
  207. type: 'attachment',
  208. }
  209. }
  210. }
  211. end
  212. end
  213. result
  214. end