As part of our eBay presentation at the SharePoint Conference 2011, we showed how we performed the upgrade in 3 months and utilized Managed Metadata (MMS) in site creation to drive searchability across the SharePoint Farm. The biggest question I have received so far from the presentation is about the MMS subject. So I'm going to outline it in detail here. For those of you that are not familiar with MMS, I like to describe it using the 3rd rule in my three rules of development. The first rule is "Don't code the same line of code twice", if you see the same line of code twice, you did something wrong (no polymorphism, missing base method calls, inheritance, etc). The second is don't put the same thing in memory more than once (this really needs no clarification). The third rule says don't put the same thing on disk twice. By doing this, you now must implement synchronization between the multiple instances. The only product I worked with over the years that ever implemented this pattern perfectly was Lotus Notes. It is for this reason, we have MMS in 2010.
In SharePoint 2007, imagine you have created a list in SharePoint that uses a choice column. You would have 50 states, plus the other various items the US owns (Examples: Guam, Virgin Islands…can you name them all?). If you use the state column in other places in the Farm, you pretty much have to copy and paste all the items over and over again. This is somewhat of a problem. For instance, if Texas ever successfully succeeds from the union, you gotta remove them from all the choice columns! What about Iraq and Afghanistan? Maybe those should be added to the list? Who knows what might happen in the future, but you'd have to update each and every source in order for the data to be meaningful. Therefore, rule #3 is a good one…don't put data on disk more than twice. MMS helps us do this by centrally stored our list data in one place.
So how did we use MMS at eBay? The summary of the process is that when users create their own site, the content inside the site should be pre-tagged with MMS data so as to allow for simple searching of their content via FAST Search. Here's a breakout of the parts:
Site Creation:
The first step is to create a site creation form. This can be anything you are comfortable with (an aspx page, an infopath form, web parts, etc). In the case of eBay we used two web parts. One is the site creation landing page web part. Previously the values used to "tag" the sites was hardcoded in the code. As part of the upgrade I changed this to pull dynamically from MMS. This web part allows the entry of the following information:
- Business Unit (MMS)
- Organization (MMS)
- Office Location (MMS)
- Site Name
- Description
- Keywords (terms that will allow users to find the site later)
- Template (teamsite, blog, etc)
- Security (allow inheritance/everyone to view the site)
When clicking submit, several things happen:
- Create a new list item with all the details of the site creation request
- Submit to the site creation processing webpart with the site creation request id
- Start a long running transaction
- Impersonate the user that made the request
- Get a site number from a database for the site URL (example: 12345)
- Determine what site collection to add the site to (allows for load balancing the sites across content databases)
- Create the new web
- Add to the custom site directory list (this list is used for later look up on a site lookup web part)
- Setup navigation for the site
- Set the web property bag with the Organization, BusinessUnit and Location properties
- Create the metadata columns (outlined below)
- Add the site keywords to FAST Search
All throughout this process if any errors occur another list is setup to keep track of the errors and steps of the long running process. This allows OPS to debug the process and work with development in case something needs to be tweaked.
Site Directory:
You will need to ensure you have a list setup to keep track of your sites. In the case of a pre-existing site directory it is likely that you have already created a choice column with your values. This doesn't move very easily to MMS. You will have to migrate the values to new MMS columns (create new column with different name, move value over, deleted old column, create column with old name, copy values again) . If you already have this site directory, it is simple to run back through all the sites and add the web properties and then add the MMS columns to all the existing lists in the already existing sites (so not only new sites have MMS, but old ones too)!
MMS Setup:
We used the following PowerShell script to pre-populate the MMS:
$session = get-sptaxonomysession -site http://contoso.com
$termstore = $session.termstores["Contoso Corporate MMS"]
$termGroup = $termstore.groups["Contoso"]
if (-not $termGroup)
{
$termGroup = $termstore.creategroup("Contoso")
}
$termSet = $termGroup.TermSets["Organization"]
if (-not $termSet)
{
$termSet = $termGroup.CreateTermSet("Organization")
}
foreach($t in $termset.terms)
{
$t.delete()
}
$termSet.createterm("Finance",1033)
$termSet.createterm("Human Resources",1033)
$termSet.createterm("Information Technology",1033)
$termSet.createterm("Legal",1033)
$termSet.createterm("Marketing and Sales",1033)
$termSet = $termGroup.termsets["BusinessUnit"]
if (-not $termSet)
{
$termSet = $termGroup.CreateTermSet("BusinessUnit")
}
foreach($t in $termset.terms)
{
$t.delete()
}
$termSet.createterm("Corporate",1033)
$termSet.createterm("PayPal",1033)
$termSet.createterm("StubHub",1033)
$termSet.createterm("Bill Me Later",1033)
$termSet = $termGroup.termsets["Location"]
if (-not $termSet)
{
$termSet = $termGroup.CreateTermSet("Location")
}
foreach($t in $termset.terms)
{
$t.delete()
}
$termSet.createterm("APAC – Australia",1033)
$termSet.createterm("APAC – China",1033)
$termSet.createterm("APAC – Hong Kong",1033)
$termSet.createterm("APAC – India",1033)
$termSet.createterm("APAC – Israel",1033)
$termSet.createterm("APAC – Korea",1033)
$termSet.createterm("APAC – Taiwan",1033)
$termSet.createterm("EU – Austria",1033)
$termSet.createterm("EU – Belgium",1033)
$termSet.createterm("EU – Czech Replubic",1033)
$termSet.createterm("EU – Estonia",1033)
$termSet.createterm("EU – France",1033)
$termSet.createterm("EU – Germany",1033)
$termSet.createterm("EU – Ireland",1033)
$termSet.createterm("EU – Italy",1033)
$termSet.createterm("EU – Luxembourg",1033)
$termSet.createterm("EU – Netherlands",1033)
$termSet.createterm("EU – Poland",1033)
$termSet.createterm("EU – Spain",1033)
$termSet.createterm("EU – Sweden",1033)
$termSet.createterm("EU – Switzerland",1033)
$ter
mSet.createterm("EU – UK",1033)
$termSet.createterm("NA – Canada",1033)
$termSet.createterm("NA – U.S.",1033)
$termSet.createterm("Global",1033)
$termStore.CommitAll()
Note that once it is created, you should not delete the values. This will cause the linkage between any previously created columns to be eliminated. Not fun to look at and fix later. So be sure to tell the ops team not to run the create more than once…EVER…
MMS Columns:
The hardest part of the entire process is the MMS column creation. It works like this:
- Check to see if the web prop bag has been set, if not then set the web props to the values in the intranet site directory list, otherwise set to some default values
- For each list, add the metadata columns
- You should not add metatdata to lists that are "hidden" or that are type "Survey". It will break those list types
- Great example is the HiddenTaxonomyList, kinda weird adding a MMS column to that one as it keeps track of MMS usage across the site, creates a bit of a loop…not good!
- You should also avoid everything but the following site types, if you don't you will get some VERY ugly messages from SharePoint 2010 (try adding MMS to an Access Services site, it doesn't work!):
- STS
- MPS
- BLANKINTERNET
- CMSPUBLISHING
- PUBLISHING
- WIKI
- BLOG
- SPS
- Adding the metadata column involves the following process:
- Detemine if the column already exists (choose your column name wisely), in this case, we preappended with "Geo" to avoid any clashes with already existing column names and internal SP names
- Provision a note field to support your MMS field (yup, each MMS column is actually two columns)
- Create a new taxonomy field using the Guid of the note field in the TextField property
- Set the default value of the field using the "WSSID;#VALUE|TERMID", hint: use -1 if WSSID has not been defined yet
The result is every viable list has MMS columns added:
Each MMS column has a default value set:
When a new item is created, the user doesn't have to do anything! The values are pre-populated with the values they selected at site creation time!
Search:
As part of the site creation there is a keyword text box. Users can type keywords delimited by semicolon. Their keywords are then added to FAST Search. Initially we thought adding to both SharePoint Search and FAST Search was the answer, but that didn't work as it actually would show two keywords in the results and not just one. You can also have the keywords added as search suggestions. What this means is that when they start typing in the search box, you will see the keyword displayed as a suggestion:
Then when the search is executed, you will see the site as a keyword and the results for that keyword displayed as business as usual:
Once the columns have been added to all the list items in all the sites, you have setup FAST Content SSA and indexed the content you will get some pretty cool results. Because of the TaxonomyFilter refiners that is preconfigured in the FAST Search Center, you will see the pre-defined MMS column values on the left side of the screen:
Users can now find content specific to their geography, organization and functional group. Results are now more meaningful and can be found much faster than with SharePoint 2007!
Enjoy!
Chris