autocomplete: recognize Japanese tags in autocomplete.

Allowing typing Japanese tags in autocomplete. For example, typing 東方
in autocomplete will be completed to the touhou tag. Typing ぶくぶ will
complete to the bkub tag.

This works using wiki page and artist other names. Effectively, any name
listed as an other name in a wiki or artist page will be treated like an
alias for autocomplete purposes. This is limited to non-ASCII other names,
to prevent English other names from interfering with regular tag searches.
This commit is contained in:
evazion
2020-12-14 16:48:21 -06:00
parent 23f6b8a46d
commit c02c31b966
3 changed files with 50 additions and 2 deletions

View File

@@ -72,8 +72,11 @@ class AutocompleteService
results = results.uniq.sort_by { |r| [r[:antecedent].length, -r[:post_count]] }.take(limit)
elsif string.include?("*")
results = tag_matches(string)
results = tag_other_name_matches(string) if results.blank?
else
results = tag_matches(string + "*")
string += "*"
results = tag_matches(string)
results = tag_other_name_matches(string) if results.blank?
results = tag_autocorrect_matches(string) if results.blank?
end
@@ -81,6 +84,8 @@ class AutocompleteService
end
def tag_matches(string)
return [] if string =~ /[^[:ascii:]]/
name_matches = Tag.nonempty.name_matches(string).order(post_count: :desc).limit(limit)
alias_matches = Tag.nonempty.alias_matches(string).order(post_count: :desc).limit(limit)
union = "((#{name_matches.to_sql}) UNION (#{alias_matches.to_sql})) AS tags"
@@ -100,6 +105,7 @@ class AutocompleteService
end
def tag_autocorrect_matches(string)
string = string.delete("*")
tags = Tag.nonempty.autocorrect_matches(string).limit(limit)
tags.map do |tag|
@@ -107,6 +113,21 @@ class AutocompleteService
end
end
def tag_other_name_matches(string)
return [] unless string =~ /[^[:ascii:]]/
artists = Artist.undeleted.any_other_name_like(string)
wikis = WikiPage.undeleted.other_names_match(string)
tags = Tag.where(name: wikis.select(:title)).or(Tag.where(name: artists.select(:name)))
tags = tags.nonempty.order(post_count: :desc).limit(limit).includes(:wiki_page, :artist)
tags.map do |tag|
other_names = tag.artist&.other_names.to_a + tag.wiki_page&.other_names.to_a
antecedent = other_names.find { |other_name| other_name.ilike?(string) }
{ type: "tag", label: tag.pretty_name, value: tag.name, category: tag.category, post_count: tag.post_count, antecedent: antecedent }
end
end
def autocomplete_metatag(metatag, value)
results = case metatag.to_sym
when :user, :approver, :commenter, :comm, :noter, :noteupdater, :commentaryupdater,

View File

@@ -45,7 +45,7 @@ class WikiPage < ApplicationRecord
def other_names_match(name)
if name =~ /\*/
subquery = WikiPage.from("unnest(other_names) AS other_name").where_ilike("other_name", name)
subquery = WikiPage.from("unnest(other_names) AS other_name").where_ilike("other_name", normalize_other_name(name))
where(id: subquery)
else
other_names_include(name)

View File

@@ -97,6 +97,33 @@ class AutocompleteServiceTest < ActiveSupport::TestCase
assert_autocomplete_includes("mole_under_eye", "~/mue", :tag_query)
end
should "autocomplete tags from wiki and artist other names" do
create(:tag, name: "touhou")
create(:tag, name: "bkub", category: Tag.categories.artist)
create(:wiki_page, title: "touhou", other_names: %w[東方 东方 동방])
create(:artist, name: "bkub", other_names: %w[大川ぶくぶ フミンバイン])
assert_autocomplete_equals(["touhou"], "", :tag_query)
assert_autocomplete_equals(["touhou"], "", :tag_query)
assert_autocomplete_equals(["touhou"], "", :tag_query)
assert_autocomplete_equals(["touhou"], "*東*", :tag_query)
assert_autocomplete_equals(["touhou"], "東*", :tag_query)
assert_autocomplete_equals([], "*東", :tag_query)
assert_autocomplete_equals(["touhou"], "*方*", :tag_query)
assert_autocomplete_equals(["touhou"], "*方", :tag_query)
assert_autocomplete_equals([], "", :tag_query)
assert_autocomplete_equals(["bkub"], "*大*", :tag_query)
assert_autocomplete_equals(["bkub"], "", :tag_query)
assert_autocomplete_equals([], "*大", :tag_query)
assert_autocomplete_equals(["bkub"], "*川*", :tag_query)
assert_autocomplete_equals([], "*川", :tag_query)
assert_autocomplete_equals([], "", :tag_query)
end
should "autocomplete wildcard searches" do
create(:tag, name: "mole", post_count: 150)
create(:tag, name: "mole_under_eye", post_count: 100)