mirror of https://github.com/apache/lucene.git
SOLR-7697: Schema API doesn't take class or luceneMatchVersion attributes into account for the analyzer when adding a new field type.
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1686327 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
81f4c0f1b5
commit
9f8635de07
|
@ -169,6 +169,9 @@ Bug Fixes
|
|||
* SOLR-7689: ReRankQuery rewrite method can change the QueryResultKey causing cache misses.
|
||||
(Emad Nashed, Yonik Seeley, Joel Bernstein)
|
||||
|
||||
* SOLR-7697: Schema API doesn't take class or luceneMatchVersion attributes into
|
||||
account for the analyzer when adding a new field type. (Marius Grama, Steve Rowe)
|
||||
|
||||
Optimizations
|
||||
----------------------
|
||||
* SOLR-7660: Avoid redundant 'exists' calls made to ZK while fetching cluster state updates. (shalin)
|
||||
|
|
|
@ -83,33 +83,45 @@ public class FieldTypeXmlAdapter {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static Element createAnalyzerElement(Document doc, String type, Map<String,?> json) {
|
||||
Element analyzer = doc.createElement("analyzer");
|
||||
protected static Element createAnalyzerElement(Document doc, String type, Map<String,?> analyzer) {
|
||||
Element analyzerElem = appendAttrs(doc.createElement("analyzer"), analyzer);
|
||||
if (type != null)
|
||||
analyzer.setAttribute("type", type);
|
||||
analyzerElem.setAttribute("type", type);
|
||||
|
||||
// charFilter(s)
|
||||
List<Map<String,?>> charFilters = (List<Map<String,?>>)json.get("charFilters");
|
||||
List<Map<String,?>> charFilters = (List<Map<String,?>>)analyzer.get("charFilters");
|
||||
Map<String,?> tokenizer = (Map<String,?>)analyzer.get("tokenizer");
|
||||
List<Map<String,?>> filters = (List<Map<String,?>>)analyzer.get("filters");
|
||||
|
||||
if (analyzer.get("class") == null) {
|
||||
if (charFilters != null)
|
||||
appendFilterElements(doc, analyzer, "charFilter", charFilters);
|
||||
appendFilterElements(doc, analyzerElem, "charFilter", charFilters);
|
||||
|
||||
// tokenizer
|
||||
Map<String,?> tokenizerJson = (Map<String,?>)json.get("tokenizer");
|
||||
if (tokenizerJson == null)
|
||||
if (tokenizer == null)
|
||||
throw new SolrException(ErrorCode.BAD_REQUEST, "Analyzer must define a tokenizer!");
|
||||
|
||||
String tokClass = (String)tokenizerJson.get("class");
|
||||
if (tokClass == null)
|
||||
if (tokenizer.get("class") == null)
|
||||
throw new SolrException(ErrorCode.BAD_REQUEST, "Every tokenizer must define a class property!");
|
||||
|
||||
analyzer.appendChild(appendAttrs(doc.createElement("tokenizer"), tokenizerJson));
|
||||
analyzerElem.appendChild(appendAttrs(doc.createElement("tokenizer"), tokenizer));
|
||||
|
||||
// filter(s)
|
||||
List<Map<String,?>> filters = (List<Map<String,?>>)json.get("filters");
|
||||
if (filters != null)
|
||||
appendFilterElements(doc, analyzer, "filter", filters);
|
||||
appendFilterElements(doc, analyzerElem, "filter", filters);
|
||||
|
||||
return analyzer;
|
||||
} else { // When analyzer class is specified: char filters, tokenizers, and filters are disallowed
|
||||
if (charFilters != null)
|
||||
throw new SolrException
|
||||
(ErrorCode.BAD_REQUEST, "An analyzer with a class property may not define any char filters!");
|
||||
|
||||
if (tokenizer != null)
|
||||
throw new SolrException
|
||||
(ErrorCode.BAD_REQUEST, "An analyzer with a class property may not define a tokenizer!");
|
||||
|
||||
if (filters != null)
|
||||
throw new SolrException
|
||||
(ErrorCode.BAD_REQUEST, "An analyzer with a class property may not define any filters!");
|
||||
}
|
||||
|
||||
return analyzerElem;
|
||||
}
|
||||
|
||||
protected static void appendFilterElements(Document doc, Element analyzer, String filterName, List<Map<String,?>> filters) {
|
||||
|
|
|
@ -52,6 +52,7 @@ import org.apache.lucene.util.BytesRef;
|
|||
import org.apache.lucene.util.BytesRefBuilder;
|
||||
import org.apache.lucene.util.CharsRef;
|
||||
import org.apache.lucene.util.CharsRefBuilder;
|
||||
import org.apache.lucene.util.Version;
|
||||
import org.apache.solr.analysis.SolrAnalyzer;
|
||||
import org.apache.solr.analysis.TokenizerChain;
|
||||
import org.apache.solr.common.SolrException;
|
||||
|
@ -870,9 +871,9 @@ public abstract class FieldType extends FieldProperties {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a description of the given analyzer, by either reporting the Analyzer name
|
||||
* if it's not a TokenizerChain, or if it is, querying each analysis factory for its
|
||||
* name and args.
|
||||
* Returns a description of the given analyzer, by either reporting the Analyzer class
|
||||
* name (and optionally luceneMatchVersion) if it's not a TokenizerChain, or if it is,
|
||||
* querying each analysis factory for its name and args.
|
||||
*/
|
||||
protected static SimpleOrderedMap<Object> getAnalyzerProperties(Analyzer analyzer) {
|
||||
SimpleOrderedMap<Object> analyzerProps = new SimpleOrderedMap<>();
|
||||
|
@ -950,6 +951,9 @@ public abstract class FieldType extends FieldProperties {
|
|||
}
|
||||
} else { // analyzer is not instanceof TokenizerChain
|
||||
analyzerProps.add(CLASS_NAME, analyzer.getClass().getName());
|
||||
if (analyzer.getVersion() != Version.LATEST) {
|
||||
analyzerProps.add(LUCENE_MATCH_VERSION_PARAM, analyzer.getVersion().toString());
|
||||
}
|
||||
}
|
||||
return analyzerProps;
|
||||
}
|
||||
|
|
|
@ -92,6 +92,67 @@ public class TestBulkSchemaAPI extends RestTestBase {
|
|||
|
||||
}
|
||||
|
||||
public void testAnalyzerClass() throws Exception {
|
||||
|
||||
String addFieldTypeAnalyzerWithClass = "{\n" +
|
||||
"'add-field-type' : {" +
|
||||
" 'name' : 'myNewTextFieldWithAnalyzerClass',\n" +
|
||||
" 'class':'solr.TextField',\n" +
|
||||
" 'analyzer' : {\n" +
|
||||
" 'luceneMatchVersion':'5.0.0',\n" +
|
||||
" 'class':'org.apache.lucene.analysis.core.WhitespaceAnalyzer'\n";
|
||||
String charFilters =
|
||||
" 'charFilters' : [{\n" +
|
||||
" 'class':'solr.PatternReplaceCharFilterFactory',\n" +
|
||||
" 'replacement':'$1$1',\n" +
|
||||
" 'pattern':'([a-zA-Z])\\\\\\\\1+'\n" +
|
||||
" }],\n";
|
||||
String tokenizer =
|
||||
" 'tokenizer' : { 'class':'solr.WhitespaceTokenizerFactory' },\n";
|
||||
String filters =
|
||||
" 'filters' : [{ 'class':'solr.ASCIIFoldingFilterFactory' }]\n";
|
||||
String suffix =
|
||||
" }\n"+
|
||||
"}}";
|
||||
|
||||
String response = restTestHarness.post("/schema?wt=json",
|
||||
json(addFieldTypeAnalyzerWithClass + ',' + charFilters + tokenizer + filters + suffix));
|
||||
Map map = (Map)ObjectBuilder.getVal(new JSONParser(new StringReader(response)));
|
||||
List list = (List)map.get("errors");
|
||||
List errorList = (List)((Map)list.get(0)).get("errorMessages");
|
||||
assertEquals(1, errorList.size());
|
||||
assertTrue (((String)errorList.get(0)).contains
|
||||
("An analyzer with a class property may not define any char filters!"));
|
||||
|
||||
response = restTestHarness.post("/schema?wt=json",
|
||||
json(addFieldTypeAnalyzerWithClass + ',' + tokenizer + filters + suffix));
|
||||
map = (Map)ObjectBuilder.getVal(new JSONParser(new StringReader(response)));
|
||||
list = (List)map.get("errors");
|
||||
errorList = (List)((Map)list.get(0)).get("errorMessages");
|
||||
assertEquals(1, errorList.size());
|
||||
assertTrue (((String)errorList.get(0)).contains
|
||||
("An analyzer with a class property may not define a tokenizer!"));
|
||||
|
||||
response = restTestHarness.post("/schema?wt=json",
|
||||
json(addFieldTypeAnalyzerWithClass + ',' + filters + suffix));
|
||||
map = (Map)ObjectBuilder.getVal(new JSONParser(new StringReader(response)));
|
||||
list = (List)map.get("errors");
|
||||
errorList = (List)((Map)list.get(0)).get("errorMessages");
|
||||
assertEquals(1, errorList.size());
|
||||
assertTrue (((String)errorList.get(0)).contains
|
||||
("An analyzer with a class property may not define any filters!"));
|
||||
|
||||
response = restTestHarness.post("/schema?wt=json", json(addFieldTypeAnalyzerWithClass + suffix));
|
||||
map = (Map)ObjectBuilder.getVal(new JSONParser(new StringReader(response)));
|
||||
assertNull(response, map.get("errors"));
|
||||
|
||||
map = getObj(restTestHarness, "myNewTextFieldWithAnalyzerClass", "fieldTypes");
|
||||
assertNotNull(map);
|
||||
Map analyzer = (Map)map.get("analyzer");
|
||||
assertEquals("org.apache.lucene.analysis.core.WhitespaceAnalyzer", String.valueOf(analyzer.get("class")));
|
||||
assertEquals("5.0.0", String.valueOf(analyzer.get("luceneMatchVersion")));
|
||||
}
|
||||
|
||||
|
||||
public void testMultipleCommands() throws Exception{
|
||||
RestTestHarness harness = restTestHarness;
|
||||
|
@ -192,6 +253,16 @@ public class TestBulkSchemaAPI extends RestTestBase {
|
|||
" 'stored':true,\n" +
|
||||
" 'indexed':true\n" +
|
||||
" },\n" +
|
||||
" 'add-field-type' : {" +
|
||||
" 'name' : 'myWhitespaceTxtField',\n" +
|
||||
" 'class':'solr.TextField',\n" +
|
||||
" 'analyzer' : {'class' : 'org.apache.lucene.analysis.core.WhitespaceAnalyzer'}\n" +
|
||||
" },\n"+
|
||||
" 'add-field' : {\n" +
|
||||
" 'name':'a5',\n" +
|
||||
" 'type': 'myWhitespaceTxtField',\n" +
|
||||
" 'stored':true\n" +
|
||||
" },\n" +
|
||||
" 'delete-field' : {'name':'wdf_nocase'},\n" +
|
||||
" 'delete-field-type' : {'name':'wdf_nocase'},\n" +
|
||||
" 'delete-dynamic-field' : {'name':'*_tt'},\n" +
|
||||
|
@ -269,6 +340,13 @@ public class TestBulkSchemaAPI extends RestTestBase {
|
|||
assertNotNull("field a3 not created", m);
|
||||
assertEquals("myNewTxtField", m.get("type"));
|
||||
|
||||
m = getObj(harness, "myWhitespaceTxtField", "fieldTypes");
|
||||
assertNotNull(m);
|
||||
|
||||
m = getObj(harness, "a5", "fields");
|
||||
assertNotNull("field a5 not created", m);
|
||||
assertEquals("myWhitespaceTxtField", m.get("type"));
|
||||
|
||||
m = getObj(harness, "wdf_nocase", "fields");
|
||||
assertNull("field 'wdf_nocase' not deleted", m);
|
||||
|
||||
|
|
Loading…
Reference in New Issue