9

I have ContentSearch code that works and runs fine using Lucene. When I switch the configs over to Solr, the query fails, and the logs state that the field I'm using in the query doesn't exist.

[IndexField("tags")]
public IEnumerable<ID> Tags { get; set; }

16644 13:34:20 ERROR Solr Error : ["undefined field tags"] - Query attempted: [((_template:(2d7ad1cb107e44158690c03e0b65f90c) AND -_name:("__Standard Values")) AND tags:(fc8ac78af9aa495fb4ee08aca0444e1b))]

Note that the error says 'undefined field tags', but really, this should be tags_sm when Sitecore adds the suffix to the query. Changing [IndexField("tags")] to [IndexField("tags_sm")] gets it working....but now my code is Search Provider dependent.

Is there something I'm missing to make this work without the suffix? I thought Sitecore would automatically add it in there?

Here is how the query looks:-

var filterPredicate = PredicateBuilder.True<ArticleSearchResultItem>()
                .And(x => x.TemplateId == IArticlePageItemConstants.TemplateId && x.Name != "__Standard Values");

if (parameters.TagId != (ID)null && parameters.TagId != ID.Null)
{
   filterPredicate = filterPredicate.And(x => x.Tags.Contains(parameters.TagId));
}

var queryable = searchContext.GetQueryable<ArticleSearchResultItem>();
var searchResults = queryable
                .Where(filterPredicate);

This is on Sitecore 8.1 Update-2, using Solr 6.1.0. Thanks.

6
  • I have always had to modify my custom index fields when switching from Lucene to SOLR. I will be interested if is it possible to do it without. I do notice in habitat switching from 8 to 9 (now SOLR) they did not change the field names. github.com/Sitecore/Habitat/blob/master/src/Foundation/Indexing/…
    – Chris Auer
    Oct 3, 2018 at 17:52
  • Try to change the public IEnumerable<ID> to public IEnumerable<string> or public List<string> Oct 4, 2018 at 20:00
  • I've had the same issue too. Have you tried adding an explicit mapping for IEnumerable<ID> in the config, something like this? <typeMatch type="System.Collections.Generic.IEnumerable`1[Sitecore.Data.ID]" typeName="idCollection" fieldNameFormat="{0}_sm" multiValued="true" settingType="Sitecore.ContentSearch.SolrProvider.SolrSearchFieldConfiguration, Sitecore.ContentSearch.SolrProvider" />
    – mikaelnet
    Feb 26, 2019 at 10:02
  • Maybe this can be solved with a type converter too. I haven't tried it, as I've opted for the approach of adding field type, such as _sm. [TypeConverter(typeof(IndexFieldEnumerableConverter))]
    – mikaelnet
    Feb 26, 2019 at 10:07
  • 1
    The other way is to add "tags" field in solr schema.xml and then use of <copyField source="tags_sm" dest="tags" />. This way you don't need to change your code. Oct 22, 2019 at 10:35

2 Answers 2

4

You must have a typematch for type IEnumerable<ID> in your index configuration to make this work. So, create a patch file and include typematch as follow

<typeMatch typeName="idIEnumerable"        type="System.Collections.Generic.IEnumerable`1[[Sitecore.Data.ID, Sitecore.Kernel]]"         fieldNameFormat="{0}_sm"  multiValued="true"    settingType="Sitecore.ContentSearch.SolrProvider.SolrSearchFieldConfiguration, Sitecore.ContentSearch.SolrProvider"  />

or if you want your property to be List<ID> then have below typematch included

<typeMatch typeName="idList"        type="System.Collections.Generic.List`1[[Sitecore.Data.ID, Sitecore.Kernel]]"       fieldNameFormat="{0}_sm"  multiValued="true"    settingType="Sitecore.ContentSearch.SolrProvider.SolrSearchFieldConfiguration, Sitecore.ContentSearch.SolrProvider"  />

Explanation

tags would get converted to tags_sm in query only if there is a typematch found for that particular type (IEnumerable<ID> in your case). You can find out the same by looking at typematchs section for your index configuration in showconfig.aspx.

enter image description here

Behind the scene SolrSearchConfiguration class reads this configuration and it sets the strongly type by calling Type.GetType(type) and that works fine with simple types like DateTime, Int32, Int64, String, String[], List etc..

enter image description here

But when type is complex such as IEnumerable<ID> then Type.GetType() method expect a AssemblyQualifiedName. You can get AssemblyQualifiedName for any type by just calling type.GetType() method.

2

You could change the default field mapping in your index configuration (i would create a custom indexconfiguration based on the default):

sitecore/contentSearch/indexConfigurations/defaultSolrIndexConfiguration/fieldMap/typeMatches

and remove the suffix from the format (this example is for text fields, you should change it for ID-types):

before:

<typeMatch 
    typeName="text"                   
    type="System.String"
    fieldNameFormat="{0}_t"
    cultureFormat="_{1}"
    settingType="Sitecore.ContentSearch.SolrProvider.SolrSearchFieldConfiguration, Sitecore.ContentSearch.SolrProvider" />

without suffix:

<typeMatch 
        typeName="text"                   
        type="System.String"
        fieldNameFormat="{0}"
        cultureFormat=""
        settingType="Sitecore.ContentSearch.SolrProvider.SolrSearchFieldConfiguration, Sitecore.ContentSearch.SolrProvider" />

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.