Thursday, February 10, 2011

SharePoint 2010 Search - Thesaurus Files

This year is the year of search for us. We're looking at implementing fast, focusing on metadata and better tagging in our content, and improving the overall search experience for our users. With that in mind, I just wanted to touch on creating Thesaurus files in SharePoint 2010 Search, as I've found the content on Technet and MSDN to be a bit cryptic.

Modifying Thesaurus Files
If you've been referencing Technet (http://technet.microsoft.com/en-us/library/dd361734.aspx), there is some pretty good information on how to create thesaurus files to improve your search. There are two main priniples in a thesaurus file: expansion sets and replacement sets.

To create an expansion set, which essentially maps synonyms to a specific keyword, you simply need to add the following code to your thesasurus file:

<expansion>
    <sub>401k</sub>
    <sub>401 k</sub>
    <sub>401-k</sub>
</expansion>

An important item to note, parentheses are not acceptable in a thesaurus file. I found this out the hard way when attempting to add <sub>401(k)</sub>, which is the approved standard for 401(k). Luckily for us, the parentheses are ignored in the keyword, so 401(k) will still appear in the search results, even when the user keys in 401-k.

To create a replacement set, the schema is similar:

<expansion>
    <pat>IE8</pat>
    <pat>IE7</pat>
    <sub>Internet Explorer</sub>
</expansion>


In this case, IE8 or IE7 would be replaced by Internet Explorer.

While we don't have much use for replacement sets, expansion sets have proven extremely valuable. Instead of providing Best Bets links via the Search Keywords administration tool, we can populate our search results with all synonyms immediately, which reduces the need for multiple clicks to get a specific result.

Updating Thesaurus Files


The update process is where I have found the least amount of information. Thesaurus files are stored in multiple locations on a SharePoint Server, and determining the correct location can be a real pain in the butt. We update our Thesaurus files in 2 locations in the /Program Files/Microsoft Office Servers/14.0/ folder.

First, we update the thesaurus files here: \Program Files\Microsoft Office Servers\14.0\Data\Config. Updates to the thesaurus files here will ensure that any new Search Service Applications that you create will have the updated thesaurus definitions when they spin up.

Second, we copy the thesaurus files to the: \Program Files\Microsoft Office Servers\14.0\Data\Applications\[GUID]\Config folder. The GUID will be the guid of your Search Service Application, which can be found using this bit of Powershell goodness: Get-SPServiceApplication. This powershell command will list all of your service applications and their corresponding IDs.

Once the files are copied to this location, you'll need to restart the search service for the changes to take affect. You can do this from Administrative Tools > Services > SharePoint Server Search 14, or by running these commands:

net stop osearch
net start osearch

Once the service is resarted, go to your search center and plug in one of the newly added expansion/replacement terms to see your results.

It is important to note that if you're running search on multiple servers, you will need to perform these steps on each server running search. If you already have multiple search applications running, you will also need to copy your thesaurus files to each config directory under the GUID folder for each search service application.

For safety sake, we also updated the tsneu.xml along with tsenu.xml. NEU is the language neutral thesaurus file, and ENU is the US English thesaurus file. Definitions for each language prefix can be found on technet.

Tuesday, February 8, 2011

Setting Managed Metadata Fields via Javascript - UPDATE

As I mentioned in a previous post, Managed Metadata fields can be set using Javascript. I've actually found an easier method to retrieve and update the values via javascript that I wish to share quickly.

Previously, I was retrieving the Managed Metadata Field Value in display format. I encountered an issue when attempting to use this value to update a form field on a modal popup however, due to multiple results in the Term Store being found for a single string. To remedy this, I found the hidden value for the Metadata Field including the GUID of the term. To do this, I used my handy Powershell script from my previous post, and located the field name for the Metadata Field. I then located the following XML for my field:


<Field Type="Note" DisplayName="Role_1" StaticName="RoleTaxHTField" Name="RoleTaxHTField" ID="{bbaf434e-cc7e-40b5-b43e-5605ee3c3543}" ShowInViewForms="FALSE" Required="FALSE" Hidden="TRUE" CanToggleHidden="TRUE" SourceID="{d96d858a-03f7-4b0f-a73f-fc0ee68996cd}" Customization="" ColName="ntext9" RowOrdinal="0"/>
    <Field Type="TaxonomyFieldTypeMulti" DisplayName="Role" List="{aff9fc9f-40b8-4a89-aaa3-f5f566117446}" WebId="d96d858a-03f7-4b0f-a73f-fc0ee68996cd" ShowField="Term1033" Mult="TRUE" Sortable="FALSE" Required="FALSE" Group="Knowledge Base Columns" ID="{5050205f-5771-40e1-b356-ec6c989147f1}" SourceID="{d96d858a-03f7-4b0f-a73f-fc0ee68996cd}" StaticName="Role" Name="Role" Version="4" EnforceUniqueValues="FALSE" Customization="" ColName="int8" RowOrdinal="0">
      <Default/>
      <Customization>
        <ArrayOfProperty>
          <Property>
            <Name>SspIdName>
            <Value xmlns:q1="http://www.w3.org/2001/XMLSchema" p4:type="q1:string" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">d6d8e56a-06c9-4c99-a5b0-1ea8b6eb747fValue>
          Property>
          <Property>
            <Name>GroupIdName>
          Property>
          <Property>
            <Name>TermSetIdName>
            <Value xmlns:q2="http://www.w3.org/2001/XMLSchema" p4:type="q2:string" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">50857e97-8bdf-4000-bf13-5b1ba34d745aValue>
          Property>
          <Property>
            <Name>AnchorIdName>
            <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-000000000000Value>
          Property>
          <Property>
            <Name>UserCreatedName>
            <Value xmlns:q4="http://www.w3.org/2001/XMLSchema" p4:type="q4:boolean" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">falseValue>
          Property>
          <Property>
            <Name>OpenName>
            <Value xmlns:q5="http://www.w3.org/2001/XMLSchema" p4:type="q5:boolean" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">falseValue>
          Property>
          <Property>
            <Name>TextFieldName>
            <Value xmlns:q6="http://www.w3.org/2001/XMLSchema" p4:type="q6:string" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">{bbaf434e-cc7e-40b5-b43e-5605ee3c3543}Value>
          Property>
          <Property>
            <Name>IsPathRenderedName>
            <Value xmlns:q7="http://www.w3.org/2001/XMLSchema" p4:type="q7:boolean" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">falseValue>
          Property>
          <Property>
            <Name>IsKeywordName>
            <Value xmlns:q8="http://www.w3.org/2001/XMLSchema" p4:type="q8:boolean" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">falseValue>
          Property>
          <Property>
            <Name>TargetTemplateName>
          Property>
          <Property>
            <Name>CreateValuesInEditFormName>
            <Value xmlns:q9="http://www.w3.org/2001/XMLSchema" p4:type="q9:boolean" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">falseValue>
          Property>
          <Property>
            <Name>FilterAssemblyStrongNameName>
            <Value xmlns:q10="http://www.w3.org/2001/XMLSchema" p4:type="q10:string" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">Microsoft.SharePoint.Taxonomy, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429cValue>
          Property>
          <Property>
            <Name>FilterClassNameName>
            <Value xmlns:q11="http://www.w3.org/2001/XMLSchema" p4:type="q11:string" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">Microsoft.SharePoint.Taxonomy.TaxonomyFieldValue>
          Property>
          <Property>
            <Name>FilterMethodNameName>
            <Value xmlns:q12="http://www.w3.org/2001/XMLSchema" p4:type="q12:string" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">GetFilteringHtmlValue>
          Property>
          <Property>
            <Name>FilterJavascriptPropertyName>
            <Value xmlns:q13="http://www.w3.org/2001/XMLSchema" p4:type="q13:string" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">FilteringJavascriptValue>
          Property>
        ArrayOfProperty>
      Customization>
    Field>

As you can see, there are 2 fields listed in the XML. The first field is the hidden value including the GUID of the term or terms, and the second field is the container/display field that is rendered as a string in Display Mode.

On my display form for the items that will be receiving feedback, I added a hidden field in the XSLT, and set the value to 

<xsl-value-of select="@RoleTaxHTField" />

When opening the dialog, the arguments passed include the value of this field.  On my dialog I now set the following the hidden storage field of the Metadata Field to the value passed. Now when the user submits the feedback, the value is mapped to the correct term without any errors, and there is no need to run the javascript that forces the metadata field to update.




Monday, February 7, 2011

Working with Lists and Schemas

I thought I would put up a quick post about retrieving list schema definitions via powershell while at the SPTechCon 2011 in SF this week. I've been working on some new Metadata functionality with JQuery and the SPServices Library (http://spservices.codeplex.com/ courtesy of Marc D Anderson), and realized that it's a real pain in the a** working with Managed Metadata Columns in SharePoint.

Here's a quick reference for grabbing the XML Schema of a list definition so you can get to internal field names, column definitions, and the Taxomony Ids required for interacting with the TaxonomyClientService.

$site = Get-SPSite http://[Site Url]
$web = $site.OpenWeb() - note: leave the value blank for the top-level web, or specify "/web url" between the parentheses to retrieve a specific web
$list = $web.Lists["List Name"]
$list.SchemaXML | Out-File C:\Temp\schema.xml


Now you should have an xml file containing the schema of your list. Open the file in your XML editor of choice, and have a blast locating the attributes you need.