{"id":1209,"date":"2012-08-21T11:45:32","date_gmt":"2012-08-21T11:45:32","guid":{"rendered":"http:\/\/bicortex.com\/?p=1209"},"modified":"2012-08-24T05:25:47","modified_gmt":"2012-08-24T05:25:47","slug":"how-to-implement-slowly-changing-dimensions-part-1-using-default-scd-ssis-component-to-load-dimension-data","status":"publish","type":"post","link":"http:\/\/bicortex.com\/bicortex\/how-to-implement-slowly-changing-dimensions-part-1-using-default-scd-ssis-component-to-load-dimension-data\/","title":{"rendered":"How to implement Slowly Changing Dimensions \u2013 Part 1. Using default SCD SSIS component to load dimension data"},"content":{"rendered":"<p style=\"text-align: justify;\">This is the first post to the short series (3 more posts) which aims at briefly outlining the concept of slowly changing dimensions (SCD) and how to implement SCD through a variety of methods. In this post (part 1) will endeavour to show and explain the concept of SCD and how to populate a dimension table using the most commonly used method \u2013 SQL Server Integration Services and SCD component. SCD component in SSIS has been designed specifically to integrate source and target data in a dimension in such way that the historical values can be preserved and maintained according to three types of tracking commonly available to a designer or developer:<\/p>\n<ul>\n<li style=\"text-align: justify;\">Type 0 &#8211; it manages dimensional changes and an action is performed. Values remain as they were at the time of the dimension record was first inserted. In certain circumstances history is preserved with a Type 0. High order types are employed to guarantee the preservation of history whereas Type 0 provides the least or no control<\/li>\n<li style=\"text-align: justify;\">\u00a0Type 1 &#8211; it overwrites old with new data, and therefore does not track historical data. Its common uses are for misspelled names<\/li>\n<li>\u00a0Type 2 &#8211; tracks historical data by creating multiple records for a given natural key in the dimensional tables with separate surrogate keys and\/or different version numbers. Unlimited history is preserved for each insert<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">As this post does not serve as a detailed explanation of the differences and\/or similarities between different SCD types other than the basics above, if you are not comfortable with dimensional modelling concepts and want to find out more about SCD methodology, please refer to other sources.<\/p>\n<p style=\"text-align: justify;\">Let\u2019s start with creating some foundations for our SSIS package \u2013 tables, constraints etc. which will also be used in subsequent posts to avoid repetition. First, let\u2019s create out data source which will imitate the relational database tables and their content by creating some database objects and populating them with some dummy data as per the script below.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\n--CREATE RELATIONAL TABLES AND CONSTRAINTS. POPULATE TABLES WITH SOME DUMMY DATA\r\nCREATE TABLE Customer(\r\nCustomerID int IDENTITY (1,1),\r\nFirst_Name varchar (50) NOT NULL,\r\nMiddle_Name varchar (50),\r\nLast_Name varchar (50) NOT NULL,\r\nEmail_Address varchar (100) NULL,\r\nPhone_Number varchar (50) NULL,\r\nCreated_Date datetime NOT NULL,\r\nModified_Date datetime NULL,\r\nCONSTRAINT pk_CustID PRIMARY KEY (CustomerID))\r\n\r\nCREATE TABLE Address(\r\nAddressID int IDENTITY (1,1) NOT NULL,\r\nAddress1 varchar (50) NOT NULL,\r\nAddress2 varchar (50) NULL,\r\nCity varchar (50) NOT NULL,\r\nPost_Code char (4) NULL,\r\nIs_Current_Flag char(1) NOT NULL,\r\nCONSTRAINT pk_AddressID PRIMARY KEY (AddressID))\r\n\r\nCREATE TABLE Customer_Address_Bridge(\r\nCustomerID int NOT NULL,\r\nAddressID int NOT NULL)\r\n\r\nGO\r\n\r\nINSERT INTO Customer\r\n(First_Name, Middle_Name, Last_Name,Email_Address,Phone_Number,Created_Date,Modified_Date)\r\nSELECT 'Mary', 'Joeanne', 'Black', 'mary0120@yahoo.com.au', '03-8573-9455', '2012-01-01', NULL UNION ALL\r\nSELECT 'John', 'Lorance', 'Moore', 'johnnym@awol.com', '03-3423-1155', '2012-01-01', '2012-05-30' UNION ALL\r\nSELECT 'Martin', NULL, 'Laser', 'mlaser91@aol.com', '03-2355-1109', '2012-01-01', '2012-05-12' UNION ALL\r\nSELECT 'Spencer', 'Chris', 'McEvans', 'spencerdude@hotmail.com', '03-1122-0007', '2012-01-01', '2012-05-30' UNION ALL\r\nSELECT 'Mark', NULL, 'King', 'mk038722@gmail.com', '03-3423-1155', '2012-01-01', '2012-05-30' UNION ALL\r\nSELECT 'Mary', 'Susan', 'Grey', 'mmgrey@gmail.com', '03-1299-3859', '2012-01-01', NULL UNION ALL\r\nSELECT 'Luis', 'Blake', 'Shimaro', 'shimarolou@yahoo.com.au', '03-0385-3999', '2012-01-01', NULL UNION ALL\r\nSELECT 'Natalie', 'G', 'Chin', 'nataliechin@mediasmarts.com.au', '03-3759-1001', '2012-01-01', NULL UNION ALL\r\nSELECT 'Marian', NULL, 'McErin', 'marianmcerin@gmail.com', '03-3400-3331', '2012-01-01', '2012-05-01' UNION ALL\r\nSELECT 'Rick', 'Tony', 'Webster', 'rikky69@gmail.com', '03-9459-1112', '2012-01-01', NULL\r\n\r\nINSERT INTO Address\r\n(Address1, Address2, City, Post_Code, Is_Current_Flag)\r\nSELECT '6 Agave Street', 'Apartment 4A', 'Launceston', '7250', 'Y' UNION ALL\r\nSELECT '88 Dodge Street', NULL, 'Sunshine', '3020', 'Y' UNION ALL\r\nSELECT '3 McKenzie Court', 'Level 9', 'Perthville', '2795', 'Y' UNION ALL\r\nSELECT '5 Spencer Drive', 'Unit 9D', 'Melbourne', '3002', 'Y' UNION ALL\r\nSELECT '8 Sunny Avenue', NULL, 'Sydney', '2000', 'Y' UNION ALL\r\nSELECT '83 Mara Drive', NULL, 'Echuca', '3563', 'Y' UNION ALL\r\nSELECT '1038 Mustang Street', NULL, 'Brisbane', '4000', 'Y' UNION ALL\r\nSELECT '1 Bradman Street', NULL, 'Bendigo', '3550', 'Y' UNION ALL\r\nSELECT '12 Cruger Drive', 'Block C', 'Cairns', '4870', 'Y' UNION ALL\r\nSELECT '124 Lasting Court', NULL, 'Adelaide', '5000', 'Y'\r\n\r\nINSERT INTO Customer_Address_Bridge\r\n(CustomerID, AddressID)\r\nSELECT 1, 1 UNION ALL\r\nSELECT 2,2 UNION ALL\r\nSELECT 3,3 UNION ALL\r\nSELECT 4,4 UNION ALL\r\nSELECT 5,5 UNION ALL\r\nSELECT 6,6 UNION ALL\r\nSELECT 7,7 UNION ALL\r\nSELECT 8,8 UNION ALL\r\nSELECT 9,9 UNION ALL\r\nSELECT 10, 10\r\n\r\n--CREATE CONSTRAINTS\r\nALTER TABLE Customer_Address_Bridge\r\nADD FOREIGN KEY (AddressID) REFERENCES Address(AddressID)\r\nALTER TABLE Customer_Address_Bridge\r\nADD FOREIGN KEY (CustomerID) REFERENCES Customer(CustomerID)\r\n\r\nGO\r\n\r\n--CREATE DIMENSION 'DimCustomer' TABLE\r\nCREATE TABLE DimCustomer(\r\nCustomerSK int IDENTITY (1,1) NOT NULL,\r\nCustomerID int NULL,\r\nFirst_Name varchar (50) NULL,\r\nLast_Name varchar (50) NULL,\r\nEmail_Address varchar (100) NULL,\r\nCity varchar (50) NULL,\r\nDT_Valid_From datetime NULL,\r\nDT_Valid_To datetime NULL,\r\nIs_Current bit NULL,\r\nCONSTRAINT PK_DimCustomer PRIMARY KEY CLUSTERED (CustomerSK asc))\r\n<\/pre>\n<p style=\"text-align: justify;\">All we have done here is created 3 tables which will imitate the source of data for our customer dimension, populated them with some made up dummy data and finally created our dimensions table which will act as our target object. If you want you can query the data and when the three source tables are linked you should get the following output for the schema.<\/p>\n<p><a href=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_Source_Tbl_Schema.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1211\" title=\"SCD_Part1_Source_Tbl_Schema\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_Source_Tbl_Schema.png\" alt=\"\" width=\"580\" height=\"210\" srcset=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/08\/SCD_Part1_Source_Tbl_Schema.png 580w, http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/08\/SCD_Part1_Source_Tbl_Schema-300x108.png 300w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/a><br \/>\nNow, onto the SSIS package. For this post I will be using SQL Server 2012 but these steps should be compatible with version 2008 and 2005. First, let\u2019s create a solution and from the toolbar place a Data Flow Task onto the Control Flow pane. Next, go to Data Flow view and drop an OLE DB Source and Slowly Changing Dimension components onto the pane and link them together so the whole solution looks like the one below.<\/p>\n<p><a href=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_DataFlow_Start.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1216\" title=\"SCD_Part1_SSIS_DataFlow_Start\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_DataFlow_Start.png\" alt=\"\" width=\"580\" height=\"58\" srcset=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/08\/SCD_Part1_SSIS_DataFlow_Start.png 580w, http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/08\/SCD_Part1_SSIS_DataFlow_Start-300x30.png 300w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">It is time to adjust some properties and kick off the SCD wizard. First, in OLE DB Source container create a database connection pointing to where we created all the objects as per the script above, from the \u2018Data Access Mode\u2019 choose \u2018SQL Command\u2019 and type in the following query.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nSELECT cu.CustomerID, cu.First_Name,\r\ncu.Last_Name, ad.City,\r\ncu.Email_Address\r\nFROM dbo.Address AS ad INNER JOIN\r\ndbo.Customer_Address_Bridge AS br ON ad.AddressID = br.AddressID INNER JOIN\r\ndbo.Customer AS cu ON br.CustomerID = cu.CustomerID\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1223\" title=\"SCD_Part1_SSIS_DataFlow_OLEDB_SQL\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_DataFlow_OLEDB_SQL.png\" alt=\"\" width=\"580\" height=\"296\" srcset=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/08\/SCD_Part1_SSIS_DataFlow_OLEDB_SQL.png 580w, http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/08\/SCD_Part1_SSIS_DataFlow_OLEDB_SQL-300x153.png 300w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/p>\n<p style=\"text-align: justify;\">The output from the above SQL code will become our base for populating our \u2018DimCustomer\u2019 dimension via SCD. Next, click on \u2018Slowly Changing Dimension\u2019 container which will start a wizard driven development. We will use the same connection as per our previous OLE DB query and for \u2018Table or View\u2019 property we will select our previously defined \u2018DimCustomer\u2019 table. Also, in this section we need to define the unique key business key which will help the wizard and all subsequent loads to differentiate between the new, changed and unchanged data being pumped into our dimension table. For this purpose we will use \u2018CustomerID\u2019 column.<\/p>\n<p style=\"text-align: justify;\"><a href=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_Wizard1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1225\" title=\"SCD_Part1_SSIS_Wizard1\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_Wizard1.png\" alt=\"\" width=\"580\" height=\"483\" srcset=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/08\/SCD_Part1_SSIS_Wizard1.png 580w, http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/08\/SCD_Part1_SSIS_Wizard1-300x249.png 300w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">In the next screen we will need to define which attributes will undergo which type of change (if any) if the new\/modified version of the data is found in the source tables. For this demo let\u2019s allow \u2018City\u2019, \u2018Last_Name\u2019 and \u2018First_Name\u2019 columns to be of Type 2 SCD (new record will be created if a change is detected) whereas \u2018Email_Address\u2019 data will be overwritten with a newer version if a change is found \u2013 Type 1 SCD as per below.<\/p>\n<p><a href=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_Wizard2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1226\" title=\"SCD_Part1_SSIS_Wizard2\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_Wizard2.png\" alt=\"\" width=\"580\" height=\"474\" srcset=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/08\/SCD_Part1_SSIS_Wizard2.png 580w, http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/08\/SCD_Part1_SSIS_Wizard2-300x245.png 300w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Don\u2019t worry too much for the options in the next screen, click \u2018Next\u2019. Finally, in the last lot of proprieties we will need to define if we will use a single field (\u2018Is_Current\u2019 in this case) or a set of dates (\u2018DT_Valid_From\u2019 and \u2018DT_Valid_To\u2019 in this case) for our changed attributes to track history. Let\u2019s go with dates and select \u2018DT_Valid_From\u2019 as a \u2018Start Date Column\u2019 and \u2018DT_Valid_To\u2019 as an \u2018End Date Column\u2019. These columns will be populated as the data in the updated row gets expired to allow for history tracking. We can also select a specific row to act as a flag indicating whether an attribute is valid or no. Another property that needs to be adjusted (providing we select start and end dates to identify expired rows) is \u2018Variable to set date values\u2019 field which can use system based variables. For this exercise we will use \u2018System: :StartTime\u2019 variable.<\/p>\n<p style=\"text-align: justify;\"><a href=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_Wizard3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1227\" title=\"SCD_Part1_SSIS_Wizard3\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_Wizard3.png\" alt=\"\" width=\"580\" height=\"472\" srcset=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/08\/SCD_Part1_SSIS_Wizard3.png 580w, http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/08\/SCD_Part1_SSIS_Wizard3-300x244.png 300w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Lastly, specify support for inferred members and choose the columns that the inferred member record contains. When loading measures into a fact table, you can create minimal records for inferred members that do not yet exist. Later, when meaningful data is available, the dimension records can be updated. Go with default options here and click \u2018Finish\u2019 to complete the wizard. This will build a bunch of other containers and update the solution with the necessary transformations based on the selections from the wizard. When finished, the solution in the \u2018Date Flow\u2019 should look as per below.<\/p>\n<p style=\"text-align: center;\"><a href=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_DataFlow_End.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter  wp-image-1228\" title=\"SCD_Part1_SSIS_DataFlow_End\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_DataFlow_End.png\" alt=\"\" width=\"580\" height=\"300\" \/><br \/>\n<\/a><\/p>\n<p>Let\u2019s run the solution and see what the output in the destination table is (DimCustomer table).<\/p>\n<p style=\"text-align: center;\"><a href=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_First_Run_Output.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter  wp-image-1229\" title=\"SCD_Part1_SSIS_First_Run_Output\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_First_Run_Output.png\" alt=\"\" width=\"580\" height=\"155\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Now, to understand how changes are applied to this dimension by means of utilising SCD methodology which we have just implemented via the SSIS package let\u2019s commit some updates to our source tables, run the package again and see what comes out at the \u2018other end\u2019. First, execute the following UPDATE statements to alter source data.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\n--UPDATE TABLE Customer\r\nUPDATE Customer\r\nSET First_Name = 'zzzzzzz' WHERE customerid = 4\r\n\r\nUPDATE Customer\r\nSET Email_Address = 'zzzzzzz@yyy.com' WHERE CustomerID = 8\r\n<\/pre>\n<p style=\"text-align: justify;\">Now run the package again and when successfully finished, query the DimCustomer dimension table and identify the changes committed through the SCD components.<\/p>\n<p style=\"text-align: center;\"><a href=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_Second_Run_Output.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter  wp-image-1231\" title=\"SCD_Part1_SSIS_Second_Run_Output\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/08\/SCD_Part1_SSIS_Second_Run_Output.png\" alt=\"\" width=\"580\" height=\"165\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">What we can observe here is how individual attributes and their corresponding rows underwent an update based on the types of SCD implemented in the package as we went through the wizard options. First thing to notice is how we updated \u2018Customer_Email\u2019 attribute. If you recall from the wizard and the options we were facing when determining whether to make this column Type 0, 1 or 2 SCD attribute, we marked it as type 1 i.e. we only wanted its content for the given \u2018CustomerID\u2019 updated or overwritten with new values rather than creating another row. Secondly, for \u2018First_Name\u2019, \u2018Last_Name\u2019 and \u2018City\u2019 attributes, when change is detected, we decided that a new record should be created when a change is found. Looking at the UPDATE statements again the first UPDATE referred to Type 2 SCD and second UPDATE to Type 1 SCD. Now, when you examine the output from the DimCustomer table as per image above you will notice that those conditions were met as per our expectations (you can click on the image to enlarge it). Customer with the \u2018CustomerID\u2019 of 4 had his first name updated from \u2018Spencer\u2019 to \u2018zzzzzz\u2019 by means of creating a new record and populating the \u2018DT_Valid_To\u2019 datetime field with an expiry date. Also, according to our second UPDATE statement, customer with a \u2018CustomerID\u2019 of 8 had her e-mail address updated to \u2018zzzzzzz@yyy.com\u2019 but the old e-mail address did not persist and no new record was created as per Type 1 SCD methodology.<\/p>\n<p style=\"text-align: justify;\">As you can see, SSIS SCD component provides an easy and convenient way to populate dimension table without any code or creating complex transformations \u2013 it\u2019s all wizard driven and takes literally seconds to implement. One thing that we need to remember though is that this convenience comes with the burden of the lack of flexibility and possible performance issues when dealing with large volumes of data. I haven\u2019t conducted any comprehensive tests which would prove or contradict this theory, however there notion in the industry is to avoid SCD SSIS component when dealing with dimensions which contain numerous records due to the way SSIS processes the data. The Slowly Changing Dimension transformation performs row by row updates to your table, so if you have a dimension table with hundreds of thousands of rows, this could be a very inefficient method. There are other inefficiencies to consider (see <a href=\"http:\/\/dimensionmergescd.codeplex.com\/wikipage?title=SCD%20Wizard%20Disadvantages&amp;referringTitle=Home\" target=\"_blank\">HERE<\/a>) when using this default option as opposed to other alternatives but it is this component\u2019s slow processing that makes it unsuitable for recordsets longer than 1000 rows. With large data volumes it is unacceptable for each incoming row of data to issues a SQL command to check against the reference (or Dimension) table in the database to compare the incoming row against its corresponding row in the reference (you can watch this happening in SQL profiler). This isn\u2019t a problem for small reference tables, but once you start processing thousands of incoming rows against tables with thousands of reference rows, performance starts to drag, because it is doing these row by row checks. The only performance tuning option you have at your disposal is to index the Business Key in the reference table. Luckily, there are other options which I will describe in the next few posts to this series.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is the first post to the short series (3 more posts) which aims at briefly outlining the concept of slowly changing dimensions (SCD) and how to implement SCD through a variety of methods. In this post (part 1) will endeavour to show and explain the concept of SCD and how to populate a dimension [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[32,5,50],"tags":[12,49,13],"class_list":["post-1209","post","type-post","status-publish","format-standard","hentry","category-how-tos","category-sql","category-ssis","tag-code","tag-sql","tag-ssis"],"aioseo_notices":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"http:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/posts\/1209","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/comments?post=1209"}],"version-history":[{"count":35,"href":"http:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/posts\/1209\/revisions"}],"predecessor-version":[{"id":1386,"href":"http:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/posts\/1209\/revisions\/1386"}],"wp:attachment":[{"href":"http:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/media?parent=1209"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/categories?post=1209"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/tags?post=1209"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}