in

Dot Net Mafia

Group site for Tulsa area .NETdevelopers, with blogs dealing with (usually) .NET, SharePoint, and other Microsoft products, as well as some discussion of general programming related concepts.

This Blog

Syndication

Corey Roth - DotNetMafia.com - Tip of the Day

Bringing you the latest time saving tips for SharePoint, MOSS 2007, ASP.NET, LINQ, and Visual Studio 2008

NEW! Web Part for Wildcard Search in Enterprise Search

I have had countless people tell me that they want to be able to do wildcard search in MOSS Enterprise Search using the existing Search Center site templates.  The Search Center site template uses keyword query syntax which does not support wildcards.  To get wildcards you need to use a full text SQL query.  Until now the only solutions to getting wildcard search was either use Ontolica's Wildcard Search or write your own search page.  Neither option has ever been appealing to me.  Ontolica replaces the entire search center and provides an extra layer of abstraction to your managed properties.  I didn't want to write my own search page because the search center already produces great looking results and it would be a lot of effort to reinvent everything on the search page.  The reason why you would have had to write your own search page is that you could not get access via conventional means to the objects to change the query.

This is why I finally decided to take matters into my own hand.  I really just wanted to just inherit from CoreResultsWebPart, change out the keyword query with a FullTextSqlQuery and call it good.  Anyone who may have looked at this before knows it is not that simple.  The class that does all the work SearchResultsHiddenObject is marked internal.   Right now this seems an impossible task unless you bend the rules a little.  That's right.  I decided I am going to break OO rules and use reflection to get to the properties I needed.  Some people say you should never do this and that its a hack.  I agree to some extent, but when you are programming against an API and the provider of said API doesn't give you the tools you need to do your job, sometimes you have to bend the rules.  Let's face it.  Microsoft should have given us this support out of the box and at the minimum should have allowed us to change the query that the CoreResultsWebPart executes through the API.  They did neither so here we are.

So how does the code work?  Well, CoreResultsWebPart happens to be the one class in all of the Enterprise Search controls that isn't marked sealed.  That is good news.  Through the use of Reflector, I discovered the method I need to inherit from is SetPropertiesOnHiddenObject.  Microsoft was even nice enough to mark this method as virtual for me.  I then got access to the type and then used the base type to get a FieldInfo object for the private field srho (which is the SearchResultsHiddenObject). 

// get the type of the current object

Type coreResultsWebPartType = this.GetType();

 

// get the private field containing the searchResultsHiddenObject

FieldInfo searchResultsHiddenObjectField = coreResultsWebPartType.BaseType.GetField("srho", BindingFlags.NonPublic | BindingFlags.Instance);

Once, I got access to the hidden object, I read the value of the KeywordQuery property to get what the user searched for.  I then had to set this value to null, because I was replacing the keyword query with a FullTextSqlQuery. 

// get the actual internal srho object attached to CoreResultsWebPart

object searchResultsHiddenObject = searchResultsHiddenObjectField.GetValue(this);

 

// get the type of the srho

Type searchResultsHiddenObjecType = searchResultsHiddenObject.GetType();

 

// get the keyword query property

PropertyInfo keywordQueryProperty = searchResultsHiddenObjecType.GetProperty("KeywordQuery", BindingFlags.Instance | BindingFlags.Public);

 

// read what the user searched for

string keywordQuery = (string)keywordQueryProperty.GetValue(searchResultsHiddenObject, null);

 

// set the keywordProperty to null so we can change it to a fullTextQuery

keywordQueryProperty.SetValue(searchResultsHiddenObject, null, null);

It was then just a matter of forming a new SQL query string (check the code on how I did that), and setting some additional fields _IsFullTextQuerySetFromForm and m_bIsKeywordQuery

 

// get the fullTextQuery field

PropertyInfo fullTextQueryProperty = searchResultsHiddenObjecType.GetProperty("FullTextQuery", BindingFlags.Instance | BindingFlags.Public);

 

// create a new query and set it

string fullTextQueryString = GetFullTextQuery(keywordQuery, keywordsAsQuery);

fullTextQueryProperty.SetValue(searchResultsHiddenObject, fullTextQueryString, null);

 

// this field needs to be set to true to use a full text query

FieldInfo fullTextQuerySetField = searchResultsHiddenObjecType.GetField("_IsFullTextQuerySetFromForm", BindingFlags.NonPublic | BindingFlags.Instance);

fullTextQuerySetField.SetValue(searchResultsHiddenObject, true);

 

// tell the srho that it is not a keyword query any more

FieldInfo isKeywordQueryField = searchResultsHiddenObjecType.GetField("m_bIsKeywordQuery", BindingFlags.NonPublic | BindingFlags.Instance);

isKeywordQueryField.SetValue(searchResultsHiddenObject, false);

The code for this is really pretty simple (aside from the reflection).  Had the SearchResultsHiddenObject been marked public, we could have had this functionality over a year ago, but oh well. 

Installation

Installation is relatively simple and instructions are included in a readme file in the document.  A solution package has been provided for ease of installation.  Once the package has been installed activate the Wildcard Search Web Part feature on your site collection.  I went with a site collection feature because the search center site does not have a web part gallery in it.  Now that the feature is activated, go to your results page in your Search Center, edit the page, and add the Wildcard Search Core Results Web Part to the Bottom Zone.  You can then remove the old CoreResultsWebPart.  Also note that this web part requires .NET Framework 3.5 because I used LINQ to XML to parse through the SelectColumns property.

Usage

Once you have the web part installed, you can perform a wildcard search by just adding an asterisk to whatever you type in the search box.  For example app* would return mataches on app, apple, and application.  You can also set the Always Use Wildcard property in the Miscellaneous property settings to always perform a wildcard search.

One thing to note.  Wildcard searches reek havoc on your search relevance.  Where you might be used to having nice clean looking results with your keyword searches, your wildcard searches will look different.  It might not always be obvious why a particular item was returned in the search results.  The best thing to do is try and see if it works for your particular situation.

This type of web part probably could have been sold, but I thought it was more important to give it to the community.  This feature gets asked for by MOSS customers all the time.  Finally there is an easy solution to implementing it.  Since this web part is new, I am sure there are going to be issues with it.  Please, log any issues you run into in installation or in us on the issue tracker of the CodePlex site.  Currently, it only supports simple keyword queries.  I still need to implement support for passing scopes and managed properties, so look for that in an update soon.

You can find the release files at CodePlex.

Corey Roth is a MOSS consultant for Stonebridge.

Comments

 

SharePoint, SharePoint and stuff said:

Heute geht aber die Post ab im SharePoint Land: da wird zum einen das Podcasting Kit for SharePoint (PKS)

June 9, 2008 12:04 PM
 

Mirrored Blogs said:

Heute geht aber die Post ab im SharePoint Land: da wird zum einen das Podcasting Kit for SharePoint

June 9, 2008 12:48 PM
 

CoreyRoth said:

The link didnt come through on some of the RSS feeds, so here it is again.

www.codeplex.com/WildcardSearch

June 9, 2008 2:00 PM
 

Bookmarking the web - w24/2008 - double density design said:

Pingback from  Bookmarking the web - w24/2008 - double density design

June 15, 2008 6:52 AM
 

fromonesource said:

Does this work with people search?

June 18, 2008 10:17 PM
 

CoreyRoth said:

Ah excellent question about using it with people search.  Right now, the answer is no because people search uses PeopleCoreResultsWebPart instead of CoreResultsWebPart.  This should be relatively easy to implement though.  I'll log a feature for this on CodePlex.

June 23, 2008 10:02 AM
 

nilang19 said:

Hi gr8 article, it helped me lot.

I am installed your Wild card search on our server. its working like a charm.

however I also deployed Facets Search, it was working with normal search. however with wild card search(codeplex.com/sct). and its giving following error:

Error while executing web part: Microsoft.Office.Server.Search.WebControls.SrhdcGenericException: Your search cannot be completed because of a service error. Try your search again or contact your administrator for more information.

Thanks,

Nilang Shah

June 24, 2008 9:01 AM
 

CoreyRoth said:

I get the feeling that at some point I will have to write a Search Facets web part that is compatible with wildcard search because the way the search facets web part works is that it does its own keyword query to get the list of facets.  Out of the box this poses a problem because even if it did work, it would actually be running a different query than what the WildcardSearchWebPart so the facets would actually be incorrect.  I'll note this as an issue.  Thanks.

June 24, 2008 1:24 PM
 

Tim said:

Hi Corey,

That is really a magnificent webpart. You've hit the nail on the head as far as missing-functionality in Search. I have 2 comments:

1. I'm using a BDC Scope. Do you have any idea when you might include the Scope functionality?

2. I noticed when I use the wildcard (eg: appl*) the hit highlighting or bolding doesnt appear. It only appears for exact matches.

Great work.

Cheers.

August 31, 2008 12:06 AM
 

stevebowers said:

Hi Corey,

Great webpart.   :-)  I noticed that it does not display the RSS links either on the webpart, or the "Search Action Links" webpart when the wildcard webpart is on the page, even if you select the "Display RSS Link" option in the webpart configuration.   Is this a casualty of using Full Text Query, or am I doing something wrong?

Thanks.

September 3, 2008 7:44 PM
 

CoreyRoth said:

I noticed that I needed to add scope to the query recently myself.  I think I can get that working pretty quickly.   The highlighting definitely doesn't work when using this.  I think it is based off keywords, but I need to confirm by using the builtin advanced search web part.

I hadn't noticed the Search Action Links being missing until you pointed it out.  Let me do some more research and I'll log these items on CodePlex.

September 15, 2008 4:12 PM
 

CoreyRoth said:

I have confirmed that when using the Advanced Search web part the RSS links button is not present either.  This tells me that the RSS link only supports keyword queries.  So it looks like this is by design on that web part.  Thanks.

September 16, 2008 12:51 PM
 

Recent Links Tagged With "wildcard" - JabberTags said:

Pingback from  Recent Links Tagged With "wildcard" - JabberTags

January 10, 2009 4:04 PM
 

kathir said:

Hi Corey

I am not able to implement the sorting i.e order by in the fulltextquery property. while executing the query, it shows the error query is malformed.

Please help me to resolve this issue on how to use the sorting in this wildcardsearch webpart.

Cheers

Kathir

February 11, 2009 5:31 AM
 

CoreyRoth said:

I believe the reason it does this is because CoreResultsWebPart has functionality to automatically append an ORDER BY clause onto the string based on if the built in web part property is set to relevance or date.  I think it might be possible to work around this, so I am going to log it as a feature to look into.

February 17, 2009 11:15 AM
 

thetony01 said:

I installed this as per the readme instructions.  I was able to add the webpart to my search results page, but nothing is ever returned, with or without a wild card search.  I have removed the core results web part as instructed.  I have not removed the paging and high confidence web parts.  Am I missing something?

February 25, 2009 2:45 PM
 

thetony01 said:

Please disregard my previous message.  I did not have the 3.5 framework installed and therefore it was not working.  As soon as I installed the 3.5 framework results started to show in the webpart.  I have run into a new issue however.  The quick search seems to work fine, but I am unable to get the advanced search to work.  Do I need to do anything special for that to work?

February 26, 2009 10:09 AM
 

CoreyRoth said:

Yes 3. is definitely required since I use LINQ to XML to query which managed properties you are using.  I'll take a look into the Advanced Search issue.  In the meantime, you can always create another results page for use with your advanced search and use the original CoreResultsWebPart.

March 4, 2009 11:11 AM
 

Mathews said:

Corey

First, Thanks so much by this excellent web part.

In my job, we used MOSS in spanish, and your webpart is working very well.

Only exists one issue:

For the search results by the scope "This site:...." or "This list...", MOSS used the page osssearchresults.aspx (not results.aspx). I custom this page adding your webpart.

The problem is: The webpart don't filter by the scope and the search is made in all the site collection.

The wildcard is working, the problem is only the scope don't working

I edit osssearchresults.aspx in this way:

1) I add the register directive:

<%@ Register TagPrefix="WpNs0" Namespace="DotNetMafia.Office.Server.Search.WildcardSearch" Assembly="DotNetMafia.Office.Server.Search.WildcardSearch, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"%>

2) I replace all the ocurrences of "SearchWC:CoreResultsWebPart"

by

"WpNs0:WildcardSearchCoreResultsWebPart"

I missing something?

March 26, 2009 1:31 PM
 

Mathews said:

It's an error:

Step 2) In the page exists two webparts "SearchWC:CoreResultsWebPart".

I replace the ocurrences of "SearchWC:CoreResultsWebPart"

by

"WpNs0:WildcardSearchCoreResultsWebPart"

ONLY in the second webpart.

Corey, I missing something aditional change?

Thanks

March 26, 2009 2:55 PM
 

CoreyRoth said:

I assume you have the latest version right?  I did make some changes to correct issues around scopes in the last build.  Not sure that you can get this web part to work on the OSSSearchResults.aspx in the way that you are.

April 2, 2009 12:33 PM
 

SharePoint Search doesn’t have Wildcard searching » novolocus.com said:

Pingback from  SharePoint Search doesn&#8217;t have Wildcard searching &raquo; novolocus.com

May 21, 2009 7:54 AM
 

SharePoint can have Wildcard searching… » Andy Burns’ SharePoint Blog said:

Pingback from  SharePoint can have Wildcard searching&#8230; &raquo; Andy Burns&#8217; SharePoint Blog

May 27, 2009 3:24 AM

About CoreyRoth

Corey Roth is a MOSS Consultant for Stonebridge, Inc. specializing in clients in the Energy Sector.
2009 dotnetmafia.
Powered by Community Server (Non-Commercial Edition), by Telligent Systems