Add a dynamic field for float collection to Solr managed schema
Tags: sitecore, solr
Published: 2019-11-01 09:04:32

In Sitecore, there is no dynamic field for `float` collection in Solr managed schema. You can add it by taking the following steps.

---

① Add the following packages to your Visual Studio project.

- Sitecore.ContentSearch.dll
- Sitecore.ContentSearch.SolrProvider.dll
- SolrNet.Core.dll

② Create a class inherit from the `SchemaPopulateHelper`, and override the `GetAllFields` method.

```csharp
public class ExtendedSchemaPopulateHelper : SchemaPopulateHelper
{
    public ExtendedSchemaPopulateHelper(SolrSchema solrSchema) : base(solrSchema)
    {
    }

    public override IEnumerable<XElement> GetAllFields()
    {
        // definition of a dynamic field
        var floatCollectionField = new XElement("add-dynamic-field",
            new XElement("name", "*_fm"),
            new XElement("type", "pfloat"),
            new XElement("indexed", "true"),
            new XElement("stored", "true"),
            new XElement("multiValued", "true"));

        /* NOTE: You can use this.CreateField instead if you use Sitecore 9.3.

         var floatCollectionField = this.CreateField(
             name: "*_fm",
             type: "pfloat",
             required: false,
             indexed: true,
             stored: true,
             multiValued: true,
             omitNorms: false,
             termVectors: false,
             termPositions: false,
             termOffsets: false,
             isDynamic: true);
        */

        return base.GetAllFields().Append(floatCollectionField);
    }
}
```

③ Create a class inherit from the `PopulateFields`, and override the `GetHelper` method.

```csharp
public class ExtendedPopulateFields : PopulateFields
{
    protected override ISchemaPopulateHelper GetHelper(SolrSchema schema)
    {
        // return a customized helper instance
        return new ExtendedSchemaPopulateHelper(schema);
    }
}
```

④ Replace the default processor to a customized one by configuration.

```xml
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:search="http://www.sitecore.net/xmlconfig/search/">
  <sitecore role:require="Standalone or ContentManagement or ContentDelivery" search:require="solr">
    <pipelines>
      <contentSearch.PopulateSolrSchema>
          <processor type="NamespaceTo.ExtendedPopulateFields, Assembly"
                     patch:instead="*[@type='Sitecore.ContentSearch.SolrProvider.Pipelines.PopulateSolrSchema.PopulateFields, Sitecore.ContentSearch.SolrProvider']" />
      </contentSearch.PopulateSolrSchema>
    </pipelines>
  </sitecore>
</configuration>
```

⑤ Populate the Solr schema in the Control Panel.  

Then, check your Solr schema in `<solr>/server/solr/<core>/conf/managed-schema`.  You can find a definition of the dynamic field.  

```xml
<dynamicField name="*_tf" type="pfloat" indexed="true" stored="true"/>
<dynamicField name="*_td" type="pdouble" indexed="true" stored="true"/>
<dynamicField name="*_pi" type="pint" indexed="true" stored="true"/>
<!-- *_fm should be added here -->
<dynamicField name="*_fm" type="pfloat" multiValued="true" indexed="true" stored="true"/>
<dynamicField name="*_t" type="text_general" indexed="true" stored="true"/>
<dynamicField name="*_i" type="pint" indexed="true" stored="true"/>
```

If you want to map your (Sitecore's) field to this dynamic field, you have to configure field mapping like below. (it's just a sample)

```xml
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:search="http://www.sitecore.net/xmlconfig/search/">
  <sitecore role:require="Standalone or ContentManagement or ContentDelivery" search:require="solr">
    <contentSearch>
      <indexConfigurations>
        <defaultSolrIndexConfiguration type="Sitecore.ContentSearch.SolrProvider.SolrIndexConfiguration, Sitecore.ContentSearch.SolrProvider">
          <fieldMap type="Sitecore.ContentSearch.SolrProvider.SolrFieldMap, Sitecore.ContentSearch.SolrProvider">
            <typeMatches hint="raw:AddTypeMatch">
              <!-- Add a typeMatch -->
              <typeMatch typeName="floatCollection" type="System.Collections.Generic.List`1[System.Single]" fieldNameFormat="{0}_fm" multiValued="true" settingType="Sitecore.ContentSearch.SolrProvider.SolrSearchFieldConfiguration, Sitecore.ContentSearch.SolrProvider" />
            </typeMatches>
            <fieldTypes hint="raw:AddFieldByFieldTypeName">
              <!-- Map your field (lowercase) to floatCollection -->
              <fieldType fieldTypeName="float list" returnType="floatCollection" />
            </fieldTypes>
          </fieldMap>
          <fieldReaders type="Sitecore.ContentSearch.FieldReaders.FieldReaderMap, Sitecore.ContentSearch">
            <param desc="id">defaultFieldReaderMap</param>
            <mapFieldByTypeName hint="raw:AddFieldReaderByFieldTypeName">
              <!-- Implement a field reader and configure for float list -->
              <fieldReader fieldTypeName="float list" fieldReaderType="NamespaceTo.FloatListFieldReader, Assembly" />
            </mapFieldByTypeName>
          </fieldReaders>
        </defaultSolrIndexConfiguration>
      </indexConfigurations>
    </contentSearch>
  </sitecore>
</configuration>
```

I hope this post helps your Sitecore life.