Mathias Osterkamp

Specialist – focus development Microsoft technology stack

Managed Metadata Migration

Secrets about SharePoint Taxonomies

Managed metadata is a formal taxonomy classification system. A taxonomy groups the words, labels, and terms that describe something, and then arranges the groups into a hierarchy. You can learn more basics and wordings on microsoft docs. Mostly it is simple called term store.

Where are my data stored?

The first common question for migration is, where actual the term store data are stored. The short answer is, everything important is stored in Managed Metadata SQL Database of the service application. To get a bit deeper look we have to analyze the field structure.

How the fields are structured?

A typical Sharepoint taxonomy field looks the following way (source).

DisplayNameInternalNameData TypeVisibleValueData FormatCreated By
[YourColumnName][YourColumnName]TaxonomyFieldType[Mult]Yes2;#ChennaiWSS Id; Name of TeamUser
[YourColumnName]_0[YourColumnName]TaxHTField0NoteNoChennaic61d9028-824f-446e-9389-eb9515813a42Name of Term
Taxonomy Catch All ColumnTaxCatchAllLookupNoSharePoint

We see here basically, there is one column [YourColumnName] for your term display value and another column [YourColumnName]TaxHTField0 for the term ID. But this is the internal structure, most time you handle with taxonomy fields by using the API, here everything internal is handled, and you don’t have to worry about the internal field. Sample for REST taxonomy structure

{
  "MetaSingleField": {
    "__metadata": {
      "type": "SP.Taxonomy.TaxonomyFieldValue"
    },
    "Label": "1289",
    "TermGuid": "0b032022-d156-49eb-9a48-904df5411349",
    "WssId": 1289
  },
  "MetaMultiField": {
    "__metadata": {
      "type": "Collection(SP.Taxonomy.TaxonomyFieldValue)"
    },
    "results": [
      {
        "Label": " Label ABC",
        "TermGuid": "158a84f4-e5ff-440b-b55f-d30b0f77c402",
        "WssId": 1291
      },
      {
        "Label": " Label DEF",
        "TermGuid": "03d2d388-a863-4f5d-818d-d71d948f763d",
        "WssId": 1290
      }
    ]
  },
  "TaxCatchAll": {
    "results": [
      {
        "__metadata": {
          "id": "158a84f4-e5ff-440b-b55f-d30b0f77c402",
          "type": "SP.Data.TaxonomyHiddenListListItem"
        },
        "ID": 1291,
        "Term": "Label ABC"
      },
      {
        "__metadata": {
          "id": "03d2d388-a863-4f5d-818d-d71d948f763d",
          "type": "SP.Data.TaxonomyHiddenListListItem"
        },
        "ID": 1290,
        "Term": "Label DEF"
      },
      {
        "__metadata": {
          "id": "0b032022-d156-49eb-9a48-904df5411349",
          "type": "SP.Data.TaxonomyHiddenListListItem"
        },
        "ID": 1289,
        "Term": "Label XYZ"
      }
    ]
  }
}

Why there is a hidden list?

On the look of the field structure you also see a reference for WSS or TaxonomyHiddenList. The answer is, that is a caching system to allow get the taxonomy data faster from list only be a simple lookup to this hidden list. The good about this is, you d’ont have to really care about that fact. If you change taxonomy field values, SharePoint internal has Event Receivers to handle an update to this hidden list. If you are change the taxonomy value inside the term store, there is also an hourly update timer job, it makes an update to the hidden list information. So the result the quick conclusion from migration perspective is for that:

  • Don’t care about hidden list on migration!

But there is a site collection and a global term store?

Yes, the only real difference is the availability. So global term sets are visible on every site collection. Local term sets are only visible to a single site collection.

  • Both sorts of terms are store on Managed Metadatabase

How are managed metadata fields and term store connected?

A really important fact is, how the term store and fields are connected. We see more details by looking on the field structure.

<Field
    Type="TaxonomyFieldType"
    DisplayName="Custom (web)"
    List="Lists/TaxonomyHiddenList"
    WebId="~sitecollection"
    ShowField="Term1033"
    Required="FALSE"
    EnforceUniqueValues="FALSE"
    Group="_Custom"
    ID="{fce6a8e2-23e8-49c2-9bad-a534555296bb}"
    SourceID="{5e68c9eb-5efe-4bcc-b8db-93d38d797fbe}"
    StaticName="__Custom"
    Name="__Custom"
    Overwrite="TRUE">
    Default />
    <Customization>
        <ArrayOfProperty>
            <Property>
                <Name>SspId</Name>
                <Value
                    xmlns:q1="http://www.w3.org/2001/XMLSchema"
                    p4:type="q1:string"
                    xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">b98dd270-8577-4db8-99e1-b9e894624fdb
                </Value>
            </Property>
            <Property>
                <Name>GroupId</Name>
            </Property>
            <Property>
                <Name>TermSetId</Name>
                <Value
                    xmlns:q2="http://www.w3.org/2001/XMLSchema"
                    p4:type="q2:string"
                    xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">b7ae10cd-6c7c-4386-a1f2-7abec8e759e1
                </Value>
            </Property>
            <Property>
                <Name>AnchorId</Name>
                <Value
                    xmlns:q3="http://www.w3.org/2001/XMLSchema"
                    p4:type="q3:string"
                    xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">00000000-0000-0000-0000-000000000000
                </Value>
            </Property>
            ...
        </ArrayOfProperty>
    </Customization>
</Field>

We find two important values:

  1. SspId: This is the ID of your managed metadata service application
  2. TermSetId: This is the ID of your termset

The consequence of these two information on migration perspective is.

  • You need your Managed Metadata SQL Database and a related service application to keep your term store ID (SspID)
  • You need always correct termset and term IDs for migration

Can I import or export my termsets?

There are several import and export mechanisms here some details about:

  • Taxonomy Import (details): It allows only to import simple csv based termsets without IDs, not for migration
  • Export-SPMetadataWebServicePartitionData (details): It’s only for server to server migration from the same version
  • Powershell Skripts (sample): You will keep your term set IDs, it can work for simple migrations only for term sets. If you have related data on your site collections, your term store ID could not match. Possible is first a database migration and afterwards a delta migration
  • Migration tools: Mostly are relative close to Powershell Scripts
  • PNP Powershell: Same like Powershell Scripts

In general, you have to think on these scenarios on a little more details:

  • Handle users are not more available on target system
  • Handle orphaned terms
  • Handle term reuse
  • Handle navigation term sets

How looks a database migration?

To move the managed metadata database, take a copy only backup of it from your SQL server and then restore from files in your new SQL server. I took this short sample from here.

At this point, you already have a managed metadata service application in your target farm and you need to get it’s globally unique identifier (GUID). Run the following:

Get-SPServiceApplication  |  ?{$_.name  -like  "*meta*"}  |  ft id

You could put that ID in a variable, or you could type it into your next set of commands that attach the new db to the Managed Metadata service application

$ServiceID  =  Get-SPServiceApplication  |  ?{$_.name  -like  "*meta*"}  |  ft id

$mms  =  Get-SPServiceApplication  -Identity  $ServiceID

Set-SPMetadataerviceApplication  -Identity  $mms  -DatabaseName  "MetaData"

The key to this working is that the correct DatabaseName is used. So if your new db is named MetaDataDB, then the above script would need to be modified a little for the -DatabsaseName parameter.

The managed metadata navigation should now be working. If it’s not, just go to manage service applications, change the managed metadata database to a database that does not exist, click OK, then change it back. This process causes SharePoint to execute a timer job that syncs the service application up to the database.