SlideShare uma empresa Scribd logo
1 de 20
Baixar para ler offline
いまさらツリー構造
2018.06.28 Meguro.rb #16
Yuya Taki
self.inspect
[1] https://github.com/muramurasan/okuribito [2] http://poject.herokuapp.com/
➢ gemのロゴを書いたり…
➢ たまにQiitaの記事を書いたり…
➢ 新卒で某SIerに就職
➢ 渋谷の企業にてRuby on Railsを学ぶ
➢ 今はお客さんに謝りに行くお仕事
Name : Yuya Taki
GitHub : yuyasat
Qiita : yuyasat
[1]
若輩者ですので、何卒優しくご教授いただければと
思います。
(commitはしていない)
➢ ○よ○よ風ゲームをReact.jsで実装し
たり
[2]
最近の知人Nとの会話
最近YouTubeばかりみてるんだけど。
うちの娘もヒカキンヒカキン言ってる。
だけど動画多くてわかりにくいし、わかりやすくカテゴリ分
けしたい。
アーティストのYouTubeページ行くといろんなのがあっ
て、ミュージックPVだけ集めたい。YouTubeの音楽チャ
ンネルあるけどちゃうねん。
おk。
知人N
知人N
知人N
いい感じにカテゴリ分けできるサイトつくって。
サイト名は決めたから。
知人N
作ってみた
https://super-youtuber.com/
カテゴリの実装
https://super-youtuber.com/
はじめてのカテゴリ実装
節点(node)
葉(leaf)
枝(edge)
根(root)
➢ こんな感じのツリー構造やろ
➢ カテゴリなんていろんなところで実装されてるし余裕っしょ
➢ rubyにはancestryというgemがあるらしい
➢ 親idを持たせとけばいいっしょ
id name parent_id
1 スポーツ NULL
2 野球 1
3 サッカー 1
➢ ancestryはrootまでの経路を全部持たせるらしい
➢ 冗長じゃない?更新面倒じゃない?
➢ やっぱりこれでいけない?→
id name path
1 スポーツ NULL
2 野球 /1
3 高校野球 /1/2
➢ とりあえずgemとか調べてみるか
RDBにおける木構造の実装方法
➢ 隣接リストモデル
○ 今回実装したのがこれ。
○ SQLアンチパターン第二章ナイーブツリー。
➢ 経路列挙モデル
○ ancestryでの実装。
➢ 入れ子集合(整数)モデル
➢ 入れ子区間(実数)モデル
○ ミック「データ型の制度という物理制約さえなければRDBで階層構造を扱う方法論として
は、検索/更新のパフォーマンスとモデルの簡潔さの双方において最も優れている」[1]
○ でも複雑さは一番大きい。
➢ 閉包テーブルモデル
○ 経路情報をもつテーブルを作る。
節点(node)
葉(leaf)
枝(edge)
根(root)
[1] 達人に学ぶDB設計徹底指南書p291
各実装の特徴
設計 テーブル数 子孫アクセス ツリーへのク
エリ実行
挿入 削除 参照整合性維
持
隣接リスト 1 簡単 難しい
※再帰クエリ
を使えば簡単
簡単 簡単
※場合による
可能
経路列挙 1 簡単 簡単 簡単 簡単 不可
入れ子 1 難しい 難しい 難しい 難しい 不可
閉包テーブル 2 簡単 簡単 簡単 簡単 可能
[1] SQLアンチパターンp30 [2] SQLアンチパターンp18
[1]
アンチパターンといいつつ、再帰処理ができれば用いても良い [2]
経路列挙モデルが跋扈してたので原点に戻って隣接リストモデルで実装してみた。
子ノードをもつノードを安易に削除できない
before_destroy do
return unless children.present?
errors.add(:base, '紐づいている子カテゴリを削除してください ')
throw :abort
end
節点(node)
葉(leaf)
枝(edge)
根(root)
➢ validationしてしまう
子孫(サブツリー)の取得
➢ rubyで再帰処理で解決!
def descendants(category = self, array = [], include_self: true, only_id: true)
array << (only_id ? self.id : self) if include_self && id == category.id
return array + [only_id ? category.id : category] if category.children.blank?
category.children.eager_load(:children).each do |cat|
array << (only_id ? cat.id : cat)
descendants(cat, array)
end
array
end
➢ SQLでもかける(後述)
先祖を取得するメソッドと子孫を取得するメソッド
class Category < ApplicationRecord
belongs_to :parent, class_name: 'Category', foreign_key: :parent_id
has_many :children, class_name: 'Category', foreign_key: :parent_id
def ancestors(category = self, result = [], include_self: true, only_id: true)
return result + [only_id ? category.id : category] if category.root?
ancestors(category.parent, result, only_id: only_id) +
(!include_self && id == category.id ? [] : [only_id ? category.id : category])
end
def descendants(category = self, array = [], include_self: true, only_id: true)
array << (only_id ? self.id : self) if include_self && id == category.id
return array + [only_id ? category.id : category] if category.children.blank?
category.children.eager_load(:children).each do |cat|
array << (only_id ? cat.id : cat)
descendants(cat, array)
end
array
end
end
先祖を取得
子孫を取得
ancestryのインスタンスメソッドとの対応
ancestry 隣接リストモデル
parent parent
parent_id parent_id
root ancestors(only_id: false).first
root_id ancestors.first
root? parent_id == 0
ancestors ancestors(include_self: false, only_id: false)
ancestors? ancestors.length > 1
ancestor_ids ancestors(include_self: false)
path ancestors(only_id: false)
path_ids ancestors
children children
child_ids children.pluck(:id)
has_parent? parent_id != 0 or self.class.exists?(id: parent_id)
has_children? children.exists?
childless? !children.exists?
https://github.com/stefankroes/ancestry
ancestry 隣接リストモデル
siblings parent&.children || self.class.ro
sibling_ids siblings.pluck(:id)
has_siblings? siblings.exists?
only_child? siblings.count == 1
descendants
descendants(include_self: false,
only_id: false)
descendant_ids descendants(include_self: false)
subtree descendants(only_id: false)
subtree_ids descendants
depth ancestors.count - 1
With `WITH RECURSIVE`
def ancestors(include_self: true)
ids = Category.find_by_sql(<<-SQL).map(&:id) - (include_self ? [] : [id])
WITH RECURSIVE ancestors(id, parent_id) as (
SELECT
categories.id,
categories.parent_id
FROM
categories
WHERE
categories.id = #{id}
UNION ALL
SELECT
categories.id,
categories.parent_id
FROM
ancestors,
categories
WHERE
ancestors.parent_id = categories.id
)
SELECT id FROM ancestors;
SQL
self.class.where(id: ids).order(ids.map { |id| "categories.id = #{id} desc" })
end
With `WITH RECURSIVE`
def descendants(include_self: true)
ids = Category.find_by_sql(<<-SQL).map(&:id) - (include_self ? [] : [id])
WITH RECURSIVE children(id, parent_id) as (
SELECT
categories.id,
categories.parent_id
FROM
categories
WHERE
categories.id = #{id}
UNION ALL
SELECT
categories.id,
categories.parent_id
FROM
categories,
children
WHERE
children.id = categories.parent_id
)
SELECT id FROM children;
SQL
self.class.where(id: ids).order(ids.map { |id| "categories.id = #{id} desc" })
end
まとめ
➢ 隣接リストモデルでも、再帰処理を用いることで先祖も子孫も簡単に取
得できる。
➢ 再帰処理のメソッド2つ(ancestrorsとdescendants)を押さえておけば
良い。
ツリー構造の実装は要件に応じて計画的に。
資料
SQLアンチパターン
達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ
RDBでツリー構造
[PostgreSQL 8.4+] WITH RECURSIVEの動作を理解する
木構造の親または子を再帰的に取得する
SQLアンチパターン - ナイーブツリー
Railsでツリー構造をもったカテゴリを隣接リストモデルで実装する
ご静聴ありがとうございました。
隣接リストモデル
カテゴリ 親
科目 NULL
数学 科目
物理 科目
力学 物理
波動 物理
熱力学 物理
物理
熱力学
科目
数学
力学 波動
経路列挙モデル
物理
熱力学
科目
数学
力学 波動
カテゴリ 経路
科目 NULL
数学 /科目
物理 /科目
力学 /科目/物理
波動 /科目/物理
熱力学 /科目/物理
入れ子集合モデル
科目
物理
力学 波動 熱力学
数学
1
2 3 4
5 6 7 8 9 10
11
12
カテゴリ 左端 右端
科目 1 12
数学 2 3
物理 4 11
力学 5 6
波動 7 8
熱力学 9 10

Mais conteúdo relacionado

Destaque

How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
ThinkNow
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
Kurio // The Social Media Age(ncy)
 

Destaque (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

いまさらツリー構造