Wednesday, May 4, 2011

Working with crawled and managed properties via code

I was teaching a FAST for SharePoint Workshop today and we were doing labs on creating and mapping crawled properties to managed properties with the FAST Administration UI and via PowerShell. But one student wanted to know how to do this in code, hence this blog post.

Instead of having a deployment script creating your properties, you could have an event receiver which creates your mappings once a site or list is provisioned. Or when some other action is going on.

So how do you go about doing this?

Well, first off Crawled and Managed Properties for FAST are a part of the index schema and is accessible via the following two namespaces:

Microsoft.SharePoint.Search.Extended.Administration Microsoft.SharePoint.Search.Extended.Administration.Schema

which are the namespaces used for working with the FAST components. But first you have to get an instance of the WCF client proxy on the SharePoint side used to communicate with the FAST for SharePoint farm. This is accomplished via the FASTAdminProxy property of the search application proxy.

Below is a quick example showing how this can be done in code, with comments along the way to guide the process. It’s all pretty straight forward.

const string propertyName = "productname";
// Get a reference to the proxy and the Index Schema
var ssaProxy = (SearchServiceApplicationProxy)SearchServiceApplicationProxy.GetProxy(SPServiceContext.Current);

SchemaContext schemaContext = ssaProxy.FASTAdminProxy.SchemaContext();
Schema schema = schemaContext.Schema;

// Assign a guid to the custom Crawled Propery Category
Guid myGuid = new Guid(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
Category catGroup;
// Create if it does not exist
if (!schema.AllCategories.Contains(myGuid))
{
    catGroup = schema.AllCategories.Create("My Crawled Properties", myGuid);
}
else
{
    catGroup = schema.AllCategories[myGuid];
}

// Create a new crawled property if it doesn't exist
CrawledProperty cp = catGroup.GetAllCrawledProperties().Where(
    c => c.Name == propertyName && c.VariantType == 31 && c.Propset == myGuid).FirstOrDefault();
if (cp == null) cp = catGroup.CreateCrawledProperty(propertyName, myGuid, 31);

// Create a new managed property if it doesn't exist
ManagedProperty mp;
if (!schema.AllManagedProperties.Contains(propertyName))
{
    mp = schema.AllManagedProperties.Create(propertyName, "", ManagedType.Text);
}
else
{
    mp = schema.AllManagedProperties[propertyName];
}

// Create a new crawled to managed property mapping if it doesn't exit
CrawledPropertyMapping mapping = mp.GetCrawledPropertyMappings();
if (!mapping.Contains(cp))
{
    mapping.Add(cp);
    mp.SetCrawledPropertyMappings(mapping);
}

// Get a reference to the default full text index (first one)
FullTextIndex fti = schema.AllFullTextIndecies.First();

// Get the full text index mapping from the Managed Property
FullTextIndexMappingCollection fullTextIndexMappingCollection = mp.GetFullTextIndexMappings();
FullTextIndexMapping indexMapping =
    fullTextIndexMappingCollection.Where(ftpMap => ftpMap.FullTextIndex.Name == fti.Name).FirstOrDefault();
// Set a mapping to importance level 6, if it's not already set to something else
if (indexMapping == null || !fullTextIndexMappingCollection.Contains(indexMapping))
{
    fullTextIndexMappingCollection.Create(fti, 6);
}