From b309263df5b2655221e3f6416813f3da8bea11c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=BF=E3=81=A6=E3=82=8B=E3=81=9E?= Date: Wed, 7 Jan 2026 03:25:27 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=96=A2=E8=81=AF=E3=82=BF=E3=82=B0?= =?UTF-8?q?=EF=BC=88#92=EF=BC=89=20(#197)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge branch 'main' into #92 Merge remote-tracking branch 'origin/main' into #92 #92 Co-authored-by: miteruzo Reviewed-on: https://git.miteruzo.com/miteruzo/btrc-hub/pulls/197 --- backend/app/models/tag_similarity.rb | 4 +++ backend/lib/tasks/calc_tag_similarities.rake | 28 ++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 backend/app/models/tag_similarity.rb create mode 100644 backend/lib/tasks/calc_tag_similarities.rake 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