mirror of https://github.com/apache/lucene.git
SOLR-619 -- refactored IndexSchema so it allows registering copy fields within SolrCoreAware.inform()
git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@678050 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ae123e592a
commit
bed156e2e1
|
@ -152,15 +152,29 @@ public final class IndexSchema {
|
|||
* <p>
|
||||
* Modifying this Map (or any item in it) will affect the real schema
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* NOTE: this function is not thread safe. However, it is safe to use within the standard
|
||||
* <code>inform( SolrCore core )</code> function for <code>SolrCoreAware</code> classes.
|
||||
* Outside <code>inform</code>, this could potentially throw a ConcurrentModificationException
|
||||
* </p>
|
||||
*/
|
||||
public Map<String,SchemaField> getFields() { return fields; }
|
||||
|
||||
/**
|
||||
* Provides direct access to the Map containing all Field Types
|
||||
* in the index, keyed on fild type name.
|
||||
* in the index, keyed on field type name.
|
||||
*
|
||||
* <p>
|
||||
* Modifying this Map (or any item in it) will affect the real schema
|
||||
* Modifying this Map (or any item in it) will affect the real schema. However if you
|
||||
* make any modifications, be sure to call {@link IndexSchema#refreshAnalyzers()} to
|
||||
* update the Analyzers for the registered fields.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* NOTE: this function is not thread safe. However, it is safe to use within the standard
|
||||
* <code>inform( SolrCore core )</code> function for <code>SolrCoreAware</code> classes.
|
||||
* Outside <code>inform</code>, this could potentially throw a ConcurrentModificationException
|
||||
* </p>
|
||||
*/
|
||||
public Map<String,FieldType> getFieldTypes() { return fieldTypes; }
|
||||
|
@ -287,8 +301,19 @@ public final class IndexSchema {
|
|||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This will re-create the Analyzers. If you make any modifications to
|
||||
* the Field map ({@link IndexSchema#getFields()}, this function is required
|
||||
* to synch the internally cached field analyzers.
|
||||
*
|
||||
* @since solr 1.3
|
||||
*/
|
||||
public void refreshAnalyzers()
|
||||
{
|
||||
analyzer = new SolrIndexAnalyzer();
|
||||
queryAnalyzer = new SolrQueryAnalyzer();
|
||||
}
|
||||
|
||||
private class SolrIndexAnalyzer extends Analyzer {
|
||||
protected final HashMap<String,Analyzer> analyzers;
|
||||
|
@ -567,9 +592,8 @@ public final class IndexSchema {
|
|||
/////////////// parse out copyField commands ///////////////
|
||||
// Map<String,ArrayList<SchemaField>> cfields = new HashMap<String,ArrayList<SchemaField>>();
|
||||
// expression = "/schema/copyField";
|
||||
|
||||
ArrayList<DynamicCopy> dCopies = new ArrayList<DynamicCopy>();
|
||||
|
||||
|
||||
dynamicCopyFields = new DynamicCopy[] {};
|
||||
expression = "//copyField";
|
||||
nodes = (NodeList) xpath.evaluate(expression, document, XPathConstants.NODESET);
|
||||
|
||||
|
@ -580,48 +604,7 @@ public final class IndexSchema {
|
|||
String source = DOMUtil.getAttr(attrs,"source","copyField definition");
|
||||
String dest = DOMUtil.getAttr(attrs,"dest", "copyField definition");
|
||||
|
||||
boolean sourceIsPattern = isWildCard(source);
|
||||
boolean destIsPattern = isWildCard(dest);
|
||||
|
||||
log.fine("copyField source='"+source+"' dest='"+dest+"'");
|
||||
SchemaField d = getField(dest);
|
||||
|
||||
if(sourceIsPattern) {
|
||||
if( destIsPattern ) {
|
||||
DynamicField df = null;
|
||||
for( DynamicField dd : dynamicFields ) {
|
||||
if( dd.regex.equals( dest ) ) {
|
||||
df = dd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( df == null ) {
|
||||
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, "copyField dynamic destination must match a dynamicField." );
|
||||
}
|
||||
dCopies.add(new DynamicDestCopy(source, df ));
|
||||
}
|
||||
else {
|
||||
dCopies.add(new DynamicCopy(source, d));
|
||||
}
|
||||
}
|
||||
else if( destIsPattern ) {
|
||||
String msg = "copyField only supports a dynamic destination if the source is also dynamic" ;
|
||||
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, msg );
|
||||
}
|
||||
else {
|
||||
// retrieve the field to force an exception if it doesn't exist
|
||||
SchemaField f = getField(source);
|
||||
|
||||
SchemaField[] destArr = copyFields.get(source);
|
||||
if (destArr==null) {
|
||||
destArr=new SchemaField[]{d};
|
||||
} else {
|
||||
destArr = (SchemaField[])append(destArr,d);
|
||||
}
|
||||
copyFields.put(source,destArr);
|
||||
|
||||
copyFieldTargetCounts.put(d, (copyFieldTargetCounts.containsKey(d) ? copyFieldTargetCounts.get(d) + 1 : 1));
|
||||
}
|
||||
registerCopyField(source, dest);
|
||||
}
|
||||
|
||||
for (Map.Entry<SchemaField, Integer> entry : copyFieldTargetCounts.entrySet()) {
|
||||
|
@ -632,11 +615,6 @@ public final class IndexSchema {
|
|||
}
|
||||
}
|
||||
|
||||
log.finest("Dynamic Copied Fields:" + dCopies);
|
||||
|
||||
// stuff it in a normal array for faster access
|
||||
dynamicCopyFields = (DynamicCopy[])dCopies.toArray(new DynamicCopy[dCopies.size()]);
|
||||
|
||||
} catch (SolrException e) {
|
||||
SolrConfig.severeErrors.add( e );
|
||||
throw e;
|
||||
|
@ -646,13 +624,86 @@ public final class IndexSchema {
|
|||
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Schema Parsing Failed",e,false);
|
||||
}
|
||||
|
||||
analyzer = new SolrIndexAnalyzer();
|
||||
queryAnalyzer = new SolrQueryAnalyzer();
|
||||
// create the field analyzers
|
||||
refreshAnalyzers();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* NOTE: this function is not thread safe. However, it is safe to use within the standard
|
||||
* <code>inform( SolrCore core )</code> function for <code>SolrCoreAware</code> classes.
|
||||
* Outside <code>inform</code>, this could potentially throw a ConcurrentModificationException
|
||||
* </p>
|
||||
*
|
||||
* @see SolrCoreAware
|
||||
*/
|
||||
public void registerCopyField( String source, String dest )
|
||||
{
|
||||
boolean sourceIsPattern = isWildCard(source);
|
||||
boolean destIsPattern = isWildCard(dest);
|
||||
|
||||
log.fine("copyField source='"+source+"' dest='"+dest+"'");
|
||||
SchemaField d = getField(dest);
|
||||
|
||||
if(sourceIsPattern) {
|
||||
if( destIsPattern ) {
|
||||
DynamicField df = null;
|
||||
for( DynamicField dd : dynamicFields ) {
|
||||
if( dd.regex.equals( dest ) ) {
|
||||
df = dd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( df == null ) {
|
||||
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, "copyField dynamic destination must match a dynamicField." );
|
||||
}
|
||||
registerDynamicCopyField(new DynamicDestCopy(source, df ));
|
||||
}
|
||||
else {
|
||||
registerDynamicCopyField(new DynamicCopy(source, d));
|
||||
}
|
||||
}
|
||||
else if( destIsPattern ) {
|
||||
String msg = "copyField only supports a dynamic destination if the source is also dynamic" ;
|
||||
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, msg );
|
||||
}
|
||||
else {
|
||||
// retrieve the field to force an exception if it doesn't exist
|
||||
SchemaField f = getField(source);
|
||||
|
||||
SchemaField[] destArr = copyFields.get(source);
|
||||
if (destArr==null) {
|
||||
destArr=new SchemaField[]{d};
|
||||
} else {
|
||||
destArr = (SchemaField[])append(destArr,d);
|
||||
}
|
||||
copyFields.put(source,destArr);
|
||||
|
||||
copyFieldTargetCounts.put(d, (copyFieldTargetCounts.containsKey(d) ? copyFieldTargetCounts.get(d) + 1 : 1));
|
||||
}
|
||||
}
|
||||
|
||||
private void registerDynamicCopyField( DynamicCopy dcopy )
|
||||
{
|
||||
if( dynamicCopyFields == null ) {
|
||||
dynamicCopyFields = new DynamicCopy[] {dcopy};
|
||||
}
|
||||
else {
|
||||
int i=0;
|
||||
DynamicCopy[] old = dynamicCopyFields;
|
||||
dynamicCopyFields = new DynamicCopy[dynamicCopyFields.length+1];
|
||||
for( DynamicCopy dc : old ) {
|
||||
dynamicCopyFields[i++] = dc;
|
||||
}
|
||||
dynamicCopyFields[i++] = dcopy;
|
||||
old = null;
|
||||
}
|
||||
log.finest("Dynamic Copy Field:" + dcopy );
|
||||
}
|
||||
|
||||
private static Object[] append(Object[] orig, Object item) {
|
||||
Object[] newArr = (Object[])java.lang.reflect.Array.newInstance(orig.getClass().getComponentType(), orig.length+1);
|
||||
System.arraycopy(orig, 0, newArr, 0, orig.length);
|
||||
System.arraycopy(orig, 0, newArr, 0, orig.length);
|
||||
newArr[orig.length] = item;
|
||||
return newArr;
|
||||
}
|
||||
|
@ -864,18 +915,18 @@ public final class IndexSchema {
|
|||
|
||||
private DynamicField[] dynamicFields;
|
||||
public SchemaField[] getDynamicFieldPrototypes() {
|
||||
SchemaField[] df = new SchemaField[dynamicFields.length];
|
||||
for (int i=0;i<dynamicFields.length;i++) {
|
||||
df[i] = dynamicFields[i].prototype;
|
||||
}
|
||||
return df;
|
||||
SchemaField[] df = new SchemaField[dynamicFields.length];
|
||||
for (int i=0;i<dynamicFields.length;i++) {
|
||||
df[i] = dynamicFields[i].prototype;
|
||||
}
|
||||
return df;
|
||||
}
|
||||
|
||||
public String getDynamicPattern(String fieldName) {
|
||||
for (DynamicField df : dynamicFields) {
|
||||
if (df.matches(fieldName)) return df.regex;
|
||||
}
|
||||
return null;
|
||||
for (DynamicField df : dynamicFields) {
|
||||
if (df.matches(fieldName)) return df.regex;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1024,19 +1075,19 @@ public final class IndexSchema {
|
|||
*/
|
||||
|
||||
public SchemaField[] getCopySources(String destField) {
|
||||
SchemaField f = getField(destField);
|
||||
if (!isCopyFieldTarget(f)) {
|
||||
return new SchemaField[0];
|
||||
}
|
||||
List<SchemaField> sf = new ArrayList<SchemaField>();
|
||||
for (Map.Entry<String, SchemaField[]> cfs : copyFields.entrySet()) {
|
||||
for (SchemaField cf : cfs.getValue()) {
|
||||
if (cf.getName().equals(destField)) {
|
||||
sf.add(getField(cfs.getKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return sf.toArray(new SchemaField[1]);
|
||||
SchemaField f = getField(destField);
|
||||
if (!isCopyFieldTarget(f)) {
|
||||
return new SchemaField[0];
|
||||
}
|
||||
List<SchemaField> sf = new ArrayList<SchemaField>();
|
||||
for (Map.Entry<String, SchemaField[]> cfs : copyFields.entrySet()) {
|
||||
for (SchemaField cf : cfs.getValue()) {
|
||||
if (cf.getName().equals(destField)) {
|
||||
sf.add(getField(cfs.getKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return sf.toArray(new SchemaField[1]);
|
||||
}
|
||||
/**
|
||||
* Get all copy fields, both the static and the dynamic ones.
|
||||
|
@ -1091,10 +1142,3 @@ public final class IndexSchema {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -20,8 +20,10 @@ package org.apache.solr.schema;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.apache.solr.common.params.CommonParams;
|
||||
import org.apache.solr.common.params.MapSolrParams;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.request.LocalSolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
|
@ -90,4 +92,41 @@ public class IndexSchemaTest extends AbstractSolrTestCase {
|
|||
assertTrue("wrong class", similarity instanceof MockConfigurableSimilarity);
|
||||
assertEquals("is there an echo?", ((MockConfigurableSimilarity)similarity).getPassthrough());
|
||||
}
|
||||
|
||||
public void testRuntimeFieldCreation()
|
||||
{
|
||||
// any field manipulation needs to happen when you know the core will not
|
||||
// be accepting any requests. Typically this is done within the inform()
|
||||
// method. Since this is a single threaded test, we can change the fields
|
||||
// willi-nilly
|
||||
|
||||
SolrCore core = h.getCore();
|
||||
IndexSchema schema = core.getSchema();
|
||||
final String fieldName = "runtimefield";
|
||||
SchemaField sf = new SchemaField( fieldName, schema.getFieldTypes().get( "string" ) );
|
||||
schema.getFields().put( fieldName, sf );
|
||||
|
||||
// also register a new copy field (from our new field)
|
||||
schema.registerCopyField( fieldName, "dynamic_runtime" );
|
||||
schema.refreshAnalyzers();
|
||||
|
||||
assertU(adoc("id", "10", "title", "test", fieldName, "aaa"));
|
||||
assertU(commit());
|
||||
|
||||
SolrQuery query = new SolrQuery( fieldName+":aaa" );
|
||||
query.set( "indent", "true" );
|
||||
SolrQueryRequest req = new LocalSolrQueryRequest( core, query );
|
||||
|
||||
assertQ("Make sure they got in", req
|
||||
,"//*[@numFound='1']"
|
||||
,"//result/doc[1]/int[@name='id'][.='10']"
|
||||
);
|
||||
|
||||
// Check to see if our copy field made it out safely
|
||||
query.setQuery( "dynamic_runtime:aaa" );
|
||||
assertQ("Make sure they got in", req
|
||||
,"//*[@numFound='1']"
|
||||
,"//result/doc[1]/int[@name='id'][.='10']"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue