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