Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement search options to enable more performant queries #2752

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions lib/administrate/field/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ def self.searchable?
false
end

def self.search_exact?
false
end

def self.search_lower?
true
end

def self.search_requires_string_cast?
true
end

def self.field_type
to_s.split("::").last.underscore
end
Expand Down
20 changes: 20 additions & 0 deletions lib/administrate/field/deferred.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,26 @@ def searchable?
end
end

def search_exact?
if options.key?(:getter)
false
else
options.fetch(:search_exact, deferred_class.search_exact?)
end
end

def search_lower?
if options.key?(:getter)
false
else
options.fetch(:searchable, deferred_class.searchable?)
end
end

def search_requires_string_cast?
deferred_class.search_requires_string_cast?
end

def searchable_field
Administrate.deprecator.warn(
"searchable_field is deprecated, use searchable_fields instead"
Expand Down
4 changes: 4 additions & 0 deletions lib/administrate/field/email.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ class Email < Field::Base
def self.searchable?
true
end

def search_requires_string_cast?
false
end
end
end
end
4 changes: 4 additions & 0 deletions lib/administrate/field/string.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def self.searchable?
true
end

def search_requires_string_cast?
false
end

def truncate
data.to_s[0...truncation_length]
end
Expand Down
4 changes: 4 additions & 0 deletions lib/administrate/field/text.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def self.searchable?
false
end

def search_requires_string_cast?
false
end

def truncate
data.to_s[0...truncation_length]
end
Expand Down
4 changes: 4 additions & 0 deletions lib/administrate/field/url.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def self.searchable?
true
end

def search_requires_string_cast?
false
end

def truncate
data.to_s[0...truncation_length]
end
Expand Down
29 changes: 25 additions & 4 deletions lib/administrate/search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,18 @@ def query_template
search_attributes.map do |attr|
table_name = query_table_name(attr)
searchable_fields(attr).map do |field|
attribute_type = attribute_types[attr]
column_name = column_to_query(field)
"LOWER(CAST(#{table_name}.#{column_name} AS CHAR(256))) LIKE ?"

search_target = "#{table_name}.#{column_name}"
search_target = "CAST(#{search_target} AS CHAR(256))" if attribute_type.search_requires_string_cast?
search_target = "LOWER(#{search_target})" if attribute_type.search_lower?

if attribute_types[attr].search_exact?
"#{search_target} = ?"
else
"#{search_target} LIKE ?"
end
end.join(" OR ")
end.join(" OR ")
end
Expand All @@ -100,10 +110,21 @@ def searchable_fields(attr)
end

def query_values
fields_count = search_attributes.sum do |attr|
searchable_fields(attr).count
search_attributes.flat_map do |attr|
attribute_type = attribute_types[attr]

search_term = if attribute_type.search_lower?
term.mb_chars.downcase
else
term.mb_chars
end

if attribute_type.search_exact?
[search_term] * searchable_fields(attr).count
else
["%#{search_term}%"] * searchable_fields(attr).count
end
end
["%#{term.mb_chars.downcase}%"] * fields_count
end

def search_attributes
Expand Down