SOLR-7682: Schema API - Add New Copy Field Rule doesn't allow maxChars parameter

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1685900 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Steven Rowe 2015-06-16 20:02:00 +00:00
parent 8ab21aa657
commit faa80ae324
5 changed files with 81 additions and 13 deletions

View File

@ -151,6 +151,8 @@ Bug Fixes
* SOLR-7091: Nested documents with unknown fields don't work in schemaless mode.
(Steve Rowe)
* SOLR-7682: Schema API: add-copy-field should accept the maxChars parameter. (Steve Rowe)
Optimizations
----------------------

View File

@ -101,6 +101,7 @@ public class IndexSchema {
public static final String FIELD_TYPES = FIELD_TYPE + "s";
public static final String INTERNAL_POLY_FIELD_PREFIX = "*" + FieldType.POLY_FIELD_SEPARATOR;
public static final String LUCENE_MATCH_VERSION_PARAM = "luceneMatchVersion";
public static final String MAX_CHARS = "maxChars";
public static final String NAME = "name";
public static final String REQUIRED = "required";
public static final String SCHEMA = "schema";
@ -115,7 +116,6 @@ public class IndexSchema {
private static final String AT = "@";
private static final String DESTINATION_DYNAMIC_BASE = "destDynamicBase";
private static final String MAX_CHARS = "maxChars";
private static final String SOLR_CORE_NAME = "solr.core.name";
private static final String SOURCE_DYNAMIC_BASE = "sourceDynamicBase";
private static final String SOURCE_EXPLICIT_FIELDS = "sourceExplicitFields";
@ -1667,6 +1667,8 @@ public class IndexSchema {
* Requires synchronizing on the object returned by
* {@link #getSchemaUpdateLock()}.
*
* @see #addCopyFields(String,Collection,int) to limit the number of copied characters.
*
* @param copyFields Key is the name of the source field name, value is a collection of target field names. Fields must exist.
* @param persist to persist the schema or not
* @return The new Schema with the copy fields added
@ -1677,6 +1679,25 @@ public class IndexSchema {
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
}
/**
* Copies this schema and adds the new copy fields to the copy.
*
* Requires synchronizing on the object returned by
* {@link #getSchemaUpdateLock()}
*
* @param source source field name
* @param destinations collection of target field names
* @param maxChars max number of characters to copy from the source to each
* of the destinations. Use {@link CopyField#UNLIMITED}
* if you don't want to limit the number of copied chars.
* @return The new Schema with the copy fields added
*/
public IndexSchema addCopyFields(String source, Collection<String> destinations, int maxChars) {
String msg = "This IndexSchema is not mutable.";
log.error(msg);
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
}
/**
* Copies this schema and deletes the given copy fields from the copy.
* <p>

View File

@ -771,6 +771,24 @@ public final class ManagedIndexSchema extends IndexSchema {
return newSchema;
}
@Override
public ManagedIndexSchema addCopyFields(String source, Collection<String> destinations, int maxChars) {
ManagedIndexSchema newSchema;
if (isMutable) {
newSchema = shallowCopy(true);
for (String destination : destinations) {
newSchema.registerCopyField(source, destination, maxChars);
}
newSchema.postReadInform();
newSchema.refreshAnalyzers();
} else {
String msg = "This ManagedIndexSchema is not mutable.";
log.error(msg);
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
}
return newSchema;
}
@Override
public ManagedIndexSchema deleteCopyFields(Map<String,Collection<String>> copyFields) {
ManagedIndexSchema newSchema;

View File

@ -48,6 +48,7 @@ import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static org.apache.solr.schema.FieldType.CLASS_NAME;
import static org.apache.solr.schema.IndexSchema.DESTINATION;
import static org.apache.solr.schema.IndexSchema.MAX_CHARS;
import static org.apache.solr.schema.IndexSchema.NAME;
import static org.apache.solr.schema.IndexSchema.SOURCE;
import static org.apache.solr.schema.IndexSchema.TYPE;
@ -198,15 +199,29 @@ public class SchemaManager {
@Override public boolean perform(CommandOperation op, SchemaManager mgr) {
String src = op.getStr(SOURCE);
List<String> dests = op.getStrs(DESTINATION);
int maxChars = CopyField.UNLIMITED; // If maxChars is not specified, there is no limit on copied chars
String maxCharsStr = op.getStr(MAX_CHARS, null);
if (null != maxCharsStr) {
try {
maxChars = Integer.parseInt(maxCharsStr);
} catch (NumberFormatException e) {
op.addError("Exception parsing " + MAX_CHARS + " '" + maxCharsStr + "': " + getErrorStr(e));
}
if (maxChars < 0) {
op.addError(MAX_CHARS + " '" + maxCharsStr + "' is negative.");
}
}
if (op.hasError())
return false;
if ( ! op.getValuesExcluding(SOURCE, DESTINATION).isEmpty()) {
op.addError("Only the '" + SOURCE + "' and '" + DESTINATION
if ( ! op.getValuesExcluding(SOURCE, DESTINATION, MAX_CHARS).isEmpty()) {
op.addError("Only the '" + SOURCE + "', '" + DESTINATION + "' and '" + MAX_CHARS
+ "' params are allowed with the 'add-copy-field' operation");
return false;
}
try {
mgr.managedIndexSchema = mgr.managedIndexSchema.addCopyFields(singletonMap(src, dests), false);
mgr.managedIndexSchema = mgr.managedIndexSchema.addCopyFields(src, dests, maxChars);
return true;
} catch (Exception e) {
op.addError(getErrorStr(e));

View File

@ -329,7 +329,9 @@ public class TestBulkSchemaAPI extends RestTestBase {
" {'source':'NewDynamicField1*', 'dest':'NewField2' },\n" +
" {'source':'NewDynamicField2*', 'dest':'NewField2' },\n" +
" {'source':'NewDynamicField3*', 'dest':'NewField3' },\n" +
" {'source':'NewField4', 'dest':'NewField3' }]\n" +
" {'source':'NewField4', 'dest':'NewField3' },\n" +
" {'source':'NewField4', 'dest':'NewField2', maxChars: 100 },\n" +
" {'source':'NewField4', 'dest':['NewField1'], maxChars: 3333 }]\n" +
"}\n";
String response = harness.post("/schema?wt=json", json(cmds));
@ -374,8 +376,17 @@ public class TestBulkSchemaAPI extends RestTestBase {
assertEquals("NewField3", ((Map)list.get(0)).get("dest"));
list = getSourceCopyFields(harness, "NewField4");
assertEquals(1, list.size());
assertEquals("NewField3", ((Map)list.get(0)).get("dest"));
assertEquals(3, list.size());
map.clear();
for (Object obj : list) {
map.put(((Map)obj).get("dest"), ((Map)obj).get("maxChars"));
}
assertTrue(map.containsKey("NewField1"));
assertEquals(3333L, map.get("NewField1"));
assertTrue(map.containsKey("NewField2"));
assertEquals(100L, map.get("NewField2"));
assertTrue(map.containsKey("NewField3"));
assertNull(map.get("NewField3"));
cmds = "{'delete-field-type' : {'name':'NewFieldType'}}";
response = harness.post("/schema?wt=json", json(cmds));
@ -433,8 +444,9 @@ public class TestBulkSchemaAPI extends RestTestBase {
for (Object obj : list) {
set.add(((Map)obj).get("source"));
}
assertEquals(3, list.size());
assertEquals(4, list.size());
assertTrue(set.contains("NewField1"));
assertTrue(set.contains("NewField4"));
assertTrue(set.contains("NewDynamicField1*"));
assertTrue(set.contains("NewDynamicField2*"));
@ -473,11 +485,11 @@ public class TestBulkSchemaAPI extends RestTestBase {
assertTrue(set.contains("NewDynamicField3*"));
cmds = "{\n" +
" 'delete-copy-field': [{'source':'NewField1', 'dest':['NewField2', 'NewDynamicField1A']},\n" +
" {'source':'NewDynamicField1*', 'dest':'NewField2' },\n" +
" {'source':'NewDynamicField2*', 'dest':'NewField2' },\n" +
" {'source':'NewDynamicField3*', 'dest':'NewField3' },\n" +
" {'source':'NewField4', 'dest':'NewField3' }]\n" +
" 'delete-copy-field': [{'source':'NewField1', 'dest':['NewField2', 'NewDynamicField1A'] },\n" +
" {'source':'NewDynamicField1*', 'dest':'NewField2' },\n" +
" {'source':'NewDynamicField2*', 'dest':'NewField2' },\n" +
" {'source':'NewDynamicField3*', 'dest':'NewField3' },\n" +
" {'source':'NewField4', 'dest':['NewField1', 'NewField2', 'NewField3']}]\n" +
"}\n";
response = harness.post("/schema?wt=json", json(cmds));
map = (Map)ObjectBuilder.getVal(new JSONParser(new StringReader(response)));