Skip to content

Commit

Permalink
SwimmerStat query fix: wasn't getting the proper min FIN score right;…
Browse files Browse the repository at this point in the history
… split fulltext indexes for Meeting, UserWorkshop & Team: search individual columns instead of groups to yield better results; rel. 0.7.09
  • Loading branch information
steveoro committed Apr 15, 2024
1 parent 00d8e4a commit a306f2e
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 42 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

_Please, add the latest build info on top of the list; use Version::MAJOR only after gold release; keep semantic versioning in line with framework's_

- **0.7.09** [Steve A.] SwimmerStat query fix: wasn't getting the proper min FIN score right;
- **0.7.09** [Steve A.] SwimmerStat query fix: wasn't getting the proper min FIN score right; split fulltext indexes for Meeting, UserWorkshop & Team: search individual columns instead of groups to yield better results
- **0.7.08** [Steve A.] added some delegation helpers to Badge; added triggers and events to MariaDB dump file generated by "db:dump" (even if not currently used); minor rubocop fixes & bundle updates
- **0.7.06** [Steve A.] query fix for SwimmerStat
- **0.7.00** [Steve A.] update to Rails 6.1; specs adjustments
Expand Down
14 changes: 7 additions & 7 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
goggles_db (0.7.08)
goggles_db (0.7.09)
acts-as-taggable-on
acts_as_votable
cities
Expand Down Expand Up @@ -137,7 +137,7 @@ GEM
crass (1.0.6)
date (3.3.4)
debug_inspector (1.2.0)
devise (4.9.3)
devise (4.9.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
Expand Down Expand Up @@ -274,7 +274,7 @@ GEM
net-smtp (0.5.0)
net-protocol
nio4r (2.7.1)
nokogiri (1.16.3-x86_64-linux)
nokogiri (1.16.4-x86_64-linux)
racc (~> 1.4)
notiffany (0.1.3)
nenv (~> 0.1)
Expand Down Expand Up @@ -392,7 +392,7 @@ GEM
rspec_pacman_formatter (0.1.7)
colorize
rspec
rubocop (1.63.0)
rubocop (1.63.1)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
Expand Down Expand Up @@ -423,7 +423,7 @@ GEM
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
rubocop-rspec_rails (~> 2.28)
rubocop-rspec_rails (2.28.2)
rubocop-rspec_rails (2.28.3)
rubocop (~> 1.40)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
Expand Down Expand Up @@ -454,7 +454,7 @@ GEM
hashie
version_gem (~> 1.1, >= 1.1.1)
sparkr (0.4.1)
spring (4.1.3)
spring (4.2.0)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
spring-commands-rubocop (0.4.0)
Expand All @@ -472,7 +472,7 @@ GEM
sync (0.5.0)
sysexits (1.2.0)
temple (0.10.3)
term-ansicolor (1.7.2)
term-ansicolor (1.8.0)
tins (~> 1.0)
thor (1.3.1)
tilt (2.3.0)
Expand Down
9 changes: 5 additions & 4 deletions app/models/goggles_db/meeting.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module GogglesDb
#
# = Meeting model
#
# - version: 7-0.6.30
# - version: 7-0.7.09
# - author: Steve A.
#
class Meeting < AbstractMeeting
Expand Down Expand Up @@ -75,9 +75,10 @@ class Meeting < AbstractMeeting
scope :for_name, lambda { |name|
like_query = "%#{name}%"
includes(:edition_type)
.where('MATCH(meetings.description, meetings.code) AGAINST(?)', name)
.or(includes([:edition_type]).where('meetings.description like ?', like_query))
.or(includes([:edition_type]).where('meetings.code like ?', like_query))
.where('MATCH(meetings.description) AGAINST(?)', name)
.or(where('meetings.description like ?', like_query))
.or(where('MATCH(meetings.code) AGAINST(?)', name))
.or(where('meetings.code like ?', like_query))
.by_date(:desc)
}
scope :for_team, lambda { |team|
Expand Down
17 changes: 9 additions & 8 deletions app/models/goggles_db/swimmer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ module GogglesDb
#
# = Swimmer model
#
# - version: 7-0.5.10
# - author: Steve A.
# - build: 20220804
# - version: 7-0.7.09
# - author: Steve A.
#
class Swimmer < ApplicationRecord
self.table_name = 'swimmers'
Expand Down Expand Up @@ -51,11 +50,13 @@ class Swimmer < ApplicationRecord
# Fulltext search with additional domain inclusion by using standard "LIKE"s
scope :for_name, lambda { |name|
like_query = "%#{name}%"
where(
'(MATCH(swimmers.last_name, swimmers.first_name, swimmers.complete_name) AGAINST(?)) OR ' \
'(swimmers.last_name LIKE ?) OR (swimmers.first_name LIKE ?) OR (swimmers.complete_name LIKE ?)',
name, like_query, like_query, like_query
).order(:complete_name, :year_of_birth)
# NOTE: Avoid/don't use:
# 1. "MATCH(swimmers.complete_name)" => yields too many different results for short names
# 2. 'CONCAT(swimmers.first_name, swimmers.last_name) LIKE ?' => doesn't work well
# 3. order(:last_name) or (:complete_name) => alters the result list moving best matches away from the top
where('swimmers.complete_name LIKE ?', like_query)
.or(where('MATCH(swimmers.last_name) AGAINST(?)', name))
.or(where('swimmers.last_name LIKE ?', like_query))
}
scope :for_first_name, ->(name) { where('swimmers.first_name like ?', "%#{name}%") }
scope :for_last_name, ->(name) { where('swimmers.last_name like ?', "%#{name}%") }
Expand Down
13 changes: 7 additions & 6 deletions app/models/goggles_db/team.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module GogglesDb
#
# = Team model
#
# - version: 7-0.6.30
# - version: 7-0.7.09
# - author: Steve A.
#
class Team < ApplicationRecord
Expand Down Expand Up @@ -55,11 +55,12 @@ class Team < ApplicationRecord
# Fulltext search by name with additional domain inclusion by using standard "LIKE"s
scope :for_name, lambda { |name|
like_query = "%#{name}%"
where(
'(MATCH(teams.name, teams.editable_name, teams.name_variations) AGAINST(?)) OR ' \
'(teams.name LIKE ?) OR (teams.editable_name LIKE ?) OR (teams.name_variations LIKE ?)',
name, like_query, like_query, like_query
)
where('MATCH(teams.name) AGAINST(?)', name)
.or(where('MATCH(teams.editable_name) AGAINST(?)', name))
.or(where('MATCH(teams.name_variations) AGAINST(?)', name))
.or(where('teams.name like ?', like_query))
.or(where('teams.editable_name like ?', like_query))
.or(where('teams.name_variations like ?', like_query))
}

# TODO: CLEAR UNUSED
Expand Down
17 changes: 12 additions & 5 deletions app/models/goggles_db/user_workshop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module GogglesDb
#
# = UserWorkshop model
#
# - version: 7-0.6.30
# - version: 7-0.7.09
# - author: Steve A.
#
# Allows to manage user-driven or team-driven swimming workshops
Expand Down Expand Up @@ -53,10 +53,17 @@ class UserWorkshop < AbstractMeeting
# Fulltext search with additional domain inclusion by using standard "LIKE"s
scope :for_name, lambda { |name|
like_query = "%#{name}%"
includes([:edition_type])
.where('MATCH(user_workshops.description, user_workshops.code) AGAINST(?)', name)
.or(includes([:edition_type]).where('user_workshops.description like ?', like_query))
.or(includes([:edition_type]).where('user_workshops.code like ?', like_query))
# TODO: split fulltext index into 2 fields for better results; in the meantime, just use a simple LIKE
# includes([:edition_type])
# .where('MATCH(user_workshops.description, user_workshops.code) AGAINST(?)', name)
# .or(includes([:edition_type]).where('user_workshops.description like ?', like_query))
# .or(includes([:edition_type]).where('user_workshops.code like ?', like_query))
# .by_date(:desc)
includes(:edition_type)
.where('MATCH(user_workshops.description) AGAINST(?)', name)
.or(where('user_workshops.description like ?', like_query))
.or(where('MATCH(user_workshops.code) AGAINST(?)', name))
.or(where('user_workshops.code like ?', like_query))
.by_date(:desc)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

class AddSplitFulltextIndexesForMeetingAndWorkshops < ActiveRecord::Migration[6.1]
def self.up
execute('CREATE FULLTEXT INDEX meeting_code ON meetings(code);')
execute('CREATE FULLTEXT INDEX meeting_desc ON meetings(description);')
execute('CREATE FULLTEXT INDEX workshop_code ON user_workshops(code);')
execute('CREATE FULLTEXT INDEX workshop_desc ON user_workshops(description);')
execute('CREATE FULLTEXT INDEX team_only_name ON teams(name);')
execute('CREATE FULLTEXT INDEX team_editable_name ON teams(editable_name);')
execute('CREATE FULLTEXT INDEX team_name_variations ON teams(name_variations);')
end

def self.down
execute('ALTER TABLE meetings DROP INDEX meeting_code;')
execute('ALTER TABLE meetings DROP INDEX meeting_desc;')
execute('ALTER TABLE user_workshops DROP INDEX workshop_code;')
execute('ALTER TABLE user_workshops DROP INDEX workshop_desc;')
execute('ALTER TABLE teams DROP INDEX team_only_name;')
execute('ALTER TABLE teams DROP INDEX team_editable_name;')
execute('ALTER TABLE teams DROP INDEX team_name_variations;')
end
end
17 changes: 17 additions & 0 deletions db/migrate/20240415111509_update_db_version_to_20702.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

require 'goggles_db/version'

class UpdateDbVersionTo20702 < ActiveRecord::Migration[6.1]
def self.up
# --- Update DB structure versioning:
GogglesDb::AppParameter.versioning_row.update(
GogglesDb::AppParameter::FULL_VERSION_FIELDNAME => GogglesDb::Version::FULL,
GogglesDb::AppParameter::DB_VERSION_FIELDNAME => GogglesDb::Version::DB
)
end

def self.down
# (no-op)
end
end
4 changes: 2 additions & 2 deletions lib/goggles_db/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ module Version
MAJOR = '0'
MINOR = '7'
PATCH = '09'
BUILD = '20240412'
BUILD = '20240415'

# Full label
FULL = "#{MAJOR}.#{MINOR}.#{PATCH} (#{CORE}-#{BUILD})".freeze

# Compact label
SEMANTIC = "#{MAJOR}.#{MINOR}.#{PATCH}".freeze
DB = '2.07.1' # Internal DB structure (frozen @ <minor>.<patch>.<seq> from last migration)
DB = '2.07.2' # Internal DB structure (frozen @ <minor>.<patch>.<seq> from last migration)

# Pointless UNICODE emojis (just for fun):
EMOJI_BUTTERFLY = 'з== ( ▀ ͜͞ʖ▀) ==ε'
Expand Down
4 changes: 2 additions & 2 deletions lib/tasks/db_dump_rebuild_reset.rake
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require 'fileutils'
#
# = Local Deployment helper tasks
#
# - (p) FASAR Software 2007-2020
# - (p) FASAR Software 2007-2024
# - for Goggles framework vers.: 7.00
# - author: Steve A.
#
Expand Down Expand Up @@ -131,7 +131,7 @@ namespace :db do
# (The Resulting SQL file will be much longer, though -- but the bzipped
# version can result more compressed due to the replicated strings, and it is
# indeed much more readable and editable...)
cmd = "mysqldump --host=#{db_host} -u #{db_user} --password=\"#{db_pwd}\" --add-drop-table --triggers " \
cmd = "mysqldump --host=#{db_host} -u #{db_user} --password=\"#{db_pwd}\" --add-drop-table " \
"--routines --events --triggers --single-transaction #{db_name} >> #{file_name}"
sh cmd
append_sql_transaction_footer(file_name)
Expand Down
22 changes: 15 additions & 7 deletions spec/dummy/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2024_03_01_123811) do
ActiveRecord::Schema.define(version: 2024_04_15_111509) do

create_table "achievement_rows", id: :integer, charset: "utf8mb3", collation: "utf8mb3_general_ci", force: :cascade do |t|
t.integer "lock_version", default: 0
Expand Down Expand Up @@ -865,7 +865,7 @@
t.integer "team_affiliation_id"
t.integer "entry_time_type_id"
t.string "disqualification_notes"
t.integer "meeting_relay_swimmers_count"
t.integer "meeting_relay_swimmers_count", default: 0, null: false
t.index ["disqualification_code_type_id"], name: "idx_mrr_disqualification_code_type"
t.index ["entry_time_type_id"], name: "fk_meeting_relay_results_entry_time_types"
t.index ["meeting_program_id", "rank"], name: "results_x_relay"
Expand All @@ -886,12 +886,13 @@
t.integer "seconds", limit: 2, default: 0
t.integer "hundredths", limit: 2, default: 0
t.integer "meeting_relay_result_id"
t.integer "length_in_meters", default: 0
t.integer "minutes_from_start", limit: 3, default: 0
t.integer "seconds_from_start", limit: 2, default: 0
t.integer "hundredths_from_start", limit: 2, default: 0
t.integer "relay_laps_count"
t.integer "length_in_meters", default: 0, null: false
t.integer "minutes_from_start", limit: 3, default: 0, null: false
t.integer "seconds_from_start", limit: 2, default: 0, null: false
t.integer "hundredths_from_start", limit: 2, default: 0, null: false
t.integer "relay_laps_count", default: 0, null: false
t.index ["badge_id"], name: "fk_meeting_relay_swimmers_badges"
t.index ["length_in_meters"], name: "index_meeting_relay_swimmers_on_length_in_meters"
t.index ["meeting_relay_result_id"], name: "fk_meeting_relay_swimmers_meeting_relay_results"
t.index ["relay_order"], name: "relay_order"
t.index ["stroke_type_id"], name: "fk_meeting_relay_swimmers_stroke_types"
Expand Down Expand Up @@ -1006,7 +1007,9 @@
t.decimal "event_fee", precision: 10, scale: 2
t.decimal "relay_fee", precision: 10, scale: 2
t.index ["code", "edition"], name: "idx_meetings_code"
t.index ["code"], name: "meeting_code", type: :fulltext
t.index ["description", "code"], name: "meeting_name", type: :fulltext
t.index ["description"], name: "meeting_desc", type: :fulltext
t.index ["edition_type_id"], name: "fk_meetings_edition_types"
t.index ["entry_deadline"], name: "index_meetings_on_entry_deadline"
t.index ["header_date"], name: "idx_meetings_header_date"
Expand Down Expand Up @@ -1462,8 +1465,11 @@
t.string "home_page_url", limit: 150
t.index ["city_id"], name: "fk_teams_cities"
t.index ["editable_name"], name: "index_teams_on_editable_name"
t.index ["editable_name"], name: "team_editable_name", type: :fulltext
t.index ["name", "editable_name", "name_variations"], name: "team_name", type: :fulltext
t.index ["name"], name: "index_teams_on_name"
t.index ["name"], name: "team_only_name", type: :fulltext
t.index ["name_variations"], name: "team_name_variations", type: :fulltext
end

create_table "timing_types", id: :integer, charset: "utf8mb3", collation: "utf8mb3_general_ci", force: :cascade do |t|
Expand Down Expand Up @@ -1684,7 +1690,9 @@
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["code"], name: "index_user_workshops_on_code"
t.index ["code"], name: "workshop_code", type: :fulltext
t.index ["description", "code"], name: "workshop_name", type: :fulltext
t.index ["description"], name: "workshop_desc", type: :fulltext
t.index ["edition_type_id"], name: "index_user_workshops_on_edition_type_id"
t.index ["header_date"], name: "index_user_workshops_on_header_date"
t.index ["header_year"], name: "index_user_workshops_on_header_year"
Expand Down

0 comments on commit a306f2e

Please sign in to comment.