{"id":1060,"date":"2019-04-04T07:24:50","date_gmt":"2019-04-04T14:24:50","guid":{"rendered":"https:\/\/www.kenwalger.com\/blog\/?p=1060"},"modified":"2019-04-11T07:12:52","modified_gmt":"2019-04-11T14:12:52","slug":"building-with-patterns-the-tree-pattern","status":"publish","type":"post","link":"https:\/\/www.kenwalger.com\/blog\/nosql\/mongodb\/building-with-patterns-the-tree-pattern\/","title":{"rendered":"Building with Patterns: The Tree Pattern"},"content":{"rendered":"\n<p>Many of the schema design patterns we&#8217;ve covered so far have stressed that saving time on JOIN operations is a benefit. Data that&#8217;s accessed together should be stored together and some data duplication is okay. A schema design pattern like <a href=\"https:\/\/www.mongodb.com\/blog\/post\/building-with-patterns-the-extended-reference-pattern\">Extended Reference<\/a> is a good example. However, what if the data to be joined is hierarchical? For example, you would like to identify the reporting chain from an employee to the CEO? MongoDB provides the <a href=\"https:\/\/docs.mongodb.com\/manual\/reference\/operator\/aggregation\/graphLookup\/\">$graphLookup<\/a> operator to navigate the data as graphs, and that could be one solution. However, if you need to do a lot of queries of this hierarchical data structure, you may want to apply the same rule of storing together data that is accessed together. This is where we can use the Tree Pattern.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Tree Pattern<\/h3>\n\n\n\n<p>There are many ways to represent a tree in a legacy tabular database. The most common ones are for a node in the graph to list its parent and for a node to list its children. Both of these representations may require multiple access to build the chain of nodes.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/webassets.mongodb.com\/_com_assets\/cms\/treeparentnodes-s72igr8b20.png?w=840&#038;ssl=1\" alt=\"Corporate structure with parent nodes\"\/><\/figure>\n\n\n\n<p style=\"text-align:center\"><em>Corporate structure with Parent nodes<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/webassets.mongodb.com\/_com_assets\/cms\/treechildnodes2-wsdhl1w7vz.png?w=840&#038;ssl=1\" alt=\"Corporate structure with Child nodes\"\/><\/figure>\n\n\n\n<p style=\"text-align:center\"><em>Corporate structure with Child nodes<\/em><\/p>\n\n\n\n<p>Alternatively, we could store the full path from a node to the top of the hierarchy. In this case, we&#8217;d basically be storing the &#8220;parents&#8221; for each node. In a tabular database, it would likely be done by encoding a list of the parents. The approach in MongoDB is to simply represent this as an array.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/webassets.mongodb.com\/_com_assets\/cms\/documenttreeparents-5ujytbwk4c.png?resize=408%2C342&#038;ssl=1\" alt=\"Image of a document with parent nodes\" width=\"408\" height=\"342\"\/><\/figure><\/div>\n\n\n\n<p>As can be seen here, in this representation there is some data duplication. If the information is relatively static, like in genealogy, your parents and ancestors won&#8217;t change making this array easy to manage. However, in our corporate structure example, when things change and there is restructuring, you will need to update the hierarchy as needed. This is still a small cost compared to the benefits you can gain from not calculating the trees all the time.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Sample Use Case<\/h3>\n\n\n\n<p>Product catalogs are another very good example of using the Tree pattern. Often products belong to categories, which are part of other categories. For example, a Solid State Drive may be under <em>Hard Drives<\/em>, which is under <em>Storage<\/em>, which is under <em>Computer Parts<\/em>. Occasionally the organization of the categories may change, but not too frequently.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webassets.mongodb.com\/_com_assets\/cms\/documenttreeancestors-4fgwdlhd1z.png \" alt=\"IImage of a document with parent and ancestor nodes\" width=\"404\" height=\"342\"\/><\/figure><\/div>\n\n\n\n<p>Note in the document above the <code>ancestor_categories<\/code> field which keeps track of the entire hierarchy. We also have the field <code>parent_category<\/code>. Duplicating the immediate parent in these two fields is a best practice we&#8217;ve developed after working with many customers using the Tree Pattern. Including the &#8220;parent&#8221; field is often handy, especially if you need to maintain the ability to use $graphLookup on your documents.<\/p>\n\n\n\n<p>Keeping the ancestors in an array provides the ability to create a multi-key index on those values. It allows for all descendants of a given category to be easily found. As for the immediate children, they are accessible by looking at the documents that have our given category as its immediate &#8220;parent&#8221;. We just told you that this field would be handy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Conclusion<\/h3>\n\n\n\n<p>As for many patterns, there is often a tradeoff between simplicity and performance when using them. In the case of the tree pattern, you get better performance by avoiding multiple joins, however, you will need to manage the updates to your graph.<\/p>\n\n\n\n<p>The next post in this series will look at the <em><a href=\"https:\/\/www.kenwalger.com\/blog\/nosql\/mongodb\/building-with-patterns-the-preallocation-pattern\/\">Pre-Allocation Pattern<\/a><\/em>.<\/p>\n\n\n\n<p>If you have questions, please leave comments below. <\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Previous Parts of Building with Patterns:<\/h4>\n\n\n\n<ul class=\"wp-block-list\"><li>The <a href=\"https:\/\/www.mongodb.com\/blog\/post\/building-with-patterns-the-polymorphic-pattern\">Polymorphic<\/a> pattern<\/li><li>The <a href=\"https:\/\/www.mongodb.com\/blog\/post\/building-with-patterns-the-attribute-pattern\">Attribute<\/a> pattern<\/li><li>The <a href=\"https:\/\/www.mongodb.com\/blog\/post\/building-with-patterns-the-bucket-pattern\">Bucket<\/a> pattern<\/li><li>The <a href=\"https:\/\/www.mongodb.com\/blog\/post\/building-with-patterns-the-outlier-pattern\">Outlier<\/a> pattern<\/li><li>The <a href=\"https:\/\/www.mongodb.com\/blog\/post\/building-with-patterns-the-computed-pattern\">Computed<\/a> pattern<\/li><li>The <a href=\"https:\/\/www.mongodb.com\/blog\/post\/building-with-patterns-the-subset-pattern\">Subset<\/a> pattern<\/li><li>The <a href=\"https:\/\/www.mongodb.com\/blog\/post\/building-with-patterns-the-extended-reference-pattern\">Extended Reference<\/a> pattern<\/li><li>The <a href=\"https:\/\/www.mongodb.com\/blog\/post\/building-with-patterns-the-approximation-reference-pattern\">Approximation<\/a> pattern<\/li><\/ul>\n<a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-facebook nolightbox\" data-provider=\"facebook\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Facebook\" href=\"https:\/\/www.facebook.com\/sharer.php?u=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F1060&#038;t=Building%20with%20Patterns%3A%20The%20Tree%20Pattern&#038;s=100&#038;p&#091;url&#093;=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F1060&#038;p&#091;images&#093;&#091;0&#093;=https%3A%2F%2Fwebassets.mongodb.com%2F_com_assets%2Fcms%2Ftreeparentnodes-s72igr8b20.png&#038;p&#091;title&#093;=Building%20with%20Patterns%3A%20The%20Tree%20Pattern\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" alt=\"Facebook\" title=\"Share on Facebook\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/i0.wp.com\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/facebook.png?resize=48%2C48&#038;ssl=1\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-twitter nolightbox\" data-provider=\"twitter\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Twitter\" href=\"https:\/\/twitter.com\/intent\/tweet?url=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F1060&#038;text=Hey%20check%20this%20out\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" alt=\"twitter\" title=\"Share on Twitter\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/i0.wp.com\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/twitter.png?resize=48%2C48&#038;ssl=1\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-reddit nolightbox\" data-provider=\"reddit\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Reddit\" href=\"https:\/\/www.reddit.com\/submit?url=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F1060&#038;title=Building%20with%20Patterns%3A%20The%20Tree%20Pattern\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" alt=\"reddit\" title=\"Share on Reddit\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/i0.wp.com\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/reddit.png?resize=48%2C48&#038;ssl=1\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-linkedin nolightbox\" data-provider=\"linkedin\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Linkedin\" href=\"https:\/\/www.linkedin.com\/shareArticle?mini=true&#038;url=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F1060&#038;title=Building%20with%20Patterns%3A%20The%20Tree%20Pattern\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" alt=\"linkedin\" title=\"Share on Linkedin\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/i0.wp.com\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/linkedin.png?resize=48%2C48&#038;ssl=1\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-mail nolightbox\" data-provider=\"mail\" rel=\"nofollow\" title=\"Share by email\" href=\"mailto:?subject=Building%20with%20Patterns%3A%20The%20Tree%20Pattern&#038;body=Hey%20check%20this%20out:%20https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F1060\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" alt=\"mail\" title=\"Share by email\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/i0.wp.com\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/mail.png?resize=48%2C48&#038;ssl=1\" \/><\/a>","protected":false},"excerpt":{"rendered":"<p>Many of the schema design patterns we&#8217;ve covered so far have stressed that saving time on JOIN operations is a benefit. Data that&#8217;s accessed together should be stored together and some data duplication is okay. A schema design pattern like Extended Reference is a good example. However, what if the data to be joined is &hellip; <a href=\"https:\/\/www.kenwalger.com\/blog\/nosql\/mongodb\/building-with-patterns-the-tree-pattern\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Building with Patterns: The Tree Pattern&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"pmpro_default_level":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[785,1581],"yst_prominent_words":[1572,1571,99,1573,360,1545,1576,1578,1575,1070,1579,507,783,1154,1574,1580,950,1569,1577,1570],"class_list":["post-1060","post","type-post","status-publish","format-standard","hentry","category-mongodb","tag-schema-design","tag-tree-pattern","pmpro-has-access"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8lx70-h6","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/posts\/1060","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/comments?post=1060"}],"version-history":[{"count":2,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/posts\/1060\/revisions"}],"predecessor-version":[{"id":1073,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/posts\/1060\/revisions\/1073"}],"wp:attachment":[{"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/media?parent=1060"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/categories?post=1060"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/tags?post=1060"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/yst_prominent_words?post=1060"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}