-
-
Save lowedown/ee49f96dcfd568a3dee8c7047d91c5e9 to your computer and use it in GitHub Desktop.
<?xml version="1.0" encoding="utf-8" ?> | |
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> | |
<sitecore> | |
<contentSearch> | |
<customSolrManagedSchema> | |
<commands applyToIndex="my_custom_index"> | |
<add-or-replace-field-type> | |
<name>ngram</name> | |
<class>solr.TextField</class> | |
<positionIncrementGap>100</positionIncrementGap> | |
<indexAnalyzer> | |
<tokenizer> | |
<class>solr.StandardTokenizerFactory</class> | |
</tokenizer> | |
<filters> | |
<class>solr.LowerCaseFilterFactory</class> | |
</filters> | |
<filters> | |
<class>solr.ASCIIFoldingFilterFactory</class> | |
<preserveOriginal>false</preserveOriginal> | |
</filters> | |
<filters> | |
<class>solr.NGramFilterFactory</class> | |
<minGramSize>2</minGramSize> | |
<minGramSize>35</minGramSize> | |
</filters> | |
</indexAnalyzer> | |
<queryAnalyzer> | |
<type>query</type> | |
<tokenizer> | |
<class>solr.StandardTokenizerFactory</class> | |
</tokenizer> | |
<filters> | |
<class>solr.LowerCaseFilterFactory</class> | |
</filters> | |
<filters> | |
<class>solr.ASCIIFoldingFilterFactory</class> | |
<preserveOriginal>false</preserveOriginal> | |
</filters> | |
</queryAnalyzer> | |
</add-field-type> | |
<add-dynamic-field> | |
<name>*_ngram</name> | |
<type>ngram</type> | |
<indexed>true</indexed> | |
<stored>true</stored> | |
<termVectors>true</termVectors> | |
<termPositions>true</termPositions> | |
<termOffsets>true</termOffsets> | |
</add-dynamic-field> | |
<add-dynamic-field> | |
<name>*_ngramm</name> | |
<type>ngram</type> | |
<indexed>true</indexed> | |
<stored>true</stored> | |
<termVectors>true</termVectors> | |
<termPositions>true</termPositions> | |
<termOffsets>true</termOffsets> | |
<multiValued>true</multiValued> | |
</add-dynamic-field> | |
</commands> | |
</customSolrManagedSchema> | |
</contentSearch> | |
<pipelines> | |
<contentSearch.PopulateSolrSchema> | |
<!-- Processor for additional SOLR schema --> | |
<processor type="MyProject.Pipelines.ContentSearch.PopulateSolrSchema.CustomSchemaPopulator, MyProject" | |
patch:after="processor[@type='Sitecore.ContentSearch.SolrProvider.Pipelines.PopulateSolrSchema.PopulateFields, Sitecore.ContentSearch.SolrProvider']"/> | |
</contentSearch.PopulateSolrSchema> | |
</pipelines> | |
</sitecore> | |
</configuration> |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Xml; | |
using System.Xml.Linq; | |
using Sitecore.Configuration; | |
using Sitecore.ContentSearch.SolrProvider.Pipelines.PopulateSolrSchema; | |
using Sitecore.Diagnostics; | |
using Sitecore.Xml; | |
using SolrNet.Schema; | |
namespace MyProject.Pipelines.ContentSearch.PopulateSolrSchema | |
{ | |
public class CustomSchemaPopulator : PopulateFields | |
{ | |
protected string IndexName; | |
public override void Process(PopulateManagedSchemaArgs args) | |
{ | |
IndexName = args.Index.Name; | |
base.Process(args); | |
} | |
protected override ISchemaPopulateHelper GetHelper(SolrNet.Schema.SolrSchema schema) | |
{ | |
Assert.ArgumentNotNull(schema, "schema"); | |
return new CustomSchemaPopulatorHelper(schema, IndexName); | |
} | |
} | |
public class CustomSchemaPopulatorHelper : ISchemaPopulateHelper | |
{ | |
private readonly SolrSchema _solrSchema; | |
private readonly string _indexName; | |
public CustomSchemaPopulatorHelper(SolrSchema solrSchema, string indexName) | |
{ | |
_solrSchema = solrSchema; | |
_indexName = indexName; | |
} | |
public IEnumerable<XElement> GetAllFields() | |
{ | |
var elements = new List<XElement>(); | |
foreach (XmlNode commands in Factory.GetConfigNodes("contentSearch/customSolrManagedSchema/commands")) | |
{ | |
if (IsApplicable(commands, _indexName)) | |
{ | |
elements.AddRange(commands.ChildNodes.Cast<XmlNode>().Select(n => ParseCommand(n.OuterXml, _solrSchema))); | |
} | |
} | |
return elements; | |
} | |
private XElement ParseCommand(string xml, SolrSchema schema) | |
{ | |
var element = XElement.Parse(xml); | |
// set "add" or "replace" depending if field type already exists in schema | |
if (element.Name == "add-or-replace-field-type") | |
{ | |
var fieldTypeName = element.Elements().FirstOrDefault(e => e.Name == "name"); | |
if (fieldTypeName != null && !string.IsNullOrEmpty(fieldTypeName.Value)) | |
{ | |
if (schema.SolrFieldTypes.Any(f => f.Name == fieldTypeName.Value)) | |
{ | |
element = new XElement("replace-field-type", element.Attributes(), element.Elements()); | |
} | |
else | |
{ | |
element = new XElement("add-field-type", element.Attributes(), element.Elements()); | |
} | |
} | |
} | |
return element; | |
} | |
private bool IsApplicable(XmlNode commands, string indexName) | |
{ | |
var indexes = XmlUtil.GetAttribute("applyToIndex", commands); | |
if (string.IsNullOrEmpty(indexes)) | |
{ | |
return false; | |
} | |
return indexes.Split('|').Any(i => i.ToLower().Equals(indexName.ToLower())); | |
} | |
} | |
} |
Hey @lowedown,
it seems sitecore included an additional function to be added "GetAllFieldTypes" to the interface of "ISchemaPopulateHelper" in sitecore 9.1 and above.
Do you think it is enough/right to return the result from the GetAllFields method?
Best regards and thanks for the share - helped me a lot to understand a bit how the new way works!
Tobi
Hi @D4rkii
Thanks for the feedback. It seems that in 9.1 the values from GetAllFieldTypes() are sent to Solr first and then the values from GetAllFields(). Maybe this is to prevent trying to add fields which do not have a type yet. In my example this doesn't happen as the add-or-replace-field-type command is processed first.
To do it right, I would run the add-field-type and replace-field-type commands in the GetAllFieldTypes() method and all the others in the GetAllFields() method. I haven't had the chance to test this on 9.1 though.
Update 05.11.2018: Added "add-or-replace-field-type" which automatically chooses "add" or "replace" operation depending if the field type alreaedy exists in the schema.