Monday, October 02, 2006

Creating a "Search Results Web Part" that searches on parts of the words

Here is the problem - We are using the profile database to create a phonebook application. SharePoint search only finds people if you type an exact match of the person name. For example, Searching for "Isha" will not bring my profile back since my name is "Ishai".

My customer wanted a prefix search so that searching for the beggining will return all people begining with the letters. Also, searching for parts of other properties such as job description should do the same (example - searching for "cons" will return anyone who is a consultant)

After much research, here is my solution:
Basically, what I do is override the built-in search result web part, and then modify the search query it runs. The only downside for this is that the default web part doesnt use XSL to format the results and doesnt have all the cool properties that the "PeopleCoreResultsWebPart" have. But with some work you can add the needed properties yourself.
  1. Create a new web part project
  2. Override the "Microsoft.SharePoint.Portal.WebControls.SearchResults" control
  3. Override the "OnInit" event (or, alternatively you can override the "GenerateQueryString" event)
  4. Add the following code:

    protected override void OnInit(object sender, EventArgs e){
    //add the wildcard support so that we will find everyone who starts with the typed keyword
    this.QueryTemplateWherePart += @"OR CONTAINS(#WeightedProps, '""%__keywordinputnoboundaryquote__%*""')";
    //add the filter to search only for people and not documents or page
    this.QueryTemplateWherePart += @"AND ""DAV:contentclass""='urn:content-class:SPSPeople'";
    base.OnInit(sender, e);
    }

Here is a sample of a class you can use:
using System;
using System.Data;
using System.IO;
using System.Web;
using System.Collections;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.Serialization;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.Office.Server.Search.Query;
using Microsoft.Office.Server.Search.WebControls;
using Microsoft.Office.Server.UserProfiles;


namespace SPSTips.SharePoint.WebParts
{
    [XmlRoot(Namespace = "SPSTips.SharePoint.WebParts")]
    public class PeopleSearchResultsWebPart : Microsoft.SharePoint.Portal.WebControls.SearchResults
    {
        protected override void OnInit(object sender, EventArgs e)
        {
            //add the wildcard support so that we will find everyone who starts with the typed keyword
            this.QueryTemplateWherePart += @"OR CONTAINS(#WeightedProps, '""%__keywordinputnoboundaryquote__%*""')";
            //add the filter to search only for people and not documents or pages
            this.QueryTemplateWherePart += @"AND ""DAV:contentclass""='urn:content-class:SPSPeople'";
            base.OnInit(sender, e);
        }
        
        
        protected override void CreateChildControls()
        {
            Label lbl = new Label();
            lbl.Text = this.QueryTemplateWherePart;
            lbl.Attributes.Add("style", "display:none");
            this.Controls.Add(lbl);
            base.CreateChildControls();
        }
   }
}
update - I found that the web part doesnt support property search and I am working on a workaround. wait for updates.

2 comments:

Garry Clum said...

Dear Mr Sagi

My name is Garry Clum and I work for the Red Cross.

I have been searching for a way to simply synchronize an outlook calendar with a Sharepoint event list. Sounds simple but not many hits on my search. Then I ran across a thing you did in 2003 on msd2d.com. Impressive and close to what I am looking for but I am not a programmer.

Did you ever develop that idea and if so do you have a web part you could share?

Thank you..

Anonymous said...

plz update the workaround!!!

thx :)