search_controller.rb 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. class SearchController < ApplicationController
  3. prepend_before_action :authentication_check
  4. # GET|POST /api/v1/search
  5. # GET|POST /api/v1/search/:objects
  6. def search_generic
  7. # enable search only for users with valid session
  8. raise Exceptions::NotAuthorized if !current_user
  9. # get params
  10. query = params[:query]
  11. if query.respond_to?(:permit!)
  12. query = query.permit!.to_h
  13. end
  14. limit = params[:limit] || 10
  15. # convert objects string into array of class names
  16. # e.g. user-ticket-another_object = %w( User Ticket AnotherObject )
  17. objects = if !params[:objects]
  18. Setting.get('models_searchable')
  19. else
  20. params[:objects].split('-').map(&:camelize)
  21. end
  22. # get priorities of result
  23. objects_in_order = []
  24. objects_in_order_hash = {}
  25. objects.each do |object|
  26. local_class = object.constantize
  27. preferences = local_class.search_preferences(current_user)
  28. next if !preferences
  29. objects_in_order_hash[preferences[:prio]] = local_class
  30. end
  31. objects_in_order_hash.keys.sort.reverse_each do |prio|
  32. objects_in_order.push objects_in_order_hash[prio]
  33. end
  34. generic_search_params = {
  35. query: query,
  36. limit: limit,
  37. current_user: current_user,
  38. }
  39. # try search index backend
  40. assets = {}
  41. result = []
  42. if SearchIndexBackend.enabled?
  43. # get direct search index based objects
  44. objects_with_direct_search_index = []
  45. objects_without_direct_search_index = []
  46. objects.each do |object|
  47. preferences = object.constantize.search_preferences(current_user)
  48. next if !preferences
  49. if preferences[:direct_search_index]
  50. objects_with_direct_search_index.push object
  51. else
  52. objects_without_direct_search_index.push object
  53. end
  54. end
  55. # do only one query to index search backend
  56. if objects_with_direct_search_index.present?
  57. items = SearchIndexBackend.search(query, objects_with_direct_search_index, limit: limit)
  58. items.each do |item|
  59. require_dependency item[:type].to_filename
  60. local_class = item[:type].constantize
  61. record = local_class.lookup(id: item[:id])
  62. next if !record
  63. assets = record.assets(assets)
  64. item[:type] = local_class.to_app_model.to_s
  65. result.push item
  66. end
  67. end
  68. # e. g. do ticket query by Ticket class to handle ticket permissions
  69. objects_without_direct_search_index.each do |object|
  70. object_result = search_generic_backend(object.constantize, assets, generic_search_params)
  71. if object_result.present?
  72. result = result.concat(object_result)
  73. end
  74. end
  75. # sort order by object priority
  76. result_in_order = []
  77. objects_in_order.each do |object|
  78. result.each do |item|
  79. next if item[:type] != object.to_app_model.to_s
  80. item[:id] = item[:id].to_i
  81. result_in_order.push item
  82. end
  83. end
  84. result = result_in_order
  85. else
  86. # do query
  87. objects_in_order.each do |object|
  88. object_result = search_generic_backend(object, assets, generic_search_params)
  89. if object_result.present?
  90. result = result.concat(object_result)
  91. end
  92. end
  93. end
  94. render json: {
  95. assets: assets,
  96. result: result,
  97. }
  98. end
  99. private
  100. =begin
  101. search generic backend
  102. SearchController#search_generic_backend(
  103. Ticket, # object
  104. {}, # assets
  105. query: "search query",
  106. limit: 10,
  107. current_user: user,
  108. )
  109. =end
  110. def search_generic_backend(object, assets, params)
  111. found_objects = object.search(params)
  112. result = []
  113. found_objects.each do |found_object|
  114. item = {
  115. id: found_object.id,
  116. type: found_object.class.to_app_model.to_s
  117. }
  118. result.push item
  119. assets = found_object.assets(assets)
  120. end
  121. result
  122. end
  123. end