Solr – Partial Match Is Not Working On Computed Field… Why?

So here I am. After so many years away from it, I’m back to having some fun with Solr.

giphy

But the fun didn’t last that long.

TL:DR: Just go check out the solution on my Sitecore Stack Exchange question.

This week I found myself wasting half of a day trying to figure out why the partial match wasn’t working on my computed field.

Here is the scenario:

public class UnifiedSearchResultItem : SearchResultItem
{
    [IndexField("unifiedtitle")]
    public string UnifiedTitle { get; set; }
}
var indexSitecore = GetSearchIndex();
using (var searchContext = indexSitecore.CreateSearchContext())
{
	var keywordFilter = PredicateBuilder.False<UnifiedSearchResultItem>();
	keywordFilter = keywordFilter.Or(item => item.UnifiedTitle.Like("Windermere"));

	var results = searchContext.GetQueryable<UnifiedSearchResultItem>()
				   .Where(keywordFilter)
				   .GetResults();
}
<field fieldName="unifiedtitle"
returnType="string">
Project.Foundation.Indexing.ComputedFields.UnifiedTitleComputedField, Project.Foundation.Indexing
</field>

solr


solr2

As we can see on the Solr screenshot there was one result that should be coming from my query. But no matter what the results count of the above code was always zero.

I decided it was time for some scientific experiments…

giphy-1

Things I Tried Without Any Luck

  1. Add a suffix _s so that the attribute on the SearchResultItem class would have this: [IndexField(“unifiedtitle_s”)]. It didn’t work.
  2. Change the operator from Like() to Contains(). It didn’t work neither.
  3. Add indexType=”tokenized” to the computed field configuration. Guess what? Nah.

My First Little Win In This Battle

Everything was going bad until I tried this:

keywordFilter = keywordFilter.Or(item => item.UnifiedTitle.Like("Windermere on the Mount"));

All of a sudden I was receiving the expected result from Solr. Interesting… So that means that when I filter by the exact value of the field it works. That showed me that the field was searchable and that it had some kind of issue with partial matches.

giphy-2

But not only that, I realized that the partial match was working on the Content field:

keywordFilter = keywordFilter.Or(item => item.Content.Like("Windermere"));

Ok, so that proves that partial match was possible and I wasn’t getting crazy. All I had to do was to compare both configurations from Content and UnifiedTitle.

 

But Both Fields Are Already Tokenized… Right?

My first reaction was to think about the indexType=”tokenized” thing that I had already added to my config. I knew that in order to be able to do a partial match on a Solr field this field must be tokenized.

So I decided to take a deeper look at those two fields on the Solr side:

solr3


solr4

Differences between them:

  1. The type (string vs text_general).
  2. The UnifiedTitle is not using the StandardTokenizerFactory
  3. The UnifiedTitle is not tokenized at the schema level

 

The Solution!

Finally, everything became clear on my head.

You can’t do partial match on string fields. 

All I had to do was to change its config to:

<field fieldName="unifiedtitle" returnType="text">
Project.Foundation.Indexing.ComputedFields.UnifiedTitleComputedField, Project.Foundation.Indexing
</field>

After doing that and rebuilding my Solr index I had this:

solr5

And there it is. By changing its type to text I was finally able to tokenize this field and use a partial match on it. I then confirmed here that string fields can’t be tokenized. That was my entire issue, guys… Hope you liked it, see you next time.

giphy-3

 

 

 

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 )

Google photo

You are commenting using your Google 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