SharePoint 2010 now provides us the ability to attach metadata to almost all the items that exists in SharePoint. We can now manage what terms are created and how we associate it. This new feature is achieved using "Managed Metadata Service".
Usually organizations will create hierarchies and set up a term set so that users can associate the terms (just like categories or tags) to an item. This can be later used in search results to refine search items. SharePoint does not provide the ability to automatically synchronize the metadata across different farms. If we need to copy term set, we need to export the term set (can use this utility) and then import it using the term store management tool. In case you need to know how to import the term set using Term Store Management tool, please check out these articles -
http://office.microsoft.com/en-us/sharepoint-server-help/import-a-term-set-HA101818255.aspx http://www.wictorwilen.se/Post/Create-SharePoint-2010-Managed-Metadata-with-Excel-2010.aspx
This is a manual process and I have seen situations where automation is required. e.g. If the term set is open for users to allow addition of terms (Submission Policy is set to Open), then the term are mostly updated in the term sets. In case you need to have same term set data across multiple farms, then we need to do the export and import process manually all the time. Before I proceed, I have to let you know that exporting and importing the term sets will break the association with the existing term set. This is because whenever we are exporting the term set in a new farm, the GUIDs are not imported. If we have a list/site column (in source site) that is associated to specific term, it is done using the GUID of that term and not the name. So, if you have migrated the content and now are trying to export and import the metadata, the metadata items will be orphaned (but will still work i.e. functionality to add and remove metadata will work with a small setting change). In case you need to maintain the associate of the ID with the data in SharePoint sites across farms, I suggest you go with this method -
http://www.andrewconnell.com/blog/archive/2011/06/15/sharepoint-2010-managed-metadata-movingcopying-mms-instances-term.aspx
Note: In the above method, you are actually moving the entire term store and not individual term sets from groups.
With that said, lets move to a situation where term sets are updated weekly/daily and needs to be synchronized across different farms. To sync the data, we will need to carry out the process weekly/daily and causes redundancy and time wastage. We can do the export and import (considering in mind that the association with the ID will be lost), but again that is manual. The next approach can be to use code or powershell scripts to export and import the term sets. Then using a batch files or through Team Foundation Server, we can automate this process. Next you will find the powershell scripts which can export a term set (upto 7 levels) and then import it in the desired farm. At the start of each script you will see that some variables are set. e.g Term Set Name, Managed Metadata Service Instance Name, Owner Name, File Name, etc. Change it according to your farm settings and details and then run the script.
****** Export Script ******
You can copy the above code and save it as .ps1 file and run it against the farm(s) where you would like to import/export the term set.
Usually organizations will create hierarchies and set up a term set so that users can associate the terms (just like categories or tags) to an item. This can be later used in search results to refine search items. SharePoint does not provide the ability to automatically synchronize the metadata across different farms. If we need to copy term set, we need to export the term set (can use this utility) and then import it using the term store management tool. In case you need to know how to import the term set using Term Store Management tool, please check out these articles -
http://office.microsoft.com/en-us/sharepoint-server-help/import-a-term-set-HA101818255.aspx http://www.wictorwilen.se/Post/Create-SharePoint-2010-Managed-Metadata-with-Excel-2010.aspx
This is a manual process and I have seen situations where automation is required. e.g. If the term set is open for users to allow addition of terms (Submission Policy is set to Open), then the term are mostly updated in the term sets. In case you need to have same term set data across multiple farms, then we need to do the export and import process manually all the time. Before I proceed, I have to let you know that exporting and importing the term sets will break the association with the existing term set. This is because whenever we are exporting the term set in a new farm, the GUIDs are not imported. If we have a list/site column (in source site) that is associated to specific term, it is done using the GUID of that term and not the name. So, if you have migrated the content and now are trying to export and import the metadata, the metadata items will be orphaned (but will still work i.e. functionality to add and remove metadata will work with a small setting change). In case you need to maintain the associate of the ID with the data in SharePoint sites across farms, I suggest you go with this method -
http://www.andrewconnell.com/blog/archive/2011/06/15/sharepoint-2010-managed-metadata-movingcopying-mms-instances-term.aspx
Note: In the above method, you are actually moving the entire term store and not individual term sets from groups.
With that said, lets move to a situation where term sets are updated weekly/daily and needs to be synchronized across different farms. To sync the data, we will need to carry out the process weekly/daily and causes redundancy and time wastage. We can do the export and import (considering in mind that the association with the ID will be lost), but again that is manual. The next approach can be to use code or powershell scripts to export and import the term sets. Then using a batch files or through Team Foundation Server, we can automate this process. Next you will find the powershell scripts which can export a term set (upto 7 levels) and then import it in the desired farm. At the start of each script you will see that some variables are set. e.g Term Set Name, Managed Metadata Service Instance Name, Owner Name, File Name, etc. Change it according to your farm settings and details and then run the script.
****** Export Script ******
Add-PSSnapin Microsoft.SharePoint.PowerShell [Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Taxonomy") #This is the directory where you need to export the term set as a .csv file. #Please ensure that this folder exists before trying to export the term set. $outPutDir = "Directory where the csv file should be saved" #This should be the url of the Central Administration Site of the farm from where we would like to export the term set. $siteURL = "Central Admin Site URL" #This is the name of the Metadata Service Instance. e.g. "Managed Metadata Service" $mmsServiceName = "Managed Metadata Service Instance Name" #This is the group name where the term set exists. #In case the group does not exists, the script will create a new group with this name under the term store. $grpName = "Term Store Group Name" #This is the term set name which we are going to export. $termSetName = "Term Set Name" #This is the name of the csv file which will contain the exported term set data. $fileName = "FileName.csv" try { $taxonomySite = Get-SPSite $siteURL $taxSession = Get-SPTaxonomySession -site $taxonomySite try { $termStore = $taxSession.TermStores[$mmsServiceName]; if ($termStore -ne $null) { try { $termGroup = $termStore.Groups[$grpName]; if ($termGroup -ne $null) { try { $termSet = $termGroup.TermSets[$termSetName]; if ($termSet -ne $null) { [string]$csvDir = ""; $csvDir = $outPutDir; $outPutFile = $csvDir + "\" + "$fileName"; $sw = New-Object System.IO.StreamWriter($outPutFile); $sw.writeline('"Term Set Name","Term Set Description","LCID","Available","Term Description","Level 1 Term","Level 2 Term","Level 3 Term","Level 4 Term","Level 5 Term","Level 6 Term","Level 7 Term"'); [Byte[]] $ampersand = 0xEF,0xBC,0x86; #$loop = $termGroup.TermSets.Count; #$count = 1; if($TermSet.TermsCount -ne 0) { $topTermOutput = '"' + $TermSet.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $TermSet.Description + '","' + $TermSet.Languages + '","' + $TermSet.IsAvailableForTagging + '","'; foreach($childTerm in $TermSet.Terms) { if($childTerm.TermsCount -ne 0) { #$topTermOutput = '"' + '","' + $TermSet.Description + '","' + $TermSet.Languages + '","' + $TermSet.IsAvailableForTagging + '","'; $heritage = $topTermOutput + '","' + $childTerm.Description + '","' + $childTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '"'; foreach($secondLevelTerm in $childTerm.Terms) { if($secondLevelTerm.TermsCount -ne 0) { foreach($thirdLevelTerm in $secondLevelTerm.Terms) { if($thirdLevelTerm.TermsCount -ne 0) { foreach($fourthLevelTerm in $thirdLevelTerm.Terms) { if($fourthLevelTerm.TermsCount -ne 0) { foreach($fifthLevelTerm in $fourthLEvelTerm.Terms) { if($fifthLevelTerm.TermsCount -ne 0) { foreach($sixthLevelTerm in $fifthLevelTerm.Terms) { if($sixthLevelTerm.TermsCount -ne 0) { foreach($seventhLevelTerm in $sixthLevelTerm.Terms) { $heritage = $topTermOutput + '","' + $childTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $secondLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $thirdLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $fourthLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $fifthLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $sixthLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $seventhLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '"'; $sw.writeline($heritage); } } else { $heritage = $topTermOutput + '","' + $childTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $secondLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $thirdLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $fourthLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $fifthLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $sixthLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '"'; $sw.writeline($heritage); } } } else { $heritage = $topTermOutput + '","' + $childTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $secondLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $thirdLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $fourthLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $fifthLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '"'; $sw.writeline($heritage); } } } else { $heritage = $topTermOutput + '","' + $childTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $secondLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $thirdLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $fourthLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '"'; $sw.writeline($heritage); } } } else { $heritage = $topTermOutput + '","' + $childTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $secondLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $thirdLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '"'; $sw.writeline($heritage); } } } else { $heritage = $topTermOutput + '","' + $childTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '","' + $secondLevelTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '"'; $sw.writeline($heritage); } } } else { $heritage = $topTermOutput + '","' + $childTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '"'; $sw.writeline($heritage); } } } else { $heritage = $topTermOutput + '","' + $childTerm.Name.Replace([System.Text.Encoding]::UTF8.GetString($ampersand), "&") + '",,,,,,,' ; $sw.writeline($heritage); } } } catch { return "Problem occurred while creating the export file." } $sw.close(); write-host "Your CSV has been created at $outPutFile"; } else { return "Termset $termSet does not exist in the term store group $term"; } } catch [System.Exception] { write-host($_.Exception) "Unable to acquire the termset $termSetName from the term group $grpName" } } else { return "Term store group $grpName does not exist in the term store $mmsServiceName"; } } catch { "Unable to acquire term store group $grpName from $mmsServiceName" } } catch { "Unable to acquire session for the site $siteURL"; } finally { $ErrorActionPreference = "Continue"; }****** Import Script ******
Add-PSSnapin Microsoft.SharePoint.Powershell $inputFile = "Complete path of the .csv file" [Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Taxonomy") #Change the below values as per your farm and term store settings. #This should be the url of the Central Administration Site of the farm where we would like to import the term set $siteURL = "Central Admin site URL" #This is the name of the Metadata Service Instance. e.g. "Managed Metadata Service" $mmsServiceName = "Metadata Service Instance" #This is the group name where the term set exists. In case the group does not exists, the script will create a new group with this name under the term store. $grpName = "Group Name" #This is the login ID of the user who should be set as the owner of the Group $grpManager = "domain\username" #This is the term set name which we are going to import. $termSetName = "Term Set Name" #This is the login ID of the user who should be set as the owner of the term set. $termSetOwner = "domain\username" #This is the login ID of the user who should be set as the one of the StakeHolders for the term set. $tsStakeHolder = "domain\username" #In case you need to add more stake holders, create new variables and add them before the CommitAll() statement (before setting the owner) at the later part of the code. $taxonomySite = Get-SPSite $siteURL $taxSession = Get-SPTaxonomySession -Site $taxonomySite $termStore = $taxSession.TermStores[$mmsServiceName]; if ($termStore -ne $null) { $termGroups = $termStore.Groups; #This checks if a group with the given name exists or not. If it does not exists then it will create a new group with the given name. foreach($termGroup in $termGroups) { if($termGroup.Name -eq $grpName) { $termGroup = $termStore.Groups[$grpName]; } else { $termGroup = $null; } } if($termGroup -eq $null) { try { $termStoreGroup = $termStore.CreateGroup($grpName); $termGroup.AddGroupManager($grpManager); write-host "Term group $grpName created successfully"; $termGroup = $termStore.Groups[$grpName]; } catch { write-host "Creation of Term Group Failed."; } } #If the group exists then deleting all the term sets under the given group. if ($termGroup -ne $null) { $termGroup.TermSets | foreach { $_.Delete(); $termStore.CommitAll(); } write-host "All term sets under the group $grpName deleted successfully" } #Importig the term set from the csv file. try { $fileReader = [System.IO.File]::OpenText($inputFile); $importMan = $termStore.GetImportManager(); $varImported = ""; $varMessage = ""; $importMan.ImportTermSet($termGroup, $fileReader,([REF]$varImported),([REF]$varMessage)); $termStore.CommitAll(); $termSet = $termGroup.TermSets[$termSetName]; $termSet.AddStakeHolder($tsStakeHolder); $termSet.IsOpenForTermCreation = "true"; $termSet.Owner = $termSetOwner; $termStore.CommitAll(); write-host "Term Set re-imported successfully."; } catch { write-host "There was either a problem while creating or importing the term set"; } } else { return "Term store $termStore does not exist"; }
You can copy the above code and save it as .ps1 file and run it against the farm(s) where you would like to import/export the term set.
If you set up a trust relationship between farm servers they can all subscribe to the same managed metadata service, removing the need to export across farms.
ReplyDelete