diff --git a/backend/app/models/tag_similarity.rb b/backend/app/models/tag_similarity.rb new file mode 100644 index 0000000..d983409 --- /dev/null +++ b/backend/app/models/tag_similarity.rb @@ -0,0 +1,4 @@ +class TagSimilarity < ApplicationRecord + belongs_to :tag, class_name: 'Tag', foreign_key: 'tag_id' + belongs_to :target_tag, class_name: 'Tag', foreign_key: 'target_tag_id' +end diff --git a/backend/lib/tasks/calc_tag_similarities.rake b/backend/lib/tasks/calc_tag_similarities.rake new file mode 100644 index 0000000..9e16977 --- /dev/null +++ b/backend/lib/tasks/calc_tag_similarities.rake @@ -0,0 +1,28 @@ +namespace :tag_similarity do + desc '関聯タグ・テーブル作成' + task calc: :environment do + dot = -> a, b { (a.keys & b.keys).sum { |k| a[k] * b[k] } } + norm = -> v { Math.sqrt(v.values.sum { |e| e * e }) } + cos = -> a, b do + na = norm.(a) + nb = norm.(b) + if na.zero? || nb.zero? + 0.0 + else + dot.(a, b) / na / nb + end + end + + tags = Tag.includes(:posts).to_a + tags.each_with_index do |tag, i| + existence_of_posts = tag.posts.index_with(1) + ((i + 1)...tags.size).each do |j| + target_tag = tags[j] + existence_of_target_posts = target_tag.posts.index_with(1) + TagSimilarity.find_or_initialize_by(tag:, target_tag:).tap { |ts| + ts.cos = cos.(existence_of_posts, existence_of_target_posts) + }.save! + end + end + end +end