Fixes #3243 - Relational report filters do not work (ticket.organization.*, ticket.article.*, ticket.customer.*).
This commit is contained in:
parent
90a67e9d94
commit
d0b5cbfe4b
25 changed files with 227 additions and 380 deletions
|
@ -13,20 +13,26 @@
|
||||||
- bundle exec rspec --tag searchindex --tag ~type:system
|
- bundle exec rspec --tag searchindex --tag ~type:system
|
||||||
- bundle exec rails test test/integration/report_test.rb
|
- bundle exec rails test test/integration/report_test.rb
|
||||||
|
|
||||||
es:5.6:
|
|
||||||
<<: *template_integration_es
|
|
||||||
variables:
|
|
||||||
ELASTICSEARCH_TAG: '5.6'
|
|
||||||
RAILS_ENV: "test"
|
|
||||||
|
|
||||||
es:6:
|
es:6:
|
||||||
<<: *template_integration_es
|
<<: *template_integration_es
|
||||||
variables:
|
variables:
|
||||||
ELASTICSEARCH_TAG: '6'
|
ELASTICSEARCH_TAG: '6'
|
||||||
RAILS_ENV: "test"
|
RAILS_ENV: "test"
|
||||||
|
|
||||||
|
es:6.5:
|
||||||
|
<<: *template_integration_es
|
||||||
|
variables:
|
||||||
|
ELASTICSEARCH_TAG: '6.5'
|
||||||
|
RAILS_ENV: "test"
|
||||||
|
|
||||||
es:7:
|
es:7:
|
||||||
<<: *template_integration_es
|
<<: *template_integration_es
|
||||||
variables:
|
variables:
|
||||||
ELASTICSEARCH_TAG: '7'
|
ELASTICSEARCH_TAG: '7'
|
||||||
RAILS_ENV: "test"
|
RAILS_ENV: "test"
|
||||||
|
|
||||||
|
es:7.0:
|
||||||
|
<<: *template_integration_es
|
||||||
|
variables:
|
||||||
|
ELASTICSEARCH_TAG: '7.0'
|
||||||
|
RAILS_ENV: "test"
|
||||||
|
|
|
@ -733,6 +733,7 @@ Metrics/PerceivedComplexity:
|
||||||
- 'app/models/application_model/checks_attribute_values_and_length.rb'
|
- 'app/models/application_model/checks_attribute_values_and_length.rb'
|
||||||
- 'app/models/application_model/checks_user_columns_fillup.rb'
|
- 'app/models/application_model/checks_user_columns_fillup.rb'
|
||||||
- 'app/models/application_model/has_attachments.rb'
|
- 'app/models/application_model/has_attachments.rb'
|
||||||
|
- 'app/models/application_model/can_lookup_search_index_attributes.rb'
|
||||||
- 'app/models/authorization.rb'
|
- 'app/models/authorization.rb'
|
||||||
- 'app/models/avatar.rb'
|
- 'app/models/avatar.rb'
|
||||||
- 'app/models/calendar.rb'
|
- 'app/models/calendar.rb'
|
||||||
|
|
|
@ -4,10 +4,13 @@ module ApplicationModel::CanLookupSearchIndexAttributes
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
||||||
lookup name of ref. objects
|
This function return the attributes for the elastic search with relation hash values.
|
||||||
|
|
||||||
|
It can be run with parameter include_references: false to skip the relational hashes to prevent endless loops.
|
||||||
|
|
||||||
ticket = Ticket.find(3)
|
ticket = Ticket.find(3)
|
||||||
attributes = ticket.search_index_attribute_lookup
|
attributes = ticket.search_index_attribute_lookup
|
||||||
|
attributes = ticket.search_index_attribute_lookup(include_references: false)
|
||||||
|
|
||||||
returns
|
returns
|
||||||
|
|
||||||
|
@ -15,10 +18,11 @@ returns
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def search_index_attribute_lookup
|
def search_index_attribute_lookup(include_references: true)
|
||||||
|
|
||||||
attributes = self.attributes
|
attributes = self.attributes
|
||||||
self.attributes.each do |key, value|
|
self.attributes.each do |key, value|
|
||||||
|
break if !include_references
|
||||||
|
|
||||||
attribute_name = key.to_s
|
attribute_name = key.to_s
|
||||||
|
|
||||||
# ignore standard attribute if needed
|
# ignore standard attribute if needed
|
||||||
|
@ -74,34 +78,7 @@ returns
|
||||||
relation_model = relation_class.lookup(id: attributes[attribute_name])
|
relation_model = relation_class.lookup(id: attributes[attribute_name])
|
||||||
return if !relation_model
|
return if !relation_model
|
||||||
|
|
||||||
relation_model.search_index_value
|
relation_model.search_index_attribute_lookup(include_references: false)
|
||||||
end
|
|
||||||
|
|
||||||
=begin
|
|
||||||
|
|
||||||
This function returns the relational search value.
|
|
||||||
|
|
||||||
organization = Organization.find(1)
|
|
||||||
value = organization.search_index_value
|
|
||||||
|
|
||||||
returns
|
|
||||||
|
|
||||||
value = {"name"=>"Zammad Foundation"}
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
def search_index_value
|
|
||||||
|
|
||||||
# get name of ref object
|
|
||||||
value = nil
|
|
||||||
if respond_to?('name')
|
|
||||||
value = send('name')
|
|
||||||
elsif respond_to?('search_index_data')
|
|
||||||
value = send('search_index_data')
|
|
||||||
return if value == true
|
|
||||||
end
|
|
||||||
|
|
||||||
value
|
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
|
@ -15,7 +15,7 @@ returns
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def search_index_attribute_lookup
|
def search_index_attribute_lookup(include_references: true)
|
||||||
attributes = super
|
attributes = super
|
||||||
return if !attributes
|
return if !attributes
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ returns
|
||||||
# start background job to transfer data to search index
|
# start background job to transfer data to search index
|
||||||
return true if !SearchIndexBackend.enabled?
|
return true if !SearchIndexBackend.enabled?
|
||||||
|
|
||||||
new_search_index_value = search_index_value
|
new_search_index_value = search_index_attribute_lookup(include_references: false)
|
||||||
return if new_search_index_value.blank?
|
return if new_search_index_value.blank?
|
||||||
|
|
||||||
Models.indexable.each do |local_object|
|
Models.indexable.each do |local_object|
|
||||||
|
@ -174,36 +174,6 @@ returns
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
|
||||||
|
|
||||||
get data to store in search index
|
|
||||||
|
|
||||||
ticket = Ticket.find(123)
|
|
||||||
result = ticket.search_index_data
|
|
||||||
|
|
||||||
returns
|
|
||||||
|
|
||||||
result = {
|
|
||||||
attribute1: 'some value',
|
|
||||||
attribute2: ['value 1', 'value 2'],
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
def search_index_data
|
|
||||||
attributes = {}
|
|
||||||
%w[name note].each do |key|
|
|
||||||
next if !self[key]
|
|
||||||
next if self[key].respond_to?('blank?') && self[key].blank?
|
|
||||||
|
|
||||||
attributes[key] = self[key]
|
|
||||||
end
|
|
||||||
return true if attributes.blank?
|
|
||||||
|
|
||||||
attributes
|
|
||||||
end
|
|
||||||
|
|
||||||
def ignore_search_indexing?(_action)
|
def ignore_search_indexing?(_action)
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
|
@ -51,7 +51,7 @@ class KnowledgeBase::Answer::Translation < ApplicationModel
|
||||||
[answer_id, title.parameterize].join('-')
|
[answer_id, title.parameterize].join('-')
|
||||||
end
|
end
|
||||||
|
|
||||||
def search_index_attribute_lookup
|
def search_index_attribute_lookup(include_references: true)
|
||||||
attrs = super
|
attrs = super
|
||||||
|
|
||||||
attrs['title'] = ActionController::Base.helpers.strip_tags attrs['title']
|
attrs['title'] = ActionController::Base.helpers.strip_tags attrs['title']
|
||||||
|
|
|
@ -39,7 +39,7 @@ class KnowledgeBase::Answer::Translation::Content < ApplicationModel
|
||||||
attributes
|
attributes
|
||||||
end
|
end
|
||||||
|
|
||||||
def search_index_attribute_lookup
|
def search_index_attribute_lookup(include_references: true)
|
||||||
attrs = super
|
attrs = super
|
||||||
attrs['body'] = ActionController::Base.helpers.strip_tags attrs['body']
|
attrs['body'] = ActionController::Base.helpers.strip_tags attrs['body']
|
||||||
attrs
|
attrs
|
||||||
|
|
|
@ -29,7 +29,7 @@ class KnowledgeBase::Category::Translation < ApplicationModel
|
||||||
category.assets(data)
|
category.assets(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
def search_index_attribute_lookup
|
def search_index_attribute_lookup(include_references: true)
|
||||||
attrs = super
|
attrs = super
|
||||||
|
|
||||||
attrs['title'] = ActionController::Base.helpers.strip_tags attrs['title']
|
attrs['title'] = ActionController::Base.helpers.strip_tags attrs['title']
|
||||||
|
|
|
@ -19,7 +19,7 @@ class KnowledgeBase::Translation < ApplicationModel
|
||||||
knowledge_base.assets(data)
|
knowledge_base.assets(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
def search_index_attribute_lookup
|
def search_index_attribute_lookup(include_references: true)
|
||||||
attrs = super
|
attrs = super
|
||||||
|
|
||||||
attrs['title'] = ActionController::Base.helpers.strip_tags attrs['title']
|
attrs['title'] = ActionController::Base.helpers.strip_tags attrs['title']
|
||||||
|
|
|
@ -17,6 +17,8 @@ class Organization < ApplicationModel
|
||||||
|
|
||||||
has_many :members, class_name: 'User'
|
has_many :members, class_name: 'User'
|
||||||
has_many :tickets, class_name: 'Ticket'
|
has_many :tickets, class_name: 'Ticket'
|
||||||
|
belongs_to :created_by, class_name: 'User'
|
||||||
|
belongs_to :updated_by, class_name: 'User'
|
||||||
|
|
||||||
before_create :domain_cleanup
|
before_create :domain_cleanup
|
||||||
before_update :domain_cleanup
|
before_update :domain_cleanup
|
||||||
|
@ -25,7 +27,7 @@ class Organization < ApplicationModel
|
||||||
validates :name, presence: true
|
validates :name, presence: true
|
||||||
validates :domain, presence: { message: 'required when Domain Based Assignment is enabled' }, if: :domain_assignment
|
validates :domain, presence: { message: 'required when Domain Based Assignment is enabled' }, if: :domain_assignment
|
||||||
|
|
||||||
association_attributes_ignored :tickets
|
association_attributes_ignored :tickets, :created_by, :updated_by
|
||||||
|
|
||||||
activity_stream_permission 'admin.role'
|
activity_stream_permission 'admin.role'
|
||||||
|
|
||||||
|
|
|
@ -4,27 +4,17 @@ class Organization
|
||||||
module SearchIndex
|
module SearchIndex
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
=begin
|
def search_index_attribute_lookup(include_references: true)
|
||||||
|
|
||||||
lookup name of ref. objects
|
|
||||||
|
|
||||||
organization = Organization.find(123)
|
|
||||||
attributes = organization.search_index_attribute_lookup
|
|
||||||
|
|
||||||
returns
|
|
||||||
|
|
||||||
attributes # object with lookup data
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
def search_index_attribute_lookup
|
|
||||||
attributes = super
|
attributes = super
|
||||||
|
|
||||||
# add org members for search index data
|
if include_references
|
||||||
attributes['members'] = []
|
|
||||||
users = User.where(organization_id: id)
|
# add org members for search index data
|
||||||
users.each do |user|
|
attributes['members'] = []
|
||||||
attributes['members'].push user.search_index_data
|
users = User.where(organization_id: id)
|
||||||
|
users.each do |user|
|
||||||
|
attributes['members'].push user.search_index_attribute_lookup(include_references: false)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
attributes
|
attributes
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
class StatsStore < ApplicationModel
|
class StatsStore < ApplicationModel
|
||||||
include HasSearchIndexBackend
|
include HasSearchIndexBackend
|
||||||
include StatsStore::SearchIndex
|
|
||||||
|
|
||||||
belongs_to :stats_storable, polymorphic: true
|
belongs_to :stats_storable, polymorphic: true
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
|
||||||
module StatsStore::SearchIndex
|
|
||||||
|
|
||||||
def search_index_attribute_lookup
|
|
||||||
attributes = super
|
|
||||||
return if !attributes
|
|
||||||
|
|
||||||
begin
|
|
||||||
record = attributes['stats_store_object'].constantize.lookup(id: o_id)
|
|
||||||
return if !record
|
|
||||||
|
|
||||||
attributes['stats_store_object_ref'] = record.search_index_attribute_lookup
|
|
||||||
rescue
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
attributes
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -2,20 +2,7 @@
|
||||||
module Ticket::SearchIndex
|
module Ticket::SearchIndex
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
=begin
|
def search_index_attribute_lookup(include_references: true)
|
||||||
|
|
||||||
lookup name of ref. objects
|
|
||||||
|
|
||||||
ticket = Ticket.find(123)
|
|
||||||
result = ticket.search_index_attribute_lookup
|
|
||||||
|
|
||||||
returns
|
|
||||||
|
|
||||||
attributes # object with lookup data
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
def search_index_attribute_lookup
|
|
||||||
attributes = super
|
attributes = super
|
||||||
return if !attributes
|
return if !attributes
|
||||||
|
|
||||||
|
@ -40,7 +27,7 @@ returns
|
||||||
articles.each do |article|
|
articles.each do |article|
|
||||||
|
|
||||||
# lookup attributes of ref. objects (normally name and note)
|
# lookup attributes of ref. objects (normally name and note)
|
||||||
article_attributes = article.search_index_attribute_lookup
|
article_attributes = article.search_index_attribute_lookup(include_references: false)
|
||||||
|
|
||||||
# remove note needed attributes
|
# remove note needed attributes
|
||||||
ignore = %w[message_id_md5 ticket]
|
ignore = %w[message_id_md5 ticket]
|
||||||
|
|
|
@ -4,68 +4,19 @@ class User
|
||||||
module SearchIndex
|
module SearchIndex
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
=begin
|
def search_index_attribute_lookup(include_references: true)
|
||||||
|
|
||||||
lookup name of ref. objects
|
|
||||||
|
|
||||||
user = User.find(123)
|
|
||||||
attributes = user.search_index_attribute_lookup
|
|
||||||
|
|
||||||
returns
|
|
||||||
|
|
||||||
attributes # object with lookup data
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
def search_index_attribute_lookup
|
|
||||||
attributes = super
|
attributes = super
|
||||||
|
attributes.delete('password')
|
||||||
|
|
||||||
attributes['permissions'] = []
|
if include_references
|
||||||
permissions_with_child_ids.each do |permission_id|
|
attributes['permissions'] = []
|
||||||
permission = ::Permission.lookup(id: permission_id)
|
permissions_with_child_ids.each do |permission_id|
|
||||||
next if !permission
|
permission = ::Permission.lookup(id: permission_id)
|
||||||
|
next if !permission
|
||||||
|
|
||||||
attributes['permissions'].push permission.name
|
attributes['permissions'].push permission.name
|
||||||
end
|
|
||||||
attributes['role_ids'] = role_ids
|
|
||||||
|
|
||||||
attributes
|
|
||||||
end
|
|
||||||
|
|
||||||
=begin
|
|
||||||
|
|
||||||
get data to store in search index
|
|
||||||
|
|
||||||
user = User.find(2)
|
|
||||||
result = user.search_index_data
|
|
||||||
|
|
||||||
returns
|
|
||||||
|
|
||||||
result = {
|
|
||||||
attribute1: 'some value',
|
|
||||||
attribute2: ['value 1', 'value 2'],
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
def search_index_data
|
|
||||||
attributes = {}
|
|
||||||
self.attributes.each do |key, value|
|
|
||||||
next if key == 'password'
|
|
||||||
next if !value
|
|
||||||
next if value.respond_to?('blank?') && value.blank?
|
|
||||||
|
|
||||||
attributes[key] = value
|
|
||||||
end
|
|
||||||
return if attributes.blank?
|
|
||||||
|
|
||||||
if attributes['organization_id'].present?
|
|
||||||
organization = Organization.lookup(id: attributes['organization_id'])
|
|
||||||
if organization
|
|
||||||
attributes['organization'] = organization.name
|
|
||||||
attributes['organization_ref'] = organization.search_index_data
|
|
||||||
end
|
end
|
||||||
|
attributes['role_ids'] = role_ids
|
||||||
end
|
end
|
||||||
|
|
||||||
attributes
|
attributes
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
class ElasticSearchLower65Obsolete < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
|
||||||
|
# return if it's a new setup
|
||||||
|
return if !Setting.exists?(name: 'system_init_done')
|
||||||
|
|
||||||
|
Setting.find_by(name: 'es_multi_index').destroy
|
||||||
|
end
|
||||||
|
end
|
|
@ -2980,15 +2980,6 @@ Setting.create_if_not_exists(
|
||||||
preferences: { online_service_disable: true },
|
preferences: { online_service_disable: true },
|
||||||
frontend: false
|
frontend: false
|
||||||
)
|
)
|
||||||
Setting.create_if_not_exists(
|
|
||||||
title: 'Elasticsearch Multi Index',
|
|
||||||
name: 'es_multi_index',
|
|
||||||
area: 'SearchIndex::Elasticsearch',
|
|
||||||
description: 'Define if Elasticsearch is using multiple indexes.',
|
|
||||||
state: false,
|
|
||||||
preferences: { online_service_disable: true },
|
|
||||||
frontend: false
|
|
||||||
)
|
|
||||||
|
|
||||||
Setting.create_if_not_exists(
|
Setting.create_if_not_exists(
|
||||||
title: 'Import Mode',
|
title: 'Import Mode',
|
||||||
|
|
|
@ -33,7 +33,7 @@ returns
|
||||||
}
|
}
|
||||||
|
|
||||||
without_merged_tickets = {
|
without_merged_tickets = {
|
||||||
'state' => {
|
'state.name' => {
|
||||||
'operator' => 'is not',
|
'operator' => 'is not',
|
||||||
'value' => 'merged'
|
'value' => 'merged'
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ returns
|
||||||
end
|
end
|
||||||
|
|
||||||
without_merged_tickets = {
|
without_merged_tickets = {
|
||||||
'state' => {
|
'state.name' => {
|
||||||
'operator' => 'is not',
|
'operator' => 'is not',
|
||||||
'value' => 'merged'
|
'value' => 'merged'
|
||||||
}
|
}
|
||||||
|
|
|
@ -479,9 +479,9 @@ example for aggregations within one year
|
||||||
current_user_id = current_user.id
|
current_user_id = current_user.id
|
||||||
end
|
end
|
||||||
|
|
||||||
query_must = []
|
query_must = []
|
||||||
query_must_not = []
|
query_must_not = []
|
||||||
relative_map = {
|
relative_map = {
|
||||||
day: 'd',
|
day: 'd',
|
||||||
year: 'y',
|
year: 'y',
|
||||||
month: 'M',
|
month: 'M',
|
||||||
|
@ -490,7 +490,13 @@ example for aggregations within one year
|
||||||
}
|
}
|
||||||
if selector.present?
|
if selector.present?
|
||||||
selector.each do |key, data|
|
selector.each do |key, data|
|
||||||
key_tmp = key.sub(/^.+?\./, '')
|
data = data.clone
|
||||||
|
table, key_tmp = key.split(/\./)
|
||||||
|
if key_tmp.blank?
|
||||||
|
key_tmp = table
|
||||||
|
table = 'ticket'
|
||||||
|
end
|
||||||
|
|
||||||
wildcard_or_term = 'term'
|
wildcard_or_term = 'term'
|
||||||
if data['value'].is_a?(Array)
|
if data['value'].is_a?(Array)
|
||||||
wildcard_or_term = 'terms'
|
wildcard_or_term = 'terms'
|
||||||
|
@ -539,22 +545,27 @@ example for aggregations within one year
|
||||||
|
|
||||||
# use .keyword and wildcard search in cases where query contains non A-z chars
|
# use .keyword and wildcard search in cases where query contains non A-z chars
|
||||||
if data['operator'] == 'contains' || data['operator'] == 'contains not'
|
if data['operator'] == 'contains' || data['operator'] == 'contains not'
|
||||||
|
|
||||||
if data['value'].is_a?(Array)
|
if data['value'].is_a?(Array)
|
||||||
data['value'].each_with_index do |value, index|
|
data['value'].each_with_index do |value, index|
|
||||||
next if !value.is_a?(String) || value !~ /[A-z]/ || value !~ /\W/
|
next if !value.is_a?(String) || value !~ /[A-z]/
|
||||||
|
|
||||||
data['value'][index] = "*#{value}*"
|
data['value'][index] = "*#{value}*"
|
||||||
key_tmp += '.keyword'
|
key_tmp += '.keyword'
|
||||||
wildcard_or_term = 'wildcards'
|
wildcard_or_term = 'wildcards'
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
elsif data['value'].is_a?(String) && /[A-z]/.match?(data['value']) && data['value'] =~ /\W/
|
elsif data['value'].is_a?(String) && /[A-z]/.match?(data['value'])
|
||||||
data['value'] = "*#{data['value']}*"
|
data['value'] = "*#{data['value']}*"
|
||||||
key_tmp += '.keyword'
|
key_tmp += '.keyword'
|
||||||
wildcard_or_term = 'wildcard'
|
wildcard_or_term = 'wildcard'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if table != 'ticket'
|
||||||
|
key_tmp = "#{table}.#{key_tmp}"
|
||||||
|
end
|
||||||
|
|
||||||
# is/is not/contains/contains not
|
# is/is not/contains/contains not
|
||||||
case data['operator']
|
case data['operator']
|
||||||
when 'is', 'is not', 'contains', 'contains not'
|
when 'is', 'is not', 'contains', 'contains not'
|
||||||
|
@ -702,29 +713,12 @@ return true if backend is configured
|
||||||
def self.build_index_name(index = nil)
|
def self.build_index_name(index = nil)
|
||||||
local_index = "#{Setting.get('es_index')}_#{Rails.env}"
|
local_index = "#{Setting.get('es_index')}_#{Rails.env}"
|
||||||
return local_index if index.blank?
|
return local_index if index.blank?
|
||||||
return "#{local_index}/#{index}" if lower_equal_es56?
|
|
||||||
|
|
||||||
"#{local_index}_#{index.underscore.tr('/', '_')}"
|
"#{local_index}_#{index.underscore.tr('/', '_')}"
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
||||||
return true if the elastic search version is lower equal 5.6
|
|
||||||
|
|
||||||
result = SearchIndexBackend.lower_equal_es56?
|
|
||||||
|
|
||||||
returns
|
|
||||||
|
|
||||||
result = true
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
def self.lower_equal_es56?
|
|
||||||
Setting.get('es_multi_index') == false
|
|
||||||
end
|
|
||||||
|
|
||||||
=begin
|
|
||||||
|
|
||||||
generate url for index or document access (only for internal use)
|
generate url for index or document access (only for internal use)
|
||||||
|
|
||||||
# url to access single document in index (in case with_pipeline or not)
|
# url to access single document in index (in case with_pipeline or not)
|
||||||
|
@ -770,7 +764,7 @@ generate url for index or document access (only for internal use)
|
||||||
url = "#{url}/#{index}"
|
url = "#{url}/#{index}"
|
||||||
|
|
||||||
# add document type
|
# add document type
|
||||||
if with_document_type && !lower_equal_es56?
|
if with_document_type
|
||||||
url = "#{url}/_doc"
|
url = "#{url}/_doc"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -801,7 +795,7 @@ generate url for index or document access (only for internal use)
|
||||||
message = if response&.error&.match?('Connection refused')
|
message = if response&.error&.match?('Connection refused')
|
||||||
"Elasticsearch is not reachable, probably because it's not running or even installed."
|
"Elasticsearch is not reachable, probably because it's not running or even installed."
|
||||||
elsif url.end_with?('pipeline/zammad-attachment', 'pipeline=zammad-attachment') && response.code == 400
|
elsif url.end_with?('pipeline/zammad-attachment', 'pipeline=zammad-attachment') && response.code == 400
|
||||||
'The installed attachment plugin could not handle the request payload. Ensure that the correct attachment plugin is installed (5.6 => ingest-attachment, 2.4 - 5.5 => mapper-attachments).'
|
'The installed attachment plugin could not handle the request payload. Ensure that the correct attachment plugin is installed (ingest-attachment).'
|
||||||
else
|
else
|
||||||
'Check the response and payload for detailed information: '
|
'Check the response and payload for detailed information: '
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,18 +6,13 @@ namespace :searchindex do
|
||||||
print 'drop indexes...'
|
print 'drop indexes...'
|
||||||
|
|
||||||
# drop indexes
|
# drop indexes
|
||||||
if es_multi_index?
|
Models.indexable.each do |local_object|
|
||||||
Models.indexable.each do |local_object|
|
|
||||||
SearchIndexBackend.index(
|
|
||||||
action: 'delete',
|
|
||||||
name: local_object.name,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
SearchIndexBackend.index(
|
SearchIndexBackend.index(
|
||||||
action: 'delete',
|
action: 'delete',
|
||||||
|
name: local_object.name,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
puts 'done'
|
puts 'done'
|
||||||
|
|
||||||
Rake::Task['searchindex:drop_pipeline'].execute
|
Rake::Task['searchindex:drop_pipeline'].execute
|
||||||
|
@ -26,37 +21,17 @@ namespace :searchindex do
|
||||||
task :create, [:opts] => %i[environment searchindex:configured searchindex:version_supported] do |_t, _args|
|
task :create, [:opts] => %i[environment searchindex:configured searchindex:version_supported] do |_t, _args|
|
||||||
print 'create indexes...'
|
print 'create indexes...'
|
||||||
|
|
||||||
if es_multi_index?
|
|
||||||
Setting.set('es_multi_index', true)
|
|
||||||
else
|
|
||||||
Setting.set('es_multi_index', false)
|
|
||||||
end
|
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
'index.mapping.total_fields.limit': 2000,
|
'index.mapping.total_fields.limit': 2000,
|
||||||
}
|
}
|
||||||
|
|
||||||
# create indexes
|
# create indexes
|
||||||
if es_multi_index?
|
Models.indexable.each do |local_object|
|
||||||
Models.indexable.each do |local_object|
|
|
||||||
SearchIndexBackend.index(
|
|
||||||
action: 'create',
|
|
||||||
name: local_object.name,
|
|
||||||
data: {
|
|
||||||
mappings: get_mapping_properties_object(local_object),
|
|
||||||
settings: settings,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
mapping = {}
|
|
||||||
Models.indexable.each do |local_object|
|
|
||||||
mapping.merge!(get_mapping_properties_object(local_object))
|
|
||||||
end
|
|
||||||
SearchIndexBackend.index(
|
SearchIndexBackend.index(
|
||||||
action: 'create',
|
action: 'create',
|
||||||
|
name: local_object.name,
|
||||||
data: {
|
data: {
|
||||||
mappings: mapping,
|
mappings: get_mapping_properties_object(local_object),
|
||||||
settings: settings,
|
settings: settings,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -68,10 +43,6 @@ namespace :searchindex do
|
||||||
end
|
end
|
||||||
|
|
||||||
task :create_pipeline, [:opts] => %i[environment searchindex:configured searchindex:version_supported] do |_t, _args|
|
task :create_pipeline, [:opts] => %i[environment searchindex:configured searchindex:version_supported] do |_t, _args|
|
||||||
if !es_pipeline?
|
|
||||||
Setting.set('es_pipeline', '')
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
# update processors
|
# update processors
|
||||||
pipeline = Setting.get('es_pipeline')
|
pipeline = Setting.get('es_pipeline')
|
||||||
|
@ -80,17 +51,11 @@ namespace :searchindex do
|
||||||
Setting.set('es_pipeline', pipeline)
|
Setting.set('es_pipeline', pipeline)
|
||||||
end
|
end
|
||||||
|
|
||||||
# define pipeline_field_attributes
|
|
||||||
# ES 5.6 and nower has no ignore_missing support
|
|
||||||
pipeline_field_attributes = {
|
pipeline_field_attributes = {
|
||||||
ignore_failure: true,
|
ignore_failure: true,
|
||||||
|
ignore_missing: true,
|
||||||
}
|
}
|
||||||
if es_multi_index?
|
|
||||||
pipeline_field_attributes = {
|
|
||||||
ignore_failure: true,
|
|
||||||
ignore_missing: true,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
print 'create pipeline (pipeline)... '
|
print 'create pipeline (pipeline)... '
|
||||||
SearchIndexBackend.processors(
|
SearchIndexBackend.processors(
|
||||||
"_ingest/pipeline/#{pipeline}": [
|
"_ingest/pipeline/#{pipeline}": [
|
||||||
|
@ -136,7 +101,6 @@ namespace :searchindex do
|
||||||
end
|
end
|
||||||
|
|
||||||
task :drop_pipeline, [:opts] => %i[environment searchindex:configured searchindex:version_supported] do |_t, _args|
|
task :drop_pipeline, [:opts] => %i[environment searchindex:configured searchindex:version_supported] do |_t, _args|
|
||||||
next if !es_pipeline?
|
|
||||||
|
|
||||||
# update processors
|
# update processors
|
||||||
pipeline = Setting.get('es_pipeline')
|
pipeline = Setting.get('es_pipeline')
|
||||||
|
@ -181,7 +145,7 @@ namespace :searchindex do
|
||||||
task :version_supported, [:opts] => :environment do |_t, _args|
|
task :version_supported, [:opts] => :environment do |_t, _args|
|
||||||
next if es_version_supported?
|
next if es_version_supported?
|
||||||
|
|
||||||
abort "Your Elasticsearch version is not supported! Please update your version to a greater equal than 5.6.0 (Your current version: #{es_version})."
|
abort "Your Elasticsearch version is not supported! Please update your version to a greater equal than 6.5.0 (Your current version: #{es_version})."
|
||||||
end
|
end
|
||||||
|
|
||||||
task :configured, [:opts] => :environment do |_t, _args|
|
task :configured, [:opts] => :environment do |_t, _args|
|
||||||
|
@ -214,10 +178,7 @@ mapping = {
|
||||||
|
|
||||||
def get_mapping_properties_object(object)
|
def get_mapping_properties_object(object)
|
||||||
|
|
||||||
name = object.name
|
name = '_doc'
|
||||||
if es_multi_index?
|
|
||||||
name = '_doc'
|
|
||||||
end
|
|
||||||
result = {
|
result = {
|
||||||
name => {
|
name => {
|
||||||
properties: {}
|
properties: {}
|
||||||
|
@ -231,13 +192,6 @@ def get_mapping_properties_object(object)
|
||||||
string_raw = { 'type': 'keyword', 'ignore_above': 5012 }
|
string_raw = { 'type': 'keyword', 'ignore_above': 5012 }
|
||||||
boolean_raw = { 'type': 'boolean' }
|
boolean_raw = { 'type': 'boolean' }
|
||||||
|
|
||||||
# for elasticsearch 5.6 and lower
|
|
||||||
if !es_multi_index?
|
|
||||||
string_type = 'string'
|
|
||||||
string_raw = { 'type': 'string', 'index': 'not_analyzed' }
|
|
||||||
boolean_raw = { 'type': 'boolean', 'index': 'not_analyzed' }
|
|
||||||
end
|
|
||||||
|
|
||||||
object.columns_hash.each do |key, value|
|
object.columns_hash.each do |key, value|
|
||||||
if value.type == :string && value.limit && value.limit <= 5000 && store_columns.exclude?(key)
|
if value.type == :string && value.limit && value.limit <= 5000 && store_columns.exclude?(key)
|
||||||
result[name][:properties][key] = {
|
result[name][:properties][key] = {
|
||||||
|
@ -276,46 +230,19 @@ def get_mapping_properties_object(object)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# es with mapper-attachments plugin
|
case object.name
|
||||||
if object.name == 'Ticket'
|
when 'Ticket'
|
||||||
|
|
||||||
# do not server attachments if document is requested
|
|
||||||
result[name][:_source] = {
|
result[name][:_source] = {
|
||||||
excludes: ['article.attachment']
|
excludes: ['article.attachment']
|
||||||
}
|
}
|
||||||
|
result[name][:properties][:article] = {
|
||||||
# for elasticsearch 5.5 and lower
|
type: 'nested',
|
||||||
if !es_pipeline?
|
include_in_parent: true,
|
||||||
result[name][:_source] = {
|
}
|
||||||
excludes: ['article.attachment']
|
when 'KnowledgeBase::Answer::Translation'
|
||||||
}
|
|
||||||
result[name][:properties][:article] = {
|
|
||||||
type: 'nested',
|
|
||||||
include_in_parent: true,
|
|
||||||
properties: {
|
|
||||||
attachment: {
|
|
||||||
type: 'attachment',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if object.name == 'KnowledgeBase::Answer::Translation'
|
|
||||||
# do not server attachments if document is requested
|
|
||||||
result[name][:_source] = {
|
result[name][:_source] = {
|
||||||
excludes: ['attachment']
|
excludes: ['attachment']
|
||||||
}
|
}
|
||||||
|
|
||||||
# for elasticsearch 5.5 and lower
|
|
||||||
if !es_pipeline?
|
|
||||||
result[name][:_source] = {
|
|
||||||
excludes: ['attachment']
|
|
||||||
}
|
|
||||||
result[name][:properties][:attachment] = {
|
|
||||||
type: 'attachment',
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return result if es_type_in_mapping?
|
return result if es_type_in_mapping?
|
||||||
|
@ -335,40 +262,25 @@ def es_version
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def es_version_int
|
||||||
|
number = es_version
|
||||||
|
return 0 if !number
|
||||||
|
|
||||||
|
number_split = es_version.split('.')
|
||||||
|
"#{number_split[0]}#{format('%<minor>03d', minor: number_split[1])}#{format('%<patch>03d', patch: number_split[2])}".to_i
|
||||||
|
end
|
||||||
|
|
||||||
def es_version_supported?
|
def es_version_supported?
|
||||||
version_split = es_version.split('.')
|
|
||||||
version = "#{version_split[0]}#{format('%<minor>03d', minor: version_split[1])}#{format('%<patch>03d', patch: version_split[2])}".to_i
|
|
||||||
|
|
||||||
# only versions greater/equal than 5.6.0 are supported
|
# only versions greater/equal than 6.5.0 are supported
|
||||||
return if version < 5_006_000
|
return if es_version_int < 6_005_000
|
||||||
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
# no es_pipeline for elasticsearch 5.5 and lower
|
|
||||||
def es_pipeline?
|
|
||||||
number = es_version
|
|
||||||
return false if number.blank?
|
|
||||||
return false if number.match?(/^[2-4]\./)
|
|
||||||
return false if number.match?(/^5\.[0-5]\./)
|
|
||||||
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
# no multi index for elasticsearch 5.6 and lower
|
|
||||||
def es_multi_index?
|
|
||||||
number = es_version
|
|
||||||
return false if number.blank?
|
|
||||||
return false if number.match?(/^[2-5]\./)
|
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
# no type in mapping
|
# no type in mapping
|
||||||
def es_type_in_mapping?
|
def es_type_in_mapping?
|
||||||
number = es_version
|
return true if es_version_int < 7_000_000
|
||||||
return true if number.blank?
|
|
||||||
return true if number.match?(/^[2-6]\./)
|
|
||||||
|
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
|
@ -164,17 +164,32 @@ RSpec.describe SearchIndexBackend, searchindex: true do
|
||||||
|
|
||||||
describe '.selectors' do
|
describe '.selectors' do
|
||||||
|
|
||||||
let(:organization1) { create :organization }
|
let(:group1) { create :group }
|
||||||
let(:agent1) { create :agent, organization: organization1 }
|
let(:organization1) { create :organization, note: 'hihi' }
|
||||||
let(:customer1) { create :customer, organization: organization1 }
|
let(:agent1) { create :agent, organization: organization1, groups: [group1] }
|
||||||
let(:ticket1) { create :ticket, title: 'some-title1', state_id: 1, created_by: agent1 }
|
let(:customer1) { create :customer, organization: organization1, firstname: 'special-first-name' }
|
||||||
let(:ticket2) { create :ticket, title: 'some_title2', state_id: 4 }
|
let(:ticket1) do
|
||||||
let(:ticket3) { create :ticket, title: 'some::title3', state_id: 1 }
|
ticket = create :ticket, title: 'some-title1', state_id: 1, created_by: agent1
|
||||||
|
ticket.tag_add('t1', 1)
|
||||||
|
ticket
|
||||||
|
end
|
||||||
|
let(:ticket2) do
|
||||||
|
ticket = create :ticket, title: 'some_title2', state_id: 4
|
||||||
|
ticket.tag_add('t2', 1)
|
||||||
|
ticket
|
||||||
|
end
|
||||||
|
let(:ticket3) do
|
||||||
|
ticket = create :ticket, title: 'some::title3', state_id: 1
|
||||||
|
ticket.tag_add('t1', 1)
|
||||||
|
ticket.tag_add('t2', 1)
|
||||||
|
ticket
|
||||||
|
end
|
||||||
let(:ticket4) { create :ticket, title: 'phrase some-title4', state_id: 1 }
|
let(:ticket4) { create :ticket, title: 'phrase some-title4', state_id: 1 }
|
||||||
let(:ticket5) { create :ticket, title: 'phrase some_title5', state_id: 1 }
|
let(:ticket5) { create :ticket, title: 'phrase some_title5', state_id: 1 }
|
||||||
let(:ticket6) { create :ticket, title: 'phrase some::title6', state_id: 1 }
|
let(:ticket6) { create :ticket, title: 'phrase some::title6', state_id: 1 }
|
||||||
let(:ticket7) { create :ticket, title: 'some title7', state_id: 1 }
|
let(:ticket7) { create :ticket, title: 'some title7', state_id: 1 }
|
||||||
let(:ticket8) { create :ticket, title: 'sometitle', state_id: 1, owner: agent1, customer: customer1 }
|
let(:ticket8) { create :ticket, title: 'sometitle', group: group1, state_id: 1, owner: agent1, customer: customer1, organization: organization1 }
|
||||||
|
let(:article8) { create :ticket_article, ticket: ticket8, subject: 'lorem ipsum' }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
Ticket.destroy_all # needed to remove not created tickets
|
Ticket.destroy_all # needed to remove not created tickets
|
||||||
|
@ -192,11 +207,96 @@ RSpec.describe SearchIndexBackend, searchindex: true do
|
||||||
travel 1.second
|
travel 1.second
|
||||||
ticket7.search_index_update_backend
|
ticket7.search_index_update_backend
|
||||||
travel 1.second
|
travel 1.second
|
||||||
ticket8.search_index_update_backend
|
article8.ticket.search_index_update_backend
|
||||||
described_class.refresh
|
described_class.refresh
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'query with contains' do
|
context 'query with contains' do
|
||||||
|
it 'finds records with tags which contains all' do
|
||||||
|
result = described_class.selectors('Ticket',
|
||||||
|
{ 'ticket.tags'=>{ 'operator' => 'contains all', 'value' => 't1, t2' } },
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
field: 'created_at', # sort to verify result
|
||||||
|
})
|
||||||
|
expect(result).to eq({ count: 1, ticket_ids: [ticket3.id.to_s] })
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'finds records with tags which contains one' do
|
||||||
|
result = described_class.selectors('Ticket',
|
||||||
|
{ 'ticket.tags'=>{ 'operator' => 'contains one', 'value' => 't1, t2' } },
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
field: 'created_at', # sort to verify result
|
||||||
|
})
|
||||||
|
expect(result).to eq({ count: 3, ticket_ids: [ticket3.id.to_s, ticket2.id.to_s, ticket1.id.to_s] })
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'finds records with tags which contains all not' do
|
||||||
|
result = described_class.selectors('Ticket',
|
||||||
|
{ 'ticket.tags'=>{ 'operator' => 'contains all not', 'value' => 't2' } },
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
field: 'created_at', # sort to verify result
|
||||||
|
})
|
||||||
|
expect(result).to eq({ count: 6, ticket_ids: [ticket8.id.to_s, ticket7.id.to_s, ticket6.id.to_s, ticket5.id.to_s, ticket4.id.to_s, ticket1.id.to_s] })
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'finds records with tags which contains one not' do
|
||||||
|
result = described_class.selectors('Ticket',
|
||||||
|
{ 'ticket.tags'=>{ 'operator' => 'contains one not', 'value' => 't1' } },
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
field: 'created_at', # sort to verify result
|
||||||
|
})
|
||||||
|
expect(result).to eq({ count: 6, ticket_ids: [ticket8.id.to_s, ticket7.id.to_s, ticket6.id.to_s, ticket5.id.to_s, ticket4.id.to_s, ticket2.id.to_s] })
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'finds records with organization note' do
|
||||||
|
result = described_class.selectors('Ticket',
|
||||||
|
{
|
||||||
|
'organization.note' => {
|
||||||
|
'operator' => 'contains',
|
||||||
|
'value' => 'hihi',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
field: 'created_at', # sort to verify result
|
||||||
|
})
|
||||||
|
expect(result).to eq({ count: 1, ticket_ids: [ticket8.id.to_s] })
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'finds records with customer firstname' do
|
||||||
|
result = described_class.selectors('Ticket',
|
||||||
|
{
|
||||||
|
'customer.firstname' => {
|
||||||
|
'operator' => 'contains',
|
||||||
|
'value' => 'special',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
field: 'created_at', # sort to verify result
|
||||||
|
})
|
||||||
|
expect(result).to eq({ count: 1, ticket_ids: [ticket8.id.to_s] })
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'finds records with article subject' do
|
||||||
|
result = described_class.selectors('Ticket',
|
||||||
|
{
|
||||||
|
'article.subject' => {
|
||||||
|
'operator' => 'contains',
|
||||||
|
'value' => 'ipsum',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
field: 'created_at', # sort to verify result
|
||||||
|
})
|
||||||
|
expect(result).to eq({ count: 1, ticket_ids: [ticket8.id.to_s] })
|
||||||
|
end
|
||||||
|
|
||||||
it 'finds records with pre_condition not_set' do
|
it 'finds records with pre_condition not_set' do
|
||||||
result = described_class.selectors('Ticket',
|
result = described_class.selectors('Ticket',
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,7 @@ RSpec.describe Chat::Session, type: :model do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'verify chat attribute' do
|
it 'verify chat attribute' do
|
||||||
expect(chat_session.search_index_attribute_lookup['chat']).to eq chat.name
|
expect(chat_session.search_index_attribute_lookup['chat']['name']).to eq chat.name
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,16 +5,7 @@ RSpec.shared_examples 'CanLookupSearchIndexAttributes' do
|
||||||
user = create(:agent, organization: organization)
|
user = create(:agent, organization: organization)
|
||||||
|
|
||||||
value = user.search_index_value_by_attribute('organization_id')
|
value = user.search_index_value_by_attribute('organization_id')
|
||||||
expect(value).to eq('Tomato42')
|
expect(value['name']).to eq('Tomato42')
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '.search_index_value' do
|
|
||||||
it 'returns correct value' do
|
|
||||||
organization = create(:organization, name: 'Tomato42', note: 'special recipe')
|
|
||||||
|
|
||||||
value = organization.search_index_value
|
|
||||||
expect(value).to eq('Tomato42')
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -363,7 +363,7 @@ RSpec.describe 'Search', type: :request, searchindex: true do
|
||||||
expect(json_response['assets']['Organization'][organization_nested.id.to_s]).to be_truthy
|
expect(json_response['assets']['Organization'][organization_nested.id.to_s]).to be_truthy
|
||||||
expect(json_response['assets']['User'][customer_nested.id.to_s]).to be_truthy
|
expect(json_response['assets']['User'][customer_nested.id.to_s]).to be_truthy
|
||||||
|
|
||||||
post '/api/v1/search/User', params: { query: 'organization:Tomato42' }, as: :json
|
post '/api/v1/search/User', params: { query: 'organization.name:Tomato42' }, as: :json
|
||||||
expect(response).to have_http_status(:ok)
|
expect(response).to have_http_status(:ok)
|
||||||
expect(json_response).to be_a_kind_of(Hash)
|
expect(json_response).to be_a_kind_of(Hash)
|
||||||
expect(json_response).to be_truthy
|
expect(json_response).to be_truthy
|
||||||
|
@ -383,7 +383,7 @@ RSpec.describe 'Search', type: :request, searchindex: true do
|
||||||
expect(json_response['assets']['Organization'][organization_nested.id.to_s]).to be_truthy
|
expect(json_response['assets']['Organization'][organization_nested.id.to_s]).to be_truthy
|
||||||
expect(json_response['assets']['User'][customer_nested.id.to_s]).to be_truthy
|
expect(json_response['assets']['User'][customer_nested.id.to_s]).to be_truthy
|
||||||
|
|
||||||
post '/api/v1/search/User', params: { query: 'organization:Cucumber43' }, as: :json
|
post '/api/v1/search/User', params: { query: 'organization.name:Cucumber43' }, as: :json
|
||||||
expect(response).to have_http_status(:ok)
|
expect(response).to have_http_status(:ok)
|
||||||
expect(json_response).to be_a_kind_of(Hash)
|
expect(json_response).to be_a_kind_of(Hash)
|
||||||
expect(json_response).to be_truthy
|
expect(json_response).to be_truthy
|
||||||
|
@ -400,7 +400,7 @@ RSpec.describe 'Search', type: :request, searchindex: true do
|
||||||
expect(json_response['assets']['Organization'][organization_nested.id.to_s]).to be_truthy
|
expect(json_response['assets']['Organization'][organization_nested.id.to_s]).to be_truthy
|
||||||
expect(json_response['assets']['Ticket'][ticket_nested.id.to_s]).to be_truthy
|
expect(json_response['assets']['Ticket'][ticket_nested.id.to_s]).to be_truthy
|
||||||
|
|
||||||
post '/api/v1/search/Ticket', params: { query: 'organization:Tomato42' }, as: :json
|
post '/api/v1/search/Ticket', params: { query: 'organization.name:Tomato42' }, as: :json
|
||||||
expect(response).to have_http_status(:ok)
|
expect(response).to have_http_status(:ok)
|
||||||
expect(json_response).to be_a_kind_of(Hash)
|
expect(json_response).to be_a_kind_of(Hash)
|
||||||
expect(json_response).to be_truthy
|
expect(json_response).to be_truthy
|
||||||
|
@ -418,7 +418,7 @@ RSpec.describe 'Search', type: :request, searchindex: true do
|
||||||
expect(json_response['assets']['Organization'][organization_nested.id.to_s]).to be_truthy
|
expect(json_response['assets']['Organization'][organization_nested.id.to_s]).to be_truthy
|
||||||
expect(json_response['assets']['Ticket'][ticket_nested.id.to_s]).to be_truthy
|
expect(json_response['assets']['Ticket'][ticket_nested.id.to_s]).to be_truthy
|
||||||
|
|
||||||
post '/api/v1/search/Ticket', params: { query: 'organization:Cucumber43' }, as: :json
|
post '/api/v1/search/Ticket', params: { query: 'organization.name:Cucumber43' }, as: :json
|
||||||
expect(response).to have_http_status(:ok)
|
expect(response).to have_http_status(:ok)
|
||||||
expect(json_response).to be_a_kind_of(Hash)
|
expect(json_response).to be_a_kind_of(Hash)
|
||||||
expect(json_response).to be_truthy
|
expect(json_response).to be_truthy
|
||||||
|
|
|
@ -82,14 +82,6 @@ class ElasticsearchTest < ActiveSupport::TestCase
|
||||||
test 'a - objects' do
|
test 'a - objects' do
|
||||||
|
|
||||||
# user
|
# user
|
||||||
attributes = @agent.search_index_data
|
|
||||||
assert_equal('E', attributes['firstname'])
|
|
||||||
assert_equal('S', attributes['lastname'])
|
|
||||||
assert_equal('es-agent@example.com', attributes['email'])
|
|
||||||
assert(attributes['preferences'])
|
|
||||||
assert_not(attributes['password'])
|
|
||||||
assert_not(attributes['organization'])
|
|
||||||
|
|
||||||
attributes = @agent.search_index_attribute_lookup
|
attributes = @agent.search_index_attribute_lookup
|
||||||
assert_equal('E', attributes['firstname'])
|
assert_equal('E', attributes['firstname'])
|
||||||
assert_equal('S', attributes['lastname'])
|
assert_equal('S', attributes['lastname'])
|
||||||
|
@ -104,14 +96,9 @@ class ElasticsearchTest < ActiveSupport::TestCase
|
||||||
assert_equal('es-customer1@example.com', attributes['email'])
|
assert_equal('es-customer1@example.com', attributes['email'])
|
||||||
assert(attributes['preferences'])
|
assert(attributes['preferences'])
|
||||||
assert_not(attributes['password'])
|
assert_not(attributes['password'])
|
||||||
assert_equal('Customer Organization Update', attributes['organization'])
|
assert_equal('Customer Organization Update', attributes['organization']['name'])
|
||||||
|
|
||||||
# organization
|
# organization
|
||||||
attributes = @organization1.search_index_data
|
|
||||||
assert_equal('Customer Organization Update', attributes['name'])
|
|
||||||
assert_equal('some note', attributes['note'])
|
|
||||||
assert_not(attributes['members'])
|
|
||||||
|
|
||||||
attributes = @organization1.search_index_attribute_lookup
|
attributes = @organization1.search_index_attribute_lookup
|
||||||
assert_equal('Customer Organization Update', attributes['name'])
|
assert_equal('Customer Organization Update', attributes['name'])
|
||||||
assert_equal('some note', attributes['note'])
|
assert_equal('some note', attributes['note'])
|
||||||
|
@ -150,15 +137,15 @@ class ElasticsearchTest < ActiveSupport::TestCase
|
||||||
)
|
)
|
||||||
|
|
||||||
attributes = ticket1.search_index_attribute_lookup
|
attributes = ticket1.search_index_attribute_lookup
|
||||||
assert_equal('Users', attributes['group'])
|
assert_equal('Users', attributes['group']['name'])
|
||||||
assert_equal('new', attributes['state'])
|
assert_equal('new', attributes['state']['name'])
|
||||||
assert_equal('2 normal', attributes['priority'])
|
assert_equal('2 normal', attributes['priority']['name'])
|
||||||
|
|
||||||
assert_equal('ES', attributes['customer']['firstname'])
|
assert_equal('ES', attributes['customer']['firstname'])
|
||||||
assert_equal('Customer1', attributes['customer']['lastname'])
|
assert_equal('Customer1', attributes['customer']['lastname'])
|
||||||
assert_equal('es-customer1@example.com', attributes['customer']['email'])
|
assert_equal('es-customer1@example.com', attributes['customer']['email'])
|
||||||
assert_not(attributes['customer']['password'])
|
assert_not(attributes['customer']['password'])
|
||||||
assert_equal('Customer Organization Update', attributes['customer']['organization'])
|
assert_nil(attributes['customer']['organization'])
|
||||||
|
|
||||||
assert_equal('-', attributes['owner']['login'])
|
assert_equal('-', attributes['owner']['login'])
|
||||||
assert_equal('-', attributes['owner']['firstname'])
|
assert_equal('-', attributes['owner']['firstname'])
|
||||||
|
@ -466,7 +453,7 @@ class ElasticsearchTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
result = Ticket.search(
|
result = Ticket.search(
|
||||||
current_user: @agent,
|
current_user: @agent,
|
||||||
query: 'state:open',
|
query: 'state.name:open',
|
||||||
limit: 15,
|
limit: 15,
|
||||||
)
|
)
|
||||||
assert(result[0], 'record 1')
|
assert(result[0], 'record 1')
|
||||||
|
|
Loading…
Reference in a new issue