This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
class PostSimilarity < ApplicationRecord
|
||||||
|
belongs_to :post, class_name: 'Post', foreign_key: 'post_id'
|
||||||
|
belongs_to :target_post, class_name: 'Post', foreign_key: 'target_post_id'
|
||||||
|
end
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class CreatePostSimilarities < ActiveRecord::Migration[7.0]
|
||||||
|
def change
|
||||||
|
create_table :post_similarities do |t|
|
||||||
|
t.references :post, null: false, foreign_key: { to_table: :posts }
|
||||||
|
t.references :target_post, null: false, foreign_key: { to_table: :posts }
|
||||||
|
t.float :cos, null: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class CreateTagSimilarities < ActiveRecord::Migration[7.0]
|
||||||
|
def change
|
||||||
|
create_table :tag_similarities do |t|
|
||||||
|
t.references :tag, null: false, foreign_key: { to_table: :tags }
|
||||||
|
t.references :target_tag, null: false, foreign_key: { to_table: :tags }
|
||||||
|
t.float :cos, null: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Generated
+21
-1
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[8.0].define(version: 2025_06_29_140234) do
|
ActiveRecord::Schema[8.0].define(version: 2025_07_29_210600) do
|
||||||
create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", null: false
|
||||||
t.string "record_type", null: false
|
t.string "record_type", null: false
|
||||||
@@ -55,6 +55,14 @@ ActiveRecord::Schema[8.0].define(version: 2025_06_29_140234) do
|
|||||||
t.index ["tag_id"], name: "index_nico_tag_relations_on_tag_id"
|
t.index ["tag_id"], name: "index_nico_tag_relations_on_tag_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "post_similarities", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||||
|
t.bigint "post_id", null: false
|
||||||
|
t.bigint "target_post_id", null: false
|
||||||
|
t.float "cos", null: false
|
||||||
|
t.index ["post_id"], name: "index_post_similarities_on_post_id"
|
||||||
|
t.index ["target_post_id"], name: "index_post_similarities_on_target_post_id"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "post_tags", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
create_table "post_tags", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||||
t.bigint "post_id", null: false
|
t.bigint "post_id", null: false
|
||||||
t.bigint "tag_id", null: false
|
t.bigint "tag_id", null: false
|
||||||
@@ -97,6 +105,14 @@ ActiveRecord::Schema[8.0].define(version: 2025_06_29_140234) do
|
|||||||
t.index ["tag_id"], name: "index_tag_aliases_on_tag_id"
|
t.index ["tag_id"], name: "index_tag_aliases_on_tag_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "tag_similarities", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||||
|
t.bigint "tag_id", null: false
|
||||||
|
t.bigint "target_tag_id", null: false
|
||||||
|
t.float "cos", null: false
|
||||||
|
t.index ["tag_id"], name: "index_tag_similarities_on_tag_id"
|
||||||
|
t.index ["target_tag_id"], name: "index_tag_similarities_on_target_tag_id"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "tags", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
create_table "tags", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", null: false
|
||||||
t.string "category", default: "general", null: false
|
t.string "category", default: "general", null: false
|
||||||
@@ -148,6 +164,8 @@ ActiveRecord::Schema[8.0].define(version: 2025_06_29_140234) do
|
|||||||
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
|
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
|
||||||
add_foreign_key "nico_tag_relations", "tags"
|
add_foreign_key "nico_tag_relations", "tags"
|
||||||
add_foreign_key "nico_tag_relations", "tags", column: "nico_tag_id"
|
add_foreign_key "nico_tag_relations", "tags", column: "nico_tag_id"
|
||||||
|
add_foreign_key "post_similarities", "posts"
|
||||||
|
add_foreign_key "post_similarities", "posts", column: "target_post_id"
|
||||||
add_foreign_key "post_tags", "posts"
|
add_foreign_key "post_tags", "posts"
|
||||||
add_foreign_key "post_tags", "tags"
|
add_foreign_key "post_tags", "tags"
|
||||||
add_foreign_key "post_tags", "users", column: "created_user_id"
|
add_foreign_key "post_tags", "users", column: "created_user_id"
|
||||||
@@ -156,6 +174,8 @@ ActiveRecord::Schema[8.0].define(version: 2025_06_29_140234) do
|
|||||||
add_foreign_key "posts", "users", column: "uploaded_user_id"
|
add_foreign_key "posts", "users", column: "uploaded_user_id"
|
||||||
add_foreign_key "settings", "users"
|
add_foreign_key "settings", "users"
|
||||||
add_foreign_key "tag_aliases", "tags"
|
add_foreign_key "tag_aliases", "tags"
|
||||||
|
add_foreign_key "tag_similarities", "tags"
|
||||||
|
add_foreign_key "tag_similarities", "tags", column: "target_tag_id"
|
||||||
add_foreign_key "user_ips", "ip_addresses"
|
add_foreign_key "user_ips", "ip_addresses"
|
||||||
add_foreign_key "user_ips", "users"
|
add_foreign_key "user_ips", "users"
|
||||||
add_foreign_key "user_post_views", "posts"
|
add_foreign_key "user_post_views", "posts"
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
namespace :post_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
|
||||||
|
|
||||||
|
posts = Post.includes(:tags).to_a
|
||||||
|
posts.each_with_index do |post, i|
|
||||||
|
existence_of_tags = post.tags.index_with(1)
|
||||||
|
((i + 1)...posts.size).each do |j|
|
||||||
|
target_post = posts[j]
|
||||||
|
existence_of_target_tags = target_post.tags.index_with(1)
|
||||||
|
PostSimilarity.find_or_initialize_by(post:, target_post:).tap { |ps|
|
||||||
|
ps.cos = cos.(existence_of_tags, existence_of_target_tags)
|
||||||
|
}.save!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user