You are viewing a plain text version of this content. The canonical link for it is here.
Posted to solr-dev@lucene.apache.org by Noble Paul നോബിള് नोब्ळ् <no...@gmail.com> on 2008/07/19 05:48:45 UTC
Re: svn commit: r678050 - in /lucene/solr/trunk/src: java/org/apache/solr/schema/IndexSchema.java test/org/apache/solr/schema/IndexSchemaTest.java
The private void registerDynamicCopyField can use the code which I
gave . It is cleaner to use System.arrayCopy() rather than doing a
manual copy
2008/7/19 <ry...@apache.org>:
> Author: ryan
> Date: Fri Jul 18 14:43:42 2008
> New Revision: 678050
>
> URL: http://svn.apache.org/viewvc?rev=678050&view=rev
> Log:
> SOLR-619 -- refactored IndexSchema so it allows registering copy fields within SolrCoreAware.inform()
>
> Modified:
> lucene/solr/trunk/src/java/org/apache/solr/schema/IndexSchema.java
> lucene/solr/trunk/src/test/org/apache/solr/schema/IndexSchemaTest.java
>
> Modified: lucene/solr/trunk/src/java/org/apache/solr/schema/IndexSchema.java
> URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/schema/IndexSchema.java?rev=678050&r1=678049&r2=678050&view=diff
> ==============================================================================
> --- lucene/solr/trunk/src/java/org/apache/solr/schema/IndexSchema.java (original)
> +++ lucene/solr/trunk/src/java/org/apache/solr/schema/IndexSchema.java Fri Jul 18 14:43:42 2008
> @@ -152,15 +152,29 @@
> * <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 @@
> }
> 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 @@
> /////////////// 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 @@
> 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 @@
> }
> }
>
> - 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 @@
> 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 @@
>
> 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 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 @@
> }
>
> }
> -
> -
> -
> -
> -
> -
> -
>
> Modified: lucene/solr/trunk/src/test/org/apache/solr/schema/IndexSchemaTest.java
> URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/test/org/apache/solr/schema/IndexSchemaTest.java?rev=678050&r1=678049&r2=678050&view=diff
> ==============================================================================
> --- lucene/solr/trunk/src/test/org/apache/solr/schema/IndexSchemaTest.java (original)
> +++ lucene/solr/trunk/src/test/org/apache/solr/schema/IndexSchemaTest.java Fri Jul 18 14:43:42 2008
> @@ -20,8 +20,10 @@
> 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 @@
> 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']"
> + );
> + }
> }
>
>
>
--
--Noble Paul