Creating Crawled Properties

You can create crawled properties for search programmatically without needing to start a full crawl. This can be helpful when adding managed properties that map to crawled properties and you can’t be sure the crawled properties will exist at that time. In the following, we create some crawled properties using a manager class and wrap up the logic in a Feature that can be deployed in a solution package.

The first thing we do is create a manager class that adds crawled properties using the object model:

public class CrawledPropertyManager
{
    private Schema _schema;
    private IEnumerable<CrawledProperty> _crawledProperties;

    public CrawledPropertyManager(string serviceName, string applicationName)
    {
        SPFarm farm = SPFarm.Local;
        SearchService searchService = farm.Services.GetValue<SearchService>(serviceName);
        SearchServiceApplication searchApp =
            searchService.SearchApplications.GetValue<SearchServiceApplication>(applicationName);
        _schema = new Schema(searchApp);
        _crawledProperties = _schema.QueryCrawledProperties(string.Empty, 1000000, Guid.NewGuid(),
            string.Empty, true).Cast<CrawledProperty>();
    }

    public void AddCrawledProperty(string propertyName, PropertySet propSet, VariantType variant)
    {
        if (string.IsNullOrEmpty(propertyName))
        {
            throw new ArgumentNullException("propertyName");
        }

        propertyName = Settings.GetCrawledPropertyPrefix(propSet) + propertyName;
        var crawledProperty = _crawledProperties.FirstOrDefault(c => c.Name.Equals(propertyName));

        //only create the crawled property if one doesn't already exist
        if (crawledProperty == null)
        {
            var propSetId = Settings.GetPropertySetId(propSet);
            var category = _schema.AllCategories[propSetId];

            try
            {
                category.CreateCrawledProperty(propertyName, false, propSetId, (int)variant);
                category.Update();
            }
            catch (Exception ex)
            {
                Logging.Logger.Log(ex);
            }
        }
    }
}

Then create a Feature which uses the manager for adding crawled properties one at a time.

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    _properties = properties;

    try
    {
        var manager = new CrawledPropertyManager(
            SearchServiceName.EnterpriseSearch,
            SearchServiceApplicationName.Default);

        manager.AddCrawledProperty(“Property1″, PropertySet.People, VariantType.String);
        manager.AddCrawledProperty(“Property2″, PropertySet.People, VariantType.Datetime);
        manager.AddCrawledProperty(“Property3″, PropertySet.People, VariantType.Taxonomic);
    }
    catch (Exception ex)
    {
        //log exception
    }
}

We use a Settings class to factor out the property set and variant types:

public static class Settings
{
    public static Guid GetPropertySetId(PropertySet propSet)
    {
        var retVal = Guid.Empty;
        var propSetIdString = string.Empty;

        switch (propSet)
        {
            case PropertySet.Basic:
                propSetIdString = PropertySetGuid.Basic;
                break;
            case PropertySet.Mail:
                propSetIdString = PropertySetGuid.Mail;
                break;
            case PropertySet.Office:
                propSetIdString = PropertySetGuid.Office;
                break;
            case PropertySet.People:
                propSetIdString = PropertySetGuid.People;
                break;
            case PropertySet.SharePoint:
                propSetIdString = PropertySetGuid.SharePoint;
                break;
        }

        if (!string.IsNullOrEmpty(propSetIdString))
        {
            retVal = new Guid(propSetIdString);
        }

        return retVal;
    }

    public static string GetCrawledPropertyPrefix(PropertySet propSet)
    {
        var retVal = string.Empty;

        switch (propSet)
        {
            case PropertySet.People:
                retVal = CrawledPropertyPrefix.People;
                break;
            case PropertySet.SharePoint:
                retVal = CrawledPropertyPrefix.SharePoint;
                break;
        }

        return retVal;
    }
}

public enum PropertySet
{
    Basic,
    Mail,
    Office,
    People,
    SharePoint
}

internal struct PropertySetGuid
{
    public const string SharePoint = "00130329-0000-0130-c000-000000131346";
    public const string Basic = "0b63e343-9ccc-11d0-bcdb-00805fccce04 ";
    public const string Mail = "aa568eec-e0e5-11cf-8fda-00aa00a14f93";
    public const string Office = "f29f85e0-4ff9-1068-ab91-08002b27b3d9";
    public const string People = "00110329-0000-0110-c000-000000111146";
}

internal struct CrawledPropertyPrefix
{
    public const string SharePoint = "ows_";
    public const string People = "urn:schemas-microsoft-com:sharepoint:portal:profile:";
}

public struct SearchServiceName
{
    public const string EnterpriseSearch = "OSearch14";
}

public struct SearchServiceApplicationName
{
    public const string Default = "Search Service Application";
}

public enum VariantType
{
    String = 31,
    YesNo = 11,
    Binary = 12,
    Integer = 20,
    Datetime = 64,
    Taxonomic = 4127
}

After deploying the solution and activating our feature the new properties will show up in Central Administration > Search Service Application > Crawled Properties:

image

Note: nothing has been indexed yet by the search crawler. We must still do a full crawl and add managed properties that map to our crawled properties before we can search. See Creating Managed Properties for creating and mapping managed properties to crawled properties.

You can do the same thing in PowerShell. Here is a great post that describes how to do this: Creating Enterprise Search Metadata Property Mappings with PowerShell.

About Michael Brockman
SharePoint (2010, MOSS 2007) and .NET developer.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.