lucene-solr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From markrmil...@apache.org
Subject svn commit: r895455 [1/2] - in /lucene/solr/branches/cloud: ./ contrib/clustering/ contrib/clustering/src/main/java/org/apache/solr/handler/clustering/carrot2/ example/exampledocs/ example/solr/conf/ src/common/org/apache/solr/common/ src/java/org/apac...
Date Sun, 03 Jan 2010 18:06:49 GMT
Author: markrmiller
Date: Sun Jan  3 18:06:36 2010
New Revision: 895455

URL: http://svn.apache.org/viewvc?rev=895455&view=rev
Log:
merge up to r894477

Added:
    lucene/solr/branches/cloud/src/java/org/apache/solr/schema/AbstractSubTypeFieldType.java
      - copied unchanged from r895450, lucene/solr/trunk/src/java/org/apache/solr/schema/AbstractSubTypeFieldType.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/schema/CoordinateFieldType.java
      - copied unchanged from r895450, lucene/solr/trunk/src/java/org/apache/solr/schema/CoordinateFieldType.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/schema/GeoHashField.java
      - copied unchanged from r895450, lucene/solr/trunk/src/java/org/apache/solr/schema/GeoHashField.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/schema/PointType.java
      - copied unchanged from r895450, lucene/solr/trunk/src/java/org/apache/solr/schema/PointType.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/schema/SchemaAware.java
      - copied unchanged from r895450, lucene/solr/trunk/src/java/org/apache/solr/schema/SchemaAware.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/schema/SpatialTileField.java
      - copied unchanged from r895450, lucene/solr/trunk/src/java/org/apache/solr/schema/SpatialTileField.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/MultiValueSource.java
      - copied unchanged from r895450, lucene/solr/trunk/src/java/org/apache/solr/search/function/MultiValueSource.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/VectorValueSource.java
      - copied unchanged from r895450, lucene/solr/trunk/src/java/org/apache/solr/search/function/VectorValueSource.java
    lucene/solr/branches/cloud/src/test/org/apache/solr/schema/PolyFieldTest.java
      - copied unchanged from r895450, lucene/solr/trunk/src/test/org/apache/solr/schema/PolyFieldTest.java
Modified:
    lucene/solr/branches/cloud/   (props changed)
    lucene/solr/branches/cloud/CHANGES.txt
    lucene/solr/branches/cloud/contrib/clustering/CHANGES.txt
    lucene/solr/branches/cloud/contrib/clustering/src/main/java/org/apache/solr/handler/clustering/carrot2/CarrotClusteringEngine.java
    lucene/solr/branches/cloud/example/exampledocs/hd.xml
    lucene/solr/branches/cloud/example/exampledocs/ipod_other.xml
    lucene/solr/branches/cloud/example/exampledocs/ipod_video.xml
    lucene/solr/branches/cloud/example/exampledocs/mem.xml
    lucene/solr/branches/cloud/example/exampledocs/monitor.xml
    lucene/solr/branches/cloud/example/exampledocs/monitor2.xml
    lucene/solr/branches/cloud/example/exampledocs/mp500.xml
    lucene/solr/branches/cloud/example/exampledocs/sd500.xml
    lucene/solr/branches/cloud/example/exampledocs/vidcard.xml
    lucene/solr/branches/cloud/example/solr/conf/schema.xml
    lucene/solr/branches/cloud/example/solr/conf/solrconfig.xml
    lucene/solr/branches/cloud/src/common/org/apache/solr/common/SolrException.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreContainer.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrCore.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryComponent.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/schema/FieldType.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/schema/IndexSchema.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/schema/SchemaField.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/schema/TextField.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/search/FieldQParserPlugin.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/search/SolrQueryParser.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/search/ValueSourceParser.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/DocValues.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/DistanceUtils.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/HaversineFunction.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/SquaredEuclideanFunction.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/VectorDistanceFunction.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/update/DocumentBuilder.java
    lucene/solr/branches/cloud/src/java/org/apache/solr/util/AbstractSolrTestCase.java
    lucene/solr/branches/cloud/src/solrj/org/apache/solr/client/solrj/impl/StreamingUpdateSolrServer.java
    lucene/solr/branches/cloud/src/test/org/apache/solr/BaseDistributedSearchTestCase.java
    lucene/solr/branches/cloud/src/test/org/apache/solr/handler/component/DistributedSpellCheckComponentTest.java
    lucene/solr/branches/cloud/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java
    lucene/solr/branches/cloud/src/test/org/apache/solr/update/DocumentBuilderTest.java
    lucene/solr/branches/cloud/src/test/test-files/solr/conf/schema.xml
    lucene/solr/branches/cloud/src/test/test-files/solr/conf/schema11.xml

Propchange: lucene/solr/branches/cloud/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sun Jan  3 18:06:36 2010
@@ -1 +1 @@
-/lucene/solr/trunk:888480-892821
+/lucene/solr/trunk:888480-895450

Modified: lucene/solr/branches/cloud/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/CHANGES.txt?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/CHANGES.txt (original)
+++ lucene/solr/branches/cloud/CHANGES.txt Sun Jan  3 18:06:36 2010
@@ -24,7 +24,10 @@
 ==================  1.5.0-dev ==================
 Upgrading from Solr 1.4
 ----------------------
-The experimental ALIAS command is removed in Solr 1.5 (SOLR-1637).
+* The experimental ALIAS command is removed in Solr 1.5 (SOLR-1637)
+
+* Using solr.xml is recommended for single cores also (SOLR-1621)
+
 
 Versions of Major Components
 ---------------------
@@ -71,6 +74,11 @@
 
 * SOLR-1653: Add PatternReplaceCharFilter (koji)
 
+* SOLR-1131: FieldTypes can now output multiple Fields per Type and still be searched.  This can be handy for hiding the details of a particular
+  implementation such as in the spatial case. (Chris Mattmann, shalin, noble, gsingers, yonik)
+
+* SOLR-1586: Add support for Geohash and Spatial Tile FieldType (Chris Mattmann, gsingers)  
+
 Optimizations
 ----------------------
 
@@ -178,6 +186,8 @@
 * SOLR-1674: Improve analysis tests and cut over to new TokenStream API.
   (Robert Muir via Mark Miller)
 
+* SOLR-1661 : Remove adminCore from CoreContainer . removed deprecated methods setAdminCore(), getAdminCore() (noble)
+
 Build
 ----------------------
 

Modified: lucene/solr/branches/cloud/contrib/clustering/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/contrib/clustering/CHANGES.txt?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/contrib/clustering/CHANGES.txt (original)
+++ lucene/solr/branches/cloud/contrib/clustering/CHANGES.txt Sun Jan  3 18:06:36 2010
@@ -8,6 +8,10 @@
 
 $Id:$
 
+================== Release 1.5-dev ==================
+
+* SOLR-1684: Switch to use the SolrIndexSearcher.doc(int, Set<String>) method b/c it can use the document cache (gsingers)
+
 ================== Release 1.4.0 ==================
 
 Solr Clustering will be released for the first time in Solr 1.4.  See http://wiki.apache.org/solr/ClusteringComponent

Modified: lucene/solr/branches/cloud/contrib/clustering/src/main/java/org/apache/solr/handler/clustering/carrot2/CarrotClusteringEngine.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/contrib/clustering/src/main/java/org/apache/solr/handler/clustering/carrot2/CarrotClusteringEngine.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/contrib/clustering/src/main/java/org/apache/solr/handler/clustering/carrot2/CarrotClusteringEngine.java (original)
+++ lucene/solr/branches/cloud/contrib/clustering/src/main/java/org/apache/solr/handler/clustering/carrot2/CarrotClusteringEngine.java Sun Jan  3 18:06:36 2010
@@ -152,8 +152,7 @@
 
     SolrIndexSearcher searcher = sreq.getSearcher();
     List<Document> result = new ArrayList<Document>(docList.size());
-    FieldSelector fieldSelector = new SetBasedFieldSelector(fieldsToLoad,
-            Collections.emptySet());
+
     float[] scores = {1.0f};
     int[] docsHolder = new int[1];
     Query theQuery = query;
@@ -161,7 +160,7 @@
     while (docsIter.hasNext()) {
       Integer id = docsIter.next();
       org.apache.lucene.document.Document doc = searcher.doc(id,
-              fieldSelector);
+              fieldsToLoad);
       String snippet = getValue(doc, snippetField);
       if (produceSummary == true) {
         docsHolder[0] = id.intValue();

Modified: lucene/solr/branches/cloud/example/exampledocs/hd.xml
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/example/exampledocs/hd.xml?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/example/exampledocs/hd.xml (original)
+++ lucene/solr/branches/cloud/example/exampledocs/hd.xml Sun Jan  3 18:06:36 2010
@@ -28,6 +28,7 @@
   <field name="popularity">6</field>
   <field name="inStock">true</field>
   <field name="manufacturedate_dt">2006-02-13T15:26:37Z</field>
+  <field name="store">45.17614,-93.87341</field>
 </doc>
 
 <doc>
@@ -42,6 +43,8 @@
   <field name="price">350</field>
   <field name="popularity">6</field>
   <field name="inStock">true</field>
+  <!-- Buffalo store -->
+  <field name="store">45.17614,-93.87341</field>
   <field name="manufacturedate_dt">2006-02-13T15:26:37Z</field>
 </doc>
 </add>

Modified: lucene/solr/branches/cloud/example/exampledocs/ipod_other.xml
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/example/exampledocs/ipod_other.xml?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/example/exampledocs/ipod_other.xml (original)
+++ lucene/solr/branches/cloud/example/exampledocs/ipod_other.xml Sun Jan  3 18:06:36 2010
@@ -28,6 +28,8 @@
   <field name="price">19.95</field>
   <field name="popularity">1</field>
   <field name="inStock">false</field>
+  <!-- Buffalo store -->
+  <field name="store">45.17614,-93.87341</field>
   <field name="manufacturedate_dt">2005-08-01T16:30:25Z</field>
 </doc>
 
@@ -42,6 +44,8 @@
   <field name="price">11.50</field>
   <field name="popularity">1</field>
   <field name="inStock">false</field>
+  <!-- San Francisco store -->
+  <field name="store">37.7752,-122.4232</field>
   <field name="manufacturedate_dt">2006-02-14T23:55:59Z</field>
 </doc>
 

Modified: lucene/solr/branches/cloud/example/exampledocs/ipod_video.xml
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/example/exampledocs/ipod_video.xml?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/example/exampledocs/ipod_video.xml (original)
+++ lucene/solr/branches/cloud/example/exampledocs/ipod_video.xml Sun Jan  3 18:06:36 2010
@@ -32,5 +32,7 @@
   <field name="price">399.00</field>
   <field name="popularity">10</field>
   <field name="inStock">true</field>
+  <!-- San Francisco store -->
+  <field name="store">37.7752,-122.4232</field>
   <field name="manufacturedate_dt">2005-10-12T08:00:00Z</field>
 </doc></add>

Modified: lucene/solr/branches/cloud/example/exampledocs/mem.xml
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/example/exampledocs/mem.xml?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/example/exampledocs/mem.xml (original)
+++ lucene/solr/branches/cloud/example/exampledocs/mem.xml Sun Jan  3 18:06:36 2010
@@ -26,6 +26,8 @@
   <field name="price">185</field>
   <field name="popularity">5</field>
   <field name="inStock">true</field>
+  <!-- San Francisco store -->
+  <field name="store">37.7752,-122.4232</field>
   <field name="manufacturedate_dt">2006-02-13T15:26:37Z</field>
 </doc>
 
@@ -38,6 +40,8 @@
   <field name="price">74.99</field>
   <field name="popularity">7</field>
   <field name="inStock">true</field>
+  <!-- San Francisco store -->
+  <field name="store">37.7752,-122.4232</field>
   <field name="manufacturedate_dt">2006-02-13T15:26:37Z</field>
 </doc>
 
@@ -51,6 +55,8 @@
   <!-- note: price & popularity is missing on this one -->
   <field name="popularity">0</field>
   <field name="inStock">true</field>
+  <!-- Buffalo store -->
+  <field name="store">45.17614,-93.87341</field>
   <field name="manufacturedate_dt">2006-02-13T15:26:37Z</field>
 </doc>
 

Modified: lucene/solr/branches/cloud/example/exampledocs/monitor.xml
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/example/exampledocs/monitor.xml?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/example/exampledocs/monitor.xml (original)
+++ lucene/solr/branches/cloud/example/exampledocs/monitor.xml Sun Jan  3 18:06:36 2010
@@ -27,5 +27,7 @@
   <field name="price">2199</field>
   <field name="popularity">6</field>
   <field name="inStock">true</field>
+  <!-- Buffalo store -->
+  <field name="store">45.17614,-93.87341</field>
 </doc></add>
 

Modified: lucene/solr/branches/cloud/example/exampledocs/monitor2.xml
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/example/exampledocs/monitor2.xml?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/example/exampledocs/monitor2.xml (original)
+++ lucene/solr/branches/cloud/example/exampledocs/monitor2.xml Sun Jan  3 18:06:36 2010
@@ -26,5 +26,7 @@
   <field name="price">279.95</field>
   <field name="popularity">6</field>
   <field name="inStock">true</field>
+  <!-- Buffalo store -->
+  <field name="store">45.17614,-93.87341</field>
 </doc></add>
 

Modified: lucene/solr/branches/cloud/example/exampledocs/mp500.xml
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/example/exampledocs/mp500.xml?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/example/exampledocs/mp500.xml (original)
+++ lucene/solr/branches/cloud/example/exampledocs/mp500.xml Sun Jan  3 18:06:36 2010
@@ -35,5 +35,7 @@
   <field name="price">179.99</field>
   <field name="popularity">6</field>
   <field name="inStock">true</field>
+  <!-- Buffalo store -->
+  <field name="store">45.17614,-93.87341</field>
 </doc></add>
 

Modified: lucene/solr/branches/cloud/example/exampledocs/sd500.xml
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/example/exampledocs/sd500.xml?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/example/exampledocs/sd500.xml (original)
+++ lucene/solr/branches/cloud/example/exampledocs/sd500.xml Sun Jan  3 18:06:36 2010
@@ -31,4 +31,6 @@
   <field name="popularity">7</field>
   <field name="inStock">true</field>
   <field name="manufacturedate_dt">2006-02-13T15:26:37Z</field>
+  <!-- Buffalo store -->
+  <field name="store">45.17614,-93.87341</field>
 </doc></add>

Modified: lucene/solr/branches/cloud/example/exampledocs/vidcard.xml
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/example/exampledocs/vidcard.xml?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/example/exampledocs/vidcard.xml (original)
+++ lucene/solr/branches/cloud/example/exampledocs/vidcard.xml Sun Jan  3 18:06:36 2010
@@ -30,6 +30,7 @@
   <field name="weight">16</field>
   <field name="price">479.95</field>
   <field name="popularity">7</field>
+  <field name="store">40.7143,-74.006</field>
   <field name="inStock">false</field>
   <field name="manufacturedate_dt">2006-02-13T15:26:37Z/DAY</field>
 </doc>
@@ -50,5 +51,7 @@
   <field name="popularity">7</field>
   <field name="inStock">false</field>
   <field name="manufacturedate_dt">2006-02-13T15:26:37Z/DAY</field>
+  <!-- NYC store -->
+  <field name="store">40.7143,-74.006</field>
 </doc>
 </add>

Modified: lucene/solr/branches/cloud/example/solr/conf/schema.xml
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/example/solr/conf/schema.xml?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/example/solr/conf/schema.xml (original)
+++ lucene/solr/branches/cloud/example/solr/conf/schema.xml Sun Jan  3 18:06:36 2010
@@ -394,8 +394,38 @@
 
     <!-- since fields of this type are by default not stored or indexed,
          any data added to them will be ignored outright.  --> 
-    <fieldtype name="ignored" stored="false" indexed="false" multiValued="true" class="solr.StrField" /> 
+    <fieldtype name="ignored" stored="false" indexed="false" multiValued="true" class="solr.StrField" />
 
+    <!-- This point type indexes the coordinates as separate fields (subFields)
+      If subFieldType is defined, it references a type, and a dynamic field
+      definition is created matching *___<typename>.  Alternately, if 
+      subFieldSuffix is defined, that is used to create the subFields.
+      Example: if subFieldType="double", then the coordinates would be
+        indexed in fields myloc_0___double,myloc_1___double.
+      Example: if subFieldSuffix="_d" then the coordinates would be indexed
+        in fields myloc_0_d,myloc_1_d
+      The subFields are an implementation detail of the fieldType, and end
+      users normally should not need to know about them.
+     -->
+    <fieldType name="location" class="solr.PointType" dimension="2" subFieldSuffix="_d"/>
+
+   <!--
+    A Geohash is a compact representation of a latitude longitude pair in a single field.
+
+    See http://wiki.apache.org/solr/SpatialSearch
+   -->
+    <fieldtype name="geohash" class="solr.GeoHashField"/>
+
+    <!--
+      A SpatialTileField is like a set of zoom levels on an interactive map (i.e. Google Maps or MapQuest).  It takes a lat/lon
+      field and indexes it into (end - start) different fields, each representing a different zoom level.
+      This can then be leveraged to quickly narrow the search space by creating a filter, at an appropriate tier level,
+      that only has to enumerate a minimum number of terms.
+
+      See http://wiki.apache.org/solr/SpatialSearch
+     -->
+    <fieldType name="tile" class="solr.SpatialTileField" start="4" end="15" subFieldSuffix="_tiled"/>
+    
  </types>
 
 
@@ -440,6 +470,9 @@
    <field name="popularity" type="int" indexed="true" stored="true" />
    <field name="inStock" type="boolean" indexed="true" stored="true" />
 
+   <field name="store" type="location" indexed="true" stored="true"/>
+   <field name="store_hash" type="geohash" indexed="true" stored="false"/>
+   <field name="store_tiles" type="tile" indexed="true" stored="false"/>
 
    <!-- Common metadata fields, named specifically to match up with
      SolrCell metadata when parsing rich documents such as Word, PDF.
@@ -494,7 +527,11 @@
    <dynamicField name="*_b"  type="boolean" indexed="true"  stored="true"/>
    <dynamicField name="*_f"  type="float"  indexed="true"  stored="true"/>
    <dynamicField name="*_d"  type="double" indexed="true"  stored="true"/>
+
+   <dynamicField name="*_tiled"  type="double" indexed="true"  stored="false"/>
+
    <dynamicField name="*_dt" type="date"    indexed="true"  stored="true"/>
+   <dynamicField name="*_p"  type="location" indexed="true" stored="true"/>
 
    <!-- some trie-coded dynamic fields for faster range queries -->
    <dynamicField name="*_ti" type="tint"    indexed="true"  stored="true"/>
@@ -534,6 +571,8 @@
         or to add multiple fields to the same field for easier/faster searching.  -->
 
    <copyField source="cat" dest="text"/>
+   <copyField source="store" dest="store_hash"/>
+   <copyField source="store" dest="store_tiles"/>
    <copyField source="name" dest="text"/>
    <copyField source="manu" dest="text"/>
    <copyField source="features" dest="text"/>

Modified: lucene/solr/branches/cloud/example/solr/conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/example/solr/conf/solrconfig.xml?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/example/solr/conf/solrconfig.xml (original)
+++ lucene/solr/branches/cloud/example/solr/conf/solrconfig.xml Sun Jan  3 18:06:36 2010
@@ -682,17 +682,17 @@
   the standard or dismax SearchHandler) queries such that a separate request is
   not needed to get suggestions.
 
+  See http://wiki.apache.org/solr/SpellCheckComponent for details on the request
+  parameters. 
+
   IN OTHER WORDS, THERE IS REALLY GOOD CHANCE THE SETUP BELOW IS NOT WHAT YOU
   WANT FOR YOUR PRODUCTION SYSTEM!
   #############################################################################
   -->
   <requestHandler name="/spell" class="solr.SearchHandler" lazy="true">
     <lst name="defaults">
-      <!-- omp = Only More Popular -->
       <str name="spellcheck.onlyMorePopular">false</str>
-      <!-- exr = Extended Results -->
       <str name="spellcheck.extendedResults">false</str>
-      <!--  The number of suggestions to return -->
       <str name="spellcheck.count">1</str>
     </lst>
     <arr name="last-components">

Modified: lucene/solr/branches/cloud/src/common/org/apache/solr/common/SolrException.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/common/org/apache/solr/common/SolrException.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/common/org/apache/solr/common/SolrException.java (original)
+++ lucene/solr/branches/cloud/src/common/org/apache/solr/common/SolrException.java Sun Jan  3 18:06:36 2010
@@ -38,7 +38,7 @@
     SERVER_ERROR( 500 ),
     SERVICE_UNAVAILABLE( 503 ),
     UNKNOWN(0);
-    final int code;
+    public final int code;
     
     private ErrorCode( int c )
     {

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreContainer.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreContainer.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreContainer.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/core/CoreContainer.java Sun Jan  3 18:06:36 2010
@@ -71,8 +71,6 @@
   protected String libDir = null;
   protected ClassLoader libLoader = null;
   protected SolrResourceLoader loader = null;
-  @Deprecated
-  protected java.lang.ref.WeakReference<SolrCore> adminCore = null;
   protected Properties containerProperties;
   protected Map<String ,IndexSchema> indexSchemaCache;
   protected String adminHandler;
@@ -260,7 +258,6 @@
    * 
    * @param dir the home directory of all resources.
    * @param cfgis the configuration file InputStream
-   * @param configName
    * @throws ParserConfigurationException
    * @throws IOException
    * @throws SAXException
@@ -680,43 +677,7 @@
     }
   }
 
-  /**
-   * Sets the preferred core used to handle MultiCore admin tasks.
-   */
-  @Deprecated
-  public void setAdminCore(SolrCore core) {
-    synchronized (cores) {
-      adminCore = new java.lang.ref.WeakReference<SolrCore>(core);
-    }
-  }
-
-  /**
-   * Ensures there is a valid core to handle MultiCore admin taks and
-   * increase its refcount.
-   * @see SolrCore#close() 
-   * @return the acquired admin core, null if no core is available
-   */
-  @Deprecated
-  public SolrCore getAdminCore() {
-    synchronized (cores) {
-      SolrCore core = adminCore != null ? adminCore.get() : null;
-      if (core != null && !core.isClosed()) {
-        core.open();
-      } else {
-        for (SolrCore c : cores.values()) {
-          if (c != null) {
-            core = c;
-            core.open();
-            setAdminCore(core);
-            break;
-          }
-        }
-      }
-      return core;
-    }
-  }
-
-  // ---------------- Multicore self related methods --------------- 
+  // ---------------- Multicore self related methods ---------------
   /** 
    * Creates a CoreAdminHandler for this MultiCore.
    * @return a CoreAdminHandler

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrCore.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrCore.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrCore.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/core/SolrCore.java Sun Jan  3 18:06:36 2010
@@ -684,10 +684,7 @@
    *   <li>All MBeans will be unregistered from MBeanServer if JMX was enabled
    *       </li>
    * </ul>
-   * <p>
-   * This method should always be called when the core is obtained through
-   * {@link CoreContainer#getCore} or {@link CoreContainer#getAdminCore}.
-   * </p>
+   * <p>   
    * <p>
    * The behavior of this method is determined by the result of decrementing
    * the core's reference count (A core is created with a refrence count of 1)...

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryComponent.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryComponent.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryComponent.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/handler/component/QueryComponent.java Sun Jan  3 18:06:36 2010
@@ -19,14 +19,11 @@
 
 import org.apache.lucene.document.Field;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.search.*;
-import org.apache.lucene.search.FieldCache.DoubleParser;
-import org.apache.lucene.search.FieldCache.LongParser;
-import org.apache.lucene.search.FieldCache.FloatParser;
-import org.apache.lucene.search.FieldCache.IntParser;
-import org.apache.lucene.search.FieldCache.Parser;
 import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.search.FieldComparator;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.SortField;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrDocumentList;
 import org.apache.solr.common.SolrException;
@@ -38,15 +35,14 @@
 import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrQueryResponse;
-import org.apache.solr.schema.SchemaField;
 import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.SchemaField;
 import org.apache.solr.search.*;
 import org.apache.solr.util.SolrPluginUtils;
 
 import java.io.IOException;
 import java.net.URL;
 import java.util.*;
-import java.text.Collator;
 
 /**
  * TODO!
@@ -187,6 +183,14 @@
     rsp.add("response",rb.getResults().docList);
     rsp.getToLog().add("hits", rb.getResults().docList.matches());
 
+    doFieldSortValues(rb, searcher);
+    doPrefetch(rb);
+  }
+
+  protected void doFieldSortValues(ResponseBuilder rb, SolrIndexSearcher searcher) throws IOException
+  {
+    SolrQueryRequest req = rb.req;
+    SolrQueryResponse rsp = rb.rsp;
 
     // The query cache doesn't currently store sort field values, and SolrIndexSearcher doesn't
     // currently have an option to return sort field values.  Because of this, we
@@ -264,7 +268,12 @@
 
       rsp.add("sort_values", sortVals);
     }
+  }
 
+  protected void doPrefetch(ResponseBuilder rb) throws IOException
+  {
+    SolrQueryRequest req = rb.req;
+    SolrQueryResponse rsp = rb.rsp;
     //pre-fetch returned documents
     if (!req.getParams().getBool(ShardParams.IS_SHARD,false) && rb.getResults().docList != null && rb.getResults().docList.size()<=50) {
       // TODO: this may depend on the highlighter component (or other components?)
@@ -557,10 +566,12 @@
       for (SolrDocument doc : docs) {
         Object id = doc.getFieldValue(keyFieldName);
         ShardDoc sdoc = rb.resultIds.get(id.toString());
-        if (returnScores && sdoc.score != null) {
-          doc.setField("score", sdoc.score);
+        if (sdoc != null) {
+          if (returnScores && sdoc.score != null) {
+              doc.setField("score", sdoc.score);
+          }
+          rb._responseDocs.set(sdoc.positionInResponse, doc);
         }
-        rb._responseDocs.set(sdoc.positionInResponse, doc);
       }      
     }
   }

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/schema/FieldType.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/schema/FieldType.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/schema/FieldType.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/schema/FieldType.java Sun Jan  3 18:06:36 2010
@@ -20,14 +20,14 @@
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.analysis.Analyzer;
-import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.Tokenizer;
-import org.apache.lucene.analysis.Token;
 import org.apache.lucene.analysis.tokenattributes.TermAttribute;
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.TermRangeQuery;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.index.Term;
 import org.apache.solr.search.function.ValueSource;
 import org.apache.solr.search.function.OrdFieldSource;
 import org.apache.solr.search.Sorting;
@@ -36,11 +36,17 @@
 import org.apache.solr.request.TextResponseWriter;
 import org.apache.solr.analysis.SolrAnalyzer;
 import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.params.MapSolrParams;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import java.util.Map;
 import java.util.HashMap;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.ArrayList;
 import java.io.Reader;
 import java.io.IOException;
 
@@ -52,6 +58,14 @@
 public abstract class FieldType extends FieldProperties {
   public static final Logger log = LoggerFactory.getLogger(FieldType.class);
 
+  /**
+   * The default poly field separator.
+   *
+   * @see #createFields(SchemaField, String, float)
+   * @see #isPolyField()
+   */
+  public static final String POLY_FIELD_SEPARATOR = "___";
+
   /** The name of the type (not the name of the field) */
   protected String typeName;
   /** additional arguments specified in the field type declaration */
@@ -59,9 +73,10 @@
   /** properties explicitly set to true */
   protected int trueProperties;
   /** properties explicitly set to false */
-  protected int falseProperties;  
+  protected int falseProperties;
   int properties;
 
+
   /** Returns true if fields of this type should be tokenized */
   public boolean isTokenized() {
     return (properties & TOKENIZED) != 0;
@@ -72,6 +87,17 @@
     return (properties & MULTIVALUED) != 0;
   }
 
+  /**
+   * A "polyField" is a FieldType that can produce more than one Fieldable instance for a single value, via the {@link #createFields(org.apache.solr.schema.SchemaField, String, float)} method.  This is useful
+   * when hiding the implementation details of a field from the Solr end user.  For instance, a spatial point may be represented by multiple different fields.
+   * @return true if the {@link #createFields(org.apache.solr.schema.SchemaField, String, float)} method may return more than one field
+   */
+  public boolean isPolyField(){
+    return false;
+  }
+
+
+
   /** Returns true if a single field value of this type has multiple logical values
    *  for the purposes of faceting, sorting, etc.  Text fields normally return
    *  true since each token/word is a logical value.
@@ -85,7 +111,8 @@
    * Common boolean properties have already been handled.
    *
    */
-  protected void init(IndexSchema schema, Map<String,String> args) {
+  protected void init(IndexSchema schema, Map<String, String> args) {
+
   }
 
   protected String getArg(String n, Map<String,String> args) {
@@ -191,8 +218,15 @@
    * :TODO: clean up and clarify this explanation.
    *
    * @see #toInternal
+   *
+   *
    */
   public Field createField(SchemaField field, String externalVal, float boost) {
+    if (!field.indexed() && !field.stored()) {
+      if (log.isTraceEnabled())
+        log.trace("Ignoring unindexed/unstored field: " + field);
+      return null;
+    }
     String val;
     try {
       val = toInternal(externalVal);
@@ -200,23 +234,54 @@
       throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, "Error while creating field '" + field + "' from value '" + externalVal + "'", e, false);
     }
     if (val==null) return null;
-    if (!field.indexed() && !field.stored()) {
-      if (log.isTraceEnabled())
-        log.trace("Ignoring unindexed/unstored field: " + field);
-      return null;
-    }
+
+    return createField(field.getName(), val, getFieldStore(field, val),
+            getFieldIndex(field, val), getFieldTermVec(field, val), field.omitNorms(),
+            field.omitTf(), boost);
+  }
 
 
-    Field f = new Field(field.getName(),
+  /**
+   * Create the field from native Lucene parts.  Mostly intended for use by FieldTypes outputing multiple
+   * Fields per SchemaField
+   * @param name The name of the field
+   * @param val The _internal_ value to index
+   * @param storage {@link org.apache.lucene.document.Field.Store}
+   * @param index {@link org.apache.lucene.document.Field.Index}
+   * @param vec {@link org.apache.lucene.document.Field.TermVector}
+   * @param omitNorms true if norms should be omitted
+   * @param omitTFPos true if term freq and position should be omitted.
+   * @param boost The boost value
+   * @return the {@link org.apache.lucene.document.Field}.
+   */
+  protected Field createField(String name, String val, Field.Store storage, Field.Index index,
+                                    Field.TermVector vec, boolean omitNorms, boolean omitTFPos, float boost){
+    Field f = new Field(name,
                         val,
-                        getFieldStore(field, val),
-                        getFieldIndex(field, val),
-                        getFieldTermVec(field, val));
-    f.setOmitNorms(field.omitNorms());
-    f.setOmitTermFreqAndPositions(field.omitTf());
+                        storage,
+                        index,
+                        vec);
+    f.setOmitNorms(omitNorms);
+    f.setOmitTermFreqAndPositions(omitTFPos);
     f.setBoost(boost);
     return f;
   }
+
+  /**
+   * Given a {@link org.apache.solr.schema.SchemaField}, create one or more {@link org.apache.lucene.document.Fieldable} instances
+   * @param field the {@link org.apache.solr.schema.SchemaField}
+   * @param externalVal The value to add to the field
+   * @param boost The boost to apply
+   * @return An array of {@link org.apache.lucene.document.Fieldable}
+   *
+   * @see #createField(SchemaField, String, float)
+   * @see #isPolyField()
+   */
+  public Fieldable[] createFields(SchemaField field, String externalVal, float boost) {
+    Field f = createField( field, externalVal, boost);
+    return f==null ? new Fieldable[]{} : new Fieldable[]{f};
+  }
+
   /* Helpers for field construction */
   protected Field.TermVector getFieldTermVec(SchemaField field,
                                              String internalVal) {
@@ -226,7 +291,7 @@
     else if (field.storeTermPositions())
       ftv = Field.TermVector.WITH_POSITIONS;
     else if (field.storeTermOffsets())
-      ftv = Field.TermVector.WITH_OFFSETS;            
+      ftv = Field.TermVector.WITH_OFFSETS;
     else if (field.storeTermVector())
       ftv = Field.TermVector.YES;
     return ftv;
@@ -237,7 +302,7 @@
   }
   protected Field.Index getFieldIndex(SchemaField field,
                                       String internalVal) {
-    return field.indexed() ? (isTokenized() ? Field.Index.TOKENIZED : 
+    return field.indexed() ? (isTokenized() ? Field.Index.TOKENIZED :
                               Field.Index.UN_TOKENIZED) : Field.Index.NO;
   }
 
@@ -265,7 +330,7 @@
   }
 
   /**
-   * Convert the stored-field format to an external object.  
+   * Convert the stored-field format to an external object.
    * @see #toInternal
    * @since solr 1.3
    */
@@ -290,7 +355,7 @@
     // that the indexed form is the same as the stored field form.
     return f.stringValue();
   }
-  
+
   /** Given the readable value, return the term value that will match it. */
   public String readableToIndexed(String val) {
     return toInternal(val);
@@ -321,7 +386,7 @@
           termAtt.setTermBuffer(s);
           offsetAtt.setOffset(correctOffset(0),correctOffset(n));
           return true;
-        }       
+        }
       };
 
       return new TokenStreamInfo(ts, ts);
@@ -335,7 +400,7 @@
    * @see #getAnalyzer
    */
   protected Analyzer analyzer=new DefaultAnalyzer(256);
-  
+
   /**
    * Analyzer set by schema for text types to use when searching fields
    * of this type, subclasses can set analyzer themselves or override
@@ -394,7 +459,7 @@
    */
   public abstract void write(TextResponseWriter writer, String name, Fieldable f) throws IOException;
 
-  
+
   /**
    * Returns the SortField instance that should be used to sort fields
    * of this type.
@@ -439,7 +504,7 @@
    * @param part2        the upper boundary of the range, nulls are allowed
    * @param minInclusive whether the minimum of the range is inclusive or not
    * @param maxInclusive whether the maximum of the range is inclusive or not
-*    @return a Query instance to perform range search according to given parameters
+   *  @return a Query instance to perform range search according to given parameters
    *
    * @see org.apache.solr.search.SolrQueryParser#getRangeQuery(String, String, String, boolean)
    */
@@ -452,4 +517,15 @@
             minInclusive, maxInclusive);
   }
 
+  /**
+   * Returns a Query instance for doing searches against a field.
+   * @param parser The {@link org.apache.solr.search.QParser} calling the method
+   * @param field The {@link org.apache.solr.schema.SchemaField} of the field to search
+   * @param externalVal The String representation of the value to search
+   * @return The {@link org.apache.lucene.search.Query} instance.  This implementation returns a {@link org.apache.lucene.search.TermQuery} but overriding queries may not
+   * 
+   */
+  public Query getFieldQuery(QParser parser, SchemaField field, String externalVal) {
+    return new TermQuery(new Term(field.getName(), toInternal(externalVal)));
+  }
 }

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/schema/IndexSchema.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/schema/IndexSchema.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/schema/IndexSchema.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/schema/IndexSchema.java Sun Jan  3 18:06:36 2010
@@ -65,6 +65,30 @@
   private float version;
   private final SolrResourceLoader loader;
 
+  private final HashMap<String, SchemaField> fields = new HashMap<String,SchemaField>();
+
+
+  private final HashMap<String, FieldType> fieldTypes = new HashMap<String,FieldType>();
+
+  private final List<SchemaField> fieldsWithDefaultValue = new ArrayList<SchemaField>();
+  private final Collection<SchemaField> requiredFields = new HashSet<SchemaField>();
+  private DynamicField[] dynamicFields;
+
+  private Analyzer analyzer;
+  private Analyzer queryAnalyzer;
+
+  private String defaultSearchFieldName=null;
+  private String queryParserDefaultOperator = "OR";
+
+
+  private final Map<String, List<CopyField>> copyFieldsMap = new HashMap<String, List<CopyField>>();
+  private DynamicCopy[] dynamicCopyFields;
+  /**
+   * keys are all fields copied to, count is num of copyField
+   * directives that target them.
+   */
+  private Map<SchemaField, Integer> copyFieldTargetCounts
+    = new HashMap<SchemaField, Integer>();
   /**
    * Constructs a schema using the specified file name using the normal
    * Config path directory searching rules.
@@ -156,11 +180,6 @@
   @Deprecated
   public String getName() { return name; }
 
-  private final HashMap<String, SchemaField> fields = new HashMap<String,SchemaField>();
-  private final HashMap<String, FieldType> fieldTypes = new HashMap<String,FieldType>();
-  private final List<SchemaField> fieldsWithDefaultValue = new ArrayList<SchemaField>();
-  private final Collection<SchemaField> requiredFields = new HashSet<SchemaField>();
-
   /**
    * Provides direct access to the Map containing all explicit
    * (ie: non-dynamic) fields in the index, keyed on field name.
@@ -218,7 +237,7 @@
    */
   public SimilarityFactory getSimilarityFactory() { return similarityFactory; }
 
-  private Analyzer analyzer;
+
 
   /**
    * Returns the Analyzer used when indexing documents for this index
@@ -230,7 +249,7 @@
    */
   public Analyzer getAnalyzer() { return analyzer; }
 
-  private Analyzer queryAnalyzer;
+
 
   /**
    * Returns the Analyzer used when searching this index
@@ -242,8 +261,7 @@
    */
   public Analyzer getQueryAnalyzer() { return queryAnalyzer; }
 
-  private String defaultSearchFieldName=null;
-  private String queryParserDefaultOperator = "OR";
+
 
   /**
    * A SolrQueryParser linked to this IndexSchema for field datatype
@@ -399,7 +417,7 @@
       Config schemaConf = new Config(loader, "schema", is, "/schema/");
       Document document = schemaConf.getDocument();
       final XPath xpath = schemaConf.getXPath();
-
+      final List<SchemaAware> schemaAware = new ArrayList<SchemaAware>();
       Node nd = (Node) xpath.evaluate("/schema/@name", document, XPathConstants.NODE);
       if (nd==null) {
         log.warn("schema has no name!");
@@ -434,6 +452,9 @@
             ft.setAnalyzer(analyzer);
             ft.setQueryAnalyzer(queryAnalyzer);
           }
+          if (ft instanceof SchemaAware){
+            schemaAware.add((SchemaAware) ft);
+          }
           return ft;
         }
         
@@ -494,7 +515,6 @@
             SolrException.logOnce(log,null,t);
             SolrConfig.severeErrors.add( t );
           }
-          
           log.debug("field defined: " + f);
           if( f.getDefaultValue() != null ) {
             log.debug(name+" contains default value: " + f.getDefaultValue());
@@ -506,23 +526,7 @@
           }
         } else if (node.getNodeName().equals("dynamicField")) {
           // make sure nothing else has the same path
-          boolean dup = false;
-          for( DynamicField df : dFields ) {
-            if( df.regex.equals( f.name ) ) {
-              String msg = "[schema.xml] Duplicate DynamicField definition for '"
-                + f.getName() + "' ignoring: "+f.toString();
-              
-              Throwable t = new SolrException( SolrException.ErrorCode.SERVER_ERROR, msg );
-              SolrException.logOnce(log,null,t);
-              SolrConfig.severeErrors.add( t );
-              dup = true;
-              break;
-            }
-          }
-          if( !dup ) {
-            dFields.add(new DynamicField(f));
-            log.debug("dynamic field defined: " + f);
-          }
+          addDynamicField(dFields, f);
         } else {
           // we should never get here
           throw new RuntimeException("Unknown field type");
@@ -534,6 +538,7 @@
     // in DocumentBuilder.getDoc()
     requiredFields.addAll(getFieldsWithDefaultValue());
 
+
     // OK, now sort the dynamic fields largest to smallest size so we don't get
     // any false matches.  We want to act like a compiler tool and try and match
     // the largest string possible.
@@ -568,6 +573,9 @@
           }
         };
       }
+      if (similarityFactory instanceof SchemaAware){
+        schemaAware.add((SchemaAware) similarityFactory);
+      }
       log.debug("using similarity factory" + similarityFactory.getClass().getName());
     }
 
@@ -652,7 +660,10 @@
                       entry.getValue()+")");
         }
       }
-
+      //Run the callbacks on SchemaAware now that everything else is done
+      for (SchemaAware aware : schemaAware) {
+        aware.inform(this);
+      }
     } catch (SolrException e) {
       SolrConfig.severeErrors.add( e );
       throw e;
@@ -664,6 +675,51 @@
 
     // create the field analyzers
     refreshAnalyzers();
+
+  }
+
+  private void addDynamicField(List<DynamicField> dFields, SchemaField f) {
+    boolean dup = isDuplicateDynField(dFields, f);
+    if( !dup ) {
+      addDynamicFieldNoDupCheck(dFields, f);
+    } else {
+      String msg = "[schema.xml] Duplicate DynamicField definition for '"
+              + f.getName() + "' ignoring: " + f.toString();
+
+      Throwable t = new SolrException(SolrException.ErrorCode.SERVER_ERROR, msg);
+      SolrException.logOnce(log, null, t);
+      SolrConfig.severeErrors.add(t);
+    }
+  }
+
+  /**
+   * Register one or more new Dynamic Field with the Schema.
+   * @param f The {@link org.apache.solr.schema.SchemaField}
+   */
+  public void registerDynamicField(SchemaField ... f) {
+    List<DynamicField> dynFields = new ArrayList<DynamicField>(Arrays.asList(dynamicFields));
+    for (SchemaField field : f) {
+      if (isDuplicateDynField(dynFields, field) == false) {
+        log.debug("dynamic field creation for schema field: " + field.getName());
+        addDynamicFieldNoDupCheck(dynFields, field);
+      } else {
+        log.debug("dynamic field already exists: dynamic field: [" + field.getName() + "]");
+      }
+    }
+    Collections.sort(dynFields);
+    dynamicFields = dynFields.toArray(new DynamicField[dynFields.size()]);
+  }
+
+  private void addDynamicFieldNoDupCheck(List<DynamicField> dFields, SchemaField f) {
+    dFields.add(new DynamicField(f));
+    log.debug("dynamic field defined: " + f);
+  }
+
+  private boolean isDuplicateDynField(List<DynamicField> dFields, SchemaField f) {
+    for( DynamicField df : dFields ) {
+      if( df.regex.equals( f.name ) ) return true;
+    }
+    return false;
   }
 
   public void registerCopyField( String source, String dest )
@@ -987,7 +1043,7 @@
     }
   }
 
-  private DynamicField[] dynamicFields;
+
   public SchemaField[] getDynamicFieldPrototypes() {
     SchemaField[] df = new SchemaField[dynamicFields.length];
     for (int i=0;i<dynamicFields.length;i++) {
@@ -1038,42 +1094,43 @@
     }
 
     return false;
-  }
-  
+  }   
+
   /**
    * Returns the SchemaField that should be used for the specified field name, or
    * null if none exists.
    *
-   * @param fieldName may be an explicitly defined field, or a name that
+   * @param fieldName may be an explicitly defined field or a name that
    * matches a dynamic field.
    * @see #getFieldType
+   * @see #getField(String)
+   * @return The {@link org.apache.solr.schema.SchemaField}
    */
   public SchemaField getFieldOrNull(String fieldName) {
-     SchemaField f = fields.get(fieldName);
+    SchemaField f = fields.get(fieldName);
     if (f != null) return f;
 
     for (DynamicField df : dynamicFields) {
       if (df.matches(fieldName)) return df.makeSchemaField(fieldName);
     }
-    
+
     return f;
   }
 
   /**
    * Returns the SchemaField that should be used for the specified field name
    *
-   * @param fieldName may be an explicitly defined field, or a name that
+   * @param fieldName may be an explicitly defined field or a name that
    * matches a dynamic field.
    * @throws SolrException if no such field exists
    * @see #getFieldType
+   * @see #getFieldOrNull(String)
+   * @return The {@link SchemaField}
    */
   public SchemaField getField(String fieldName) {
-     SchemaField f = fields.get(fieldName);
+    SchemaField f = getFieldOrNull(fieldName);
     if (f != null) return f;
 
-    for (DynamicField df : dynamicFields) {
-      if (df.matches(fieldName)) return df.makeSchemaField(fieldName);
-    }
 
     // Hmmm, default field could also be implemented with a dynamic field of "*".
     // It would have to be special-cased and only used if nothing else matched.
@@ -1105,6 +1162,16 @@
   }
 
   /**
+   * Given the name of a {@link org.apache.solr.schema.FieldType} (not to be confused with {@link #getFieldType(String)} which
+   * takes in the name of a field), return the {@link org.apache.solr.schema.FieldType}.
+   * @param fieldTypeName The name of the {@link org.apache.solr.schema.FieldType}
+   * @return The {@link org.apache.solr.schema.FieldType} or null.
+   */
+  public FieldType getFieldTypeByName(String fieldTypeName){
+    return fieldTypes.get(fieldTypeName);
+  }
+
+  /**
    * Returns the FieldType for the specified field name.
    *
    * <p>
@@ -1150,15 +1217,6 @@
   };
 
 
-  private final Map<String, List<CopyField>> copyFieldsMap = new HashMap<String, List<CopyField>>();
-  private DynamicCopy[] dynamicCopyFields;
-  /**
-   * keys are all fields copied to, count is num of copyField
-   * directives that target them.
-   */
-  private Map<SchemaField, Integer> copyFieldTargetCounts
-    = new HashMap<SchemaField, Integer>();
-
   /**
    * Get all copy fields, both the static and the dynamic ones.
    * @param destField

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/schema/SchemaField.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/schema/SchemaField.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/schema/SchemaField.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/schema/SchemaField.java Sun Jan  3 18:06:36 2010
@@ -90,9 +90,23 @@
   boolean isTokenized() { return (properties & TOKENIZED)!=0; }
   boolean isBinary() { return (properties & BINARY)!=0; }
 
+
   public Field createField(String val, float boost) {
     return type.createField(this,val,boost);
   }
+  
+  public Fieldable[] createFields(String val, float boost) {
+    return type.createFields(this,val,boost);
+  }
+
+  /**
+   * If true, then use {@link #createFields(String, float)}, else use {@link #createField} to save an extra allocation
+   * @return true if this field is a poly field
+   */
+  public boolean isPolyField(){
+    return type.isPolyField();
+  }
+
 
   @Override
   public String toString() {
@@ -119,6 +133,29 @@
 
 
   static SchemaField create(String name, FieldType ft, Map<String,String> props) {
+
+    String defaultValue = null;
+    if( props.containsKey( "default" ) ) {
+    	defaultValue = (String)props.get( "default" );
+    }
+    return new SchemaField(name, ft, calcProps(name, ft, props), defaultValue );
+  }
+
+  /**
+   * Create a SchemaField w/ the props specified.  Does not support a default value.
+   * @param name The name of the SchemaField
+   * @param ft The {@link org.apache.solr.schema.FieldType} of the field
+   * @param props The props.  See {@link #calcProps(String, org.apache.solr.schema.FieldType, java.util.Map)}
+   * @param defValue The default Value for the field
+   * @return The SchemaField
+   *
+   * @see #create(String, FieldType, java.util.Map)
+   */
+  static SchemaField create(String name, FieldType ft, int props, String defValue){
+    return new SchemaField(name, ft, props, defValue);
+  }
+
+  static int calcProps(String name, FieldType ft, Map<String, String> props) {
     int trueProps = parseProperties(props,true);
     int falseProps = parseProperties(props,false);
 
@@ -166,17 +203,22 @@
 
     p &= ~falseProps;
     p |= trueProps;
-
-    String defaultValue = null;
-    if( props.containsKey( "default" ) ) {
-    	defaultValue = (String)props.get( "default" );
-    }
-    return new SchemaField(name, ft, p, defaultValue );
+    return p;
   }
 
   public String getDefaultValue() {
     return defaultValue;
   }
+
+  @Override
+  public int hashCode() {
+    return name.hashCode();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    return(obj instanceof SchemaField) && name.equals(((SchemaField)obj).name);
+  }
 }
 
 

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/schema/TextField.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/schema/TextField.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/schema/TextField.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/schema/TextField.java Sun Jan  3 18:06:36 2010
@@ -18,12 +18,28 @@
 package org.apache.solr.schema;
 
 import org.apache.lucene.search.SortField;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.PhraseQuery;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.MultiPhraseQuery;
 import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
+import org.apache.lucene.analysis.tokenattributes.TermAttribute;
+import org.apache.lucene.analysis.CachingTokenFilter;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.Analyzer;
 import org.apache.solr.request.XMLWriter;
 import org.apache.solr.request.TextResponseWriter;
+import org.apache.solr.search.QParser;
 
 import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
 import java.io.IOException;
+import java.io.StringReader;
 
 /** <code>TextField</code> is the basic type for configurable text analysis.
  * Analyzers for field types using this implementation should be defined in the schema.
@@ -48,4 +64,190 @@
   public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
     writer.writeStr(name, f.stringValue(), true);
   }
+
+  @Override
+  public Query getFieldQuery(QParser parser, SchemaField field, String externalVal) {
+    return parseFieldQuery(parser, getQueryAnalyzer(), field.getName(), externalVal);
+  }
+
+
+  static Query parseFieldQuery(QParser parser, Analyzer analyzer, String field, String queryText) {
+    int phraseSlop = 0;
+    boolean enablePositionIncrements = true;
+
+    // most of the following code is taken from the Lucene QueryParser
+
+    // Use the analyzer to get all the tokens, and then build a TermQuery,
+    // PhraseQuery, or nothing based on the term count
+
+    TokenStream source;
+    try {
+      source = analyzer.reusableTokenStream(field, new StringReader(queryText));
+      source.reset();
+    } catch (IOException e) {
+      source = analyzer.tokenStream(field, new StringReader(queryText));
+    }
+    CachingTokenFilter buffer = new CachingTokenFilter(source);
+    TermAttribute termAtt = null;
+    PositionIncrementAttribute posIncrAtt = null;
+    int numTokens = 0;
+
+    boolean success = false;
+    try {
+      buffer.reset();
+      success = true;
+    } catch (IOException e) {
+      // success==false if we hit an exception
+    }
+    if (success) {
+      if (buffer.hasAttribute(TermAttribute.class)) {
+        termAtt = (TermAttribute) buffer.getAttribute(TermAttribute.class);
+      }
+      if (buffer.hasAttribute(PositionIncrementAttribute.class)) {
+        posIncrAtt = (PositionIncrementAttribute) buffer.getAttribute(PositionIncrementAttribute.class);
+      }
+    }
+
+    int positionCount = 0;
+    boolean severalTokensAtSamePosition = false;
+
+    boolean hasMoreTokens = false;
+    if (termAtt != null) {
+      try {
+        hasMoreTokens = buffer.incrementToken();
+        while (hasMoreTokens) {
+          numTokens++;
+          int positionIncrement = (posIncrAtt != null) ? posIncrAtt.getPositionIncrement() : 1;
+          if (positionIncrement != 0) {
+            positionCount += positionIncrement;
+          } else {
+            severalTokensAtSamePosition = true;
+          }
+          hasMoreTokens = buffer.incrementToken();
+        }
+      } catch (IOException e) {
+        // ignore
+      }
+    }
+    try {
+      // rewind the buffer stream
+      buffer.reset();
+
+      // close original stream - all tokens buffered
+      source.close();
+    }
+    catch (IOException e) {
+      // ignore
+    }
+
+    if (numTokens == 0)
+      return null;
+    else if (numTokens == 1) {
+      String term = null;
+      try {
+        boolean hasNext = buffer.incrementToken();
+        assert hasNext == true;
+        term = termAtt.term();
+      } catch (IOException e) {
+        // safe to ignore, because we know the number of tokens
+      }
+      // return newTermQuery(new Term(field, term));
+      return new TermQuery(new Term(field, term));
+    } else {
+      if (severalTokensAtSamePosition) {
+        if (positionCount == 1) {
+          // no phrase query:
+          // BooleanQuery q = newBooleanQuery(true);
+          BooleanQuery q = new BooleanQuery(true);
+          for (int i = 0; i < numTokens; i++) {
+            String term = null;
+            try {
+              boolean hasNext = buffer.incrementToken();
+              assert hasNext == true;
+              term = termAtt.term();
+            } catch (IOException e) {
+              // safe to ignore, because we know the number of tokens
+            }
+
+            // Query currentQuery = newTermQuery(new Term(field, term));
+            Query currentQuery = new TermQuery(new Term(field, term));
+            q.add(currentQuery, BooleanClause.Occur.SHOULD);
+          }
+          return q;
+        }
+        else {
+          // phrase query:
+          // MultiPhraseQuery mpq = newMultiPhraseQuery();
+          MultiPhraseQuery mpq = new MultiPhraseQuery();
+          mpq.setSlop(phraseSlop);
+          List multiTerms = new ArrayList();
+          int position = -1;
+          for (int i = 0; i < numTokens; i++) {
+            String term = null;
+            int positionIncrement = 1;
+            try {
+              boolean hasNext = buffer.incrementToken();
+              assert hasNext == true;
+              term = termAtt.term();
+              if (posIncrAtt != null) {
+                positionIncrement = posIncrAtt.getPositionIncrement();
+              }
+            } catch (IOException e) {
+              // safe to ignore, because we know the number of tokens
+            }
+
+            if (positionIncrement > 0 && multiTerms.size() > 0) {
+              if (enablePositionIncrements) {
+                mpq.add((Term[])multiTerms.toArray(new Term[0]),position);
+              } else {
+                mpq.add((Term[])multiTerms.toArray(new Term[0]));
+              }
+              multiTerms.clear();
+            }
+            position += positionIncrement;
+            multiTerms.add(new Term(field, term));
+          }
+          if (enablePositionIncrements) {
+            mpq.add((Term[])multiTerms.toArray(new Term[0]),position);
+          } else {
+            mpq.add((Term[])multiTerms.toArray(new Term[0]));
+          }
+          return mpq;
+        }
+      }
+      else {
+        // PhraseQuery pq = newPhraseQuery();
+        PhraseQuery pq = new PhraseQuery();
+        pq.setSlop(phraseSlop);
+        int position = -1;
+
+
+        for (int i = 0; i < numTokens; i++) {
+          String term = null;
+          int positionIncrement = 1;
+
+          try {
+            boolean hasNext = buffer.incrementToken();
+            assert hasNext == true;
+            term = termAtt.term();
+            if (posIncrAtt != null) {
+              positionIncrement = posIncrAtt.getPositionIncrement();
+            }
+          } catch (IOException e) {
+            // safe to ignore, because we know the number of tokens
+          }
+
+          if (enablePositionIncrements) {
+            position += positionIncrement;
+            pq.add(new Term(field, term),position);
+          } else {
+            pq.add(new Term(field, term));
+          }
+        }
+        return pq;
+      }
+    }
+
+  }
+
 }

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/search/FieldQParserPlugin.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/search/FieldQParserPlugin.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/search/FieldQParserPlugin.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/search/FieldQParserPlugin.java Sun Jan  3 18:06:36 2010
@@ -28,6 +28,7 @@
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.schema.FieldType;
 import org.apache.solr.schema.TextField;
+import org.apache.solr.schema.SchemaField;
 
 import java.io.IOException;
 import java.io.StringReader;
@@ -52,99 +53,9 @@
       public Query parse() throws ParseException {
         String field = localParams.get(QueryParsing.F);
         String queryText = localParams.get(QueryParsing.V);
-        FieldType ft = req.getSchema().getFieldType(field);
-        if (!(ft instanceof TextField)) {
-          String internal = ft.toInternal(queryText);
-          return new TermQuery(new Term(field, internal));
-        }
-
-        int phraseSlop = 0;
-        Analyzer analyzer = req.getSchema().getQueryAnalyzer();
-
-        // most of the following code is taken from the Lucene QueryParser
-
-        // Use the analyzer to get all the tokens, and then build a TermQuery,
-        // PhraseQuery, or nothing based on the term count
-
-        TokenStream source = null;
-        try {
-          source = analyzer.reusableTokenStream(field, new StringReader(queryText));
-          source.reset();
-        } catch (IOException e) {
-          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);  
-        }
-        ArrayList<Token> lst = new ArrayList<Token>();
-        Token t;
-        int positionCount = 0;
-        boolean severalTokensAtSamePosition = false;
-
-        while (true) {
-          try {
-            t = source.next();
-          }
-          catch (IOException e) {
-            t = null;
-          }
-          if (t == null)
-            break;
-          lst.add(t);
-          if (t.getPositionIncrement() != 0)
-            positionCount += t.getPositionIncrement();
-          else
-            severalTokensAtSamePosition = true;
-        }
-        try {
-          source.close();
-        }
-        catch (IOException e) {
-          // ignore
-        }
-
-        if (lst.size() == 0)
-          return null;
-        else if (lst.size() == 1) {
-          t = lst.get(0);
-          return new TermQuery(new Term(field, new String(t.termBuffer(), 0, t.termLength())));
-        } else {
-          if (severalTokensAtSamePosition) {
-            if (positionCount == 1) {
-              // no phrase query:
-              BooleanQuery q = new BooleanQuery(true);
-              for (int i = 0; i < lst.size(); i++) {
-                t = (org.apache.lucene.analysis.Token) lst.get(i);
-                TermQuery currentQuery = new TermQuery(
-                        new Term(field, new String(t.termBuffer(), 0, t.termLength())));
-                q.add(currentQuery, BooleanClause.Occur.SHOULD);
-              }
-              return q;
-            }
-            else {
-              // phrase query:
-              MultiPhraseQuery mpq = new MultiPhraseQuery();
-              mpq.setSlop(phraseSlop);
-              ArrayList multiTerms = new ArrayList();
-              for (int i = 0; i < lst.size(); i++) {
-                t = (org.apache.lucene.analysis.Token) lst.get(i);
-                if (t.getPositionIncrement() == 1 && multiTerms.size() > 0) {
-                  mpq.add((Term[])multiTerms.toArray(new Term[0]));
-                  multiTerms.clear();
-                }
-                multiTerms.add(new Term(field, new String(t.termBuffer(), 0, t.termLength())));
-              }
-              mpq.add((Term[])multiTerms.toArray(new Term[0]));
-              return mpq;
-            }
-          }
-          else {
-            PhraseQuery q = new PhraseQuery();
-            q.setSlop(phraseSlop);
-            for (int i = 0; i < lst.size(); i++) {
-              Token token = lst.get(i);
-              q.add(new Term(field, new String(token.termBuffer(), 0, token.termLength())));
-            }
-            return q;
-          }
-        }
+        SchemaField sf = req.getSchema().getField(field);
+        FieldType ft = sf.getType();
+        return ft.getFieldQuery(this, sf, queryText);
       }
     };
   }

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/search/SolrQueryParser.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/search/SolrQueryParser.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/search/SolrQueryParser.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/search/SolrQueryParser.java Sun Jan  3 18:06:36 2010
@@ -34,6 +34,7 @@
 import org.apache.solr.schema.SchemaField;
 import org.apache.solr.schema.TrieField;
 import org.apache.solr.schema.SchemaField;
+import org.apache.solr.schema.TextField;
 
 // TODO: implement the analysis of simple fields with
 // FieldType.toInternal() instead of going through the
@@ -145,6 +146,12 @@
         return parser.subQuery(queryText, null).getQuery();
       }
     }
+    //Intercept poly fields, as they get expanded by default to an OR clause of
+    SchemaField sf = schema.getField(field);
+    //TODO: is there anyway to avoid this instance of check?
+    if (sf != null&& !(sf.getType() instanceof TextField)){//we have a poly field, deal with it specially by delegating to the FieldType
+      return sf.getType().getFieldQuery(parser, sf, queryText); 
+    }
 
     // default to a normal field query
     return super.getFieldQuery(field, queryText);

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/search/ValueSourceParser.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/search/ValueSourceParser.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/search/ValueSourceParser.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/search/ValueSourceParser.java Sun Jan  3 18:06:36 2010
@@ -41,6 +41,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Collections;
 
 /**
  * A factory that parses user queries to generate ValueSource instances.
@@ -202,6 +203,11 @@
         };
       }
     });
+    addParser("vector", new ValueSourceParser(){
+      public ValueSource parse(FunctionQParser fp) throws ParseException{
+        return new VectorValueSource(fp.parseValueSourceList());
+      }
+    });
     addParser("query", new ValueSourceParser() {
       // boost(query($q),rating)
       public ValueSource parse(FunctionQParser fp) throws ParseException {
@@ -224,22 +230,47 @@
     addParser("hsin", new ValueSourceParser() {
       public ValueSource parse(FunctionQParser fp) throws ParseException {
 
-        ValueSource x1 = fp.parseValueSource();
-        ValueSource y1 = fp.parseValueSource();
-        ValueSource x2 = fp.parseValueSource();
-        ValueSource y2 = fp.parseValueSource();
         double radius = fp.parseDouble();
+        MultiValueSource pv1;
+        MultiValueSource pv2;
 
-        return new HaversineFunction(x1, y1, x2, y2, radius);
+        ValueSource one = fp.parseValueSource();
+        ValueSource two = fp.parseValueSource();
+        if (fp.hasMoreArguments()) {
+          List<ValueSource> s1 = new ArrayList<ValueSource>();
+          s1.add(one);
+          s1.add(two);
+          pv1 = new VectorValueSource(s1);
+          ValueSource x2 = fp.parseValueSource();
+          ValueSource y2 = fp.parseValueSource();
+          List<ValueSource> s2 = new ArrayList<ValueSource>();
+          s2.add(x2);
+          s2.add(y2);
+          pv2 = new VectorValueSource(s2);
+        } else {
+          //check to see if we have multiValue source
+          if (one instanceof MultiValueSource && two instanceof MultiValueSource){
+            pv1 = (MultiValueSource) one;
+            pv2 = (MultiValueSource) two;
+          } else {
+            throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+                    "Input must either be 2 MultiValueSources, or there must be 4 ValueSources");
+          }
+        }
+        boolean convert = false;
+        if (fp.hasMoreArguments()){
+          convert = Boolean.parseBoolean(fp.parseArg());
+        }
+        return new HaversineFunction(pv1, pv2, radius, convert);
       }
     });
 
     addParser("ghhsin", new ValueSourceParser() {
       public ValueSource parse(FunctionQParser fp) throws ParseException {
+        double radius = fp.parseDouble();
 
         ValueSource gh1 = fp.parseValueSource();
         ValueSource gh2 = fp.parseValueSource();
-        double radius = fp.parseDouble();
 
         return new GeohashHaversineFunction(gh1, gh2, radius);
       }
@@ -393,15 +424,9 @@
     addParser("sqedist", new ValueSourceParser() {
       public ValueSource parse(FunctionQParser fp) throws ParseException {
         List<ValueSource> sources = fp.parseValueSourceList();
-        if (sources.size() % 2 != 0) {
-          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Illegal number of sources.  There must be an even number of sources");
-        }
-        int dim = sources.size() / 2;
-        List<ValueSource> sources1 = new ArrayList<ValueSource>(dim);
-        List<ValueSource> sources2 = new ArrayList<ValueSource>(dim);
-        //Get dim value sources for the first vector
-        splitSources(dim, sources, sources1, sources2);
-        return new SquaredEuclideanFunction(sources1, sources2);
+        MVResult mvr = getMultiValueSources(sources);
+
+        return new SquaredEuclideanFunction(mvr.mv1, mvr.mv2);
       }
     });
 
@@ -409,14 +434,8 @@
       public ValueSource parse(FunctionQParser fp) throws ParseException {
         float power = fp.parseFloat();
         List<ValueSource> sources = fp.parseValueSourceList();
-        if (sources.size() % 2 != 0) {
-          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Illegal number of sources.  There must be an even number of sources");
-        }
-        int dim = sources.size() / 2;
-        List<ValueSource> sources1 = new ArrayList<ValueSource>(dim);
-        List<ValueSource> sources2 = new ArrayList<ValueSource>(dim);
-        splitSources(dim, sources, sources1, sources2);
-        return new VectorDistanceFunction(power, sources1, sources2);
+        MVResult mvr = getMultiValueSources(sources);
+        return new VectorDistanceFunction(power, mvr.mv1, mvr.mv2);
       }
     });
     addParser("ms", new DateValueSourceParser());
@@ -445,6 +464,44 @@
     }
   }
 
+  private static MVResult getMultiValueSources(List<ValueSource> sources) {
+    MVResult mvr = new MVResult();
+    if (sources.size() % 2 != 0) {
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Illegal number of sources.  There must be an even number of sources");
+    }
+    if (sources.size() == 2) {
+
+      //check to see if these are MultiValueSource
+      boolean s1MV = sources.get(0) instanceof MultiValueSource;
+      boolean s2MV = sources.get(1) instanceof MultiValueSource;
+      if (s1MV && s2MV) {
+        mvr.mv1 = (MultiValueSource) sources.get(0);
+        mvr.mv2 = (MultiValueSource) sources.get(1);
+      } else if (s1MV ||
+              s2MV) {
+        //if one is a MultiValueSource, than the other one needs to be too.
+        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Illegal number of sources.  There must be an even number of sources");
+      } else {
+        mvr.mv1 = new VectorValueSource(Collections.singletonList(sources.get(0)));
+        mvr.mv2 = new VectorValueSource(Collections.singletonList(sources.get(1)));
+      }
+    } else {
+      int dim = sources.size() / 2;
+      List<ValueSource> sources1 = new ArrayList<ValueSource>(dim);
+      List<ValueSource> sources2 = new ArrayList<ValueSource>(dim);
+      //Get dim value sources for the first vector
+      splitSources(dim, sources, sources1, sources2);
+      mvr.mv1 = new VectorValueSource(sources1);
+      mvr.mv2 = new VectorValueSource(sources2);
+    }
+
+    return mvr;
+  }
+
+  private static class MVResult {
+    MultiValueSource mv1;
+    MultiValueSource mv2;
+  }
 }
 
 

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/DocValues.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/DocValues.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/DocValues.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/DocValues.java Sun Jan  3 18:06:36 2010
@@ -48,6 +48,15 @@
   public String strVal(int doc) { throw new UnsupportedOperationException(); }
   public abstract String toString(int doc);
 
+  //For Functions that can work with multiple values from the same document.  This does not apply to all functions
+  public void byteVal(int doc, byte [] vals) { throw new UnsupportedOperationException(); }
+  public void shortVal(int doc, short [] vals) { throw new UnsupportedOperationException(); }
+
+  public void floatVal(int doc, float [] vals) { throw new UnsupportedOperationException(); }
+  public void intVal(int doc, int [] vals) { throw new UnsupportedOperationException(); }
+  public void longVal(int doc, long [] vals) { throw new UnsupportedOperationException(); }
+  public void doubleVal(int doc, double [] vals) { throw new UnsupportedOperationException(); }
+  public void strVal(int doc, String [] vals) { throw new UnsupportedOperationException(); }
 
   public Explanation explain(int doc) {
     return new Explanation(floatVal(doc), toString(doc));

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/DistanceUtils.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/DistanceUtils.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/DistanceUtils.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/DistanceUtils.java Sun Jan  3 18:06:36 2010
@@ -1,4 +1,6 @@
 package org.apache.solr.search.function.distance;
+
+import org.apache.solr.common.SolrException;
 /**
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -18,7 +20,8 @@
 
 
 /**
- * Useful distance utiltities
+ * Useful distance utiltities.
+ * solr-internal: subject to change w/o notification.
  *
  **/
 public class DistanceUtils {
@@ -50,5 +53,76 @@
     return result;
   }
 
+  /**
+   * Given a string containing <i>dimension</i> values encoded in it, separated by commas, return a String array of length <i>dimension</i>
+   * containing the values.
+   * @param out A preallocated array.  Must be size dimension.  If it is not it will be resized.
+   * @param externalVal The value to parse
+   * @param dimension The expected number of values for the point
+   * @return An array of the values that make up the point (aka vector)
+   *
+   * @throws {@link SolrException} if the dimension specified does not match the number of values in the externalValue.
+   */
+  public static String[] parsePoint(String[] out, String externalVal, int dimension) {
+    //TODO: Should we support sparse vectors?
+    if (out==null || out.length != dimension) out=new String[dimension];
+    int idx = externalVal.indexOf(',');
+    int end = idx;
+    int start = 0;
+    int i = 0;
+    if (idx == -1 && dimension == 1 && externalVal.length() > 0){//we have a single point, dimension better be 1
+      out[0] = externalVal.trim();
+      i = 1;
+    }
+    else if (idx > 0) {//if it is zero, that is an error
+      //Parse out a comma separated list of point values, as in: 73.5,89.2,7773.4
+      for (; i < dimension; i++){
+        while (start<end && externalVal.charAt(start)==' ') start++;
+        while (end>start && externalVal.charAt(end-1)==' ') end--;
+        out[i] = externalVal.substring(start, end);
+        start = idx+1;
+        end = externalVal.indexOf(',', start);
+        if (end == -1){
+          end = externalVal.length();
+        }
+      }
+    } 
+    if (i != dimension){
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "incompatible dimension (" + dimension +
+              ") and values (" + externalVal + ").  Only " + i + " values specified");
+    }
+    return out;
+  }
 
+  /**
+   * extract (by calling {@link #parsePoint(String[], String, int)} and validate the latitude and longitude contained
+   * in the String by making sure the latitude is between 90 & -90 and longitude is between -180 and 180
+   * @param latLon A preallocated array to hold the result
+   * @param latLonStr The string to parse
+   * @return The lat long
+   */
+  public static final double[] parseLatitudeLongitude(double [] latLon, String latLonStr) {
+    if (latLon == null){
+      latLon = new double[2];
+    }
+    String[] toks = DistanceUtils.parsePoint(null, latLonStr, 2);
+    latLon[0] = Double.valueOf(toks[0]);
+
+    if (latLon[0] < -90.0 || latLon[0] > 90.0) {
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+              "Invalid latitude: latitudes are range -90 to 90: provided lat: ["
+                      + latLon[0] + "]");
+    }
+
+    latLon[1] = Double.valueOf(toks[1]);
+
+    if (latLon[1] < -180.0 || latLon[1] > 180.0) {
+
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+              "Invalid longitude: longitudes are range -180 to 180: provided lon: ["
+                      + latLon[1] + "]");
+    }
+
+    return latLon;
+  }
 }

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/HaversineFunction.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/HaversineFunction.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/HaversineFunction.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/HaversineFunction.java Sun Jan  3 18:06:36 2010
@@ -18,6 +18,8 @@
 
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.search.Searcher;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.search.function.MultiValueSource;
 import org.apache.solr.search.function.DocValues;
 import org.apache.solr.search.function.ValueSource;
 
@@ -29,28 +31,31 @@
  * Calculate the Haversine formula (distance) between any two points on a sphere
  * Takes in four value sources: (latA, lonA); (latB, lonB).
  * <p/>
- * Assumes the value sources are in radians
+ * Assumes the value sources are in radians unless
  * <p/>
  * See http://en.wikipedia.org/wiki/Great-circle_distance and
  * http://en.wikipedia.org/wiki/Haversine_formula for the actual formula and
  * also http://www.movable-type.co.uk/scripts/latlong.html
- *
- * @see org.apache.solr.search.function.RadianFunction
  */
 public class HaversineFunction extends ValueSource {
 
-  private ValueSource x1;
-  private ValueSource y1;
-  private ValueSource x2;
-  private ValueSource y2;
+  private MultiValueSource p1;
+  private MultiValueSource p2;
+  private boolean convertToRadians = false;
   private double radius;
 
-  public HaversineFunction(ValueSource x1, ValueSource y1, ValueSource x2, ValueSource y2, double radius) {
-    this.x1 = x1;
-    this.y1 = y1;
-    this.x2 = x2;
-    this.y2 = y2;
+  public HaversineFunction(MultiValueSource p1, MultiValueSource p2, double radius) {
+    this(p1, p2, radius, false);
+  }
+
+  public HaversineFunction(MultiValueSource p1, MultiValueSource p2, double radius, boolean convertToRads){
+    this.p1 = p1;
+    this.p2 = p2;
+    if (p1.dimension() != 2 || p2.dimension() != 2) {
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Illegal dimension for value sources");
+    }
     this.radius = radius;
+    this.convertToRadians = convertToRads;
   }
 
   protected String name() {
@@ -59,28 +64,40 @@
 
   /**
    * @param doc  The doc to score
-   * @param x1DV
-   * @param y1DV
-   * @param x2DV
-   * @param y2DV
+   * @param p1DV
+   * @param p2DV
    * @return The haversine distance formula
    */
-  protected double distance(int doc, DocValues x1DV, DocValues y1DV, DocValues x2DV, DocValues y2DV) {
-    double x1 = x1DV.doubleVal(doc); //in radians
-    double y1 = y1DV.doubleVal(doc);
-    double x2 = x2DV.doubleVal(doc);
-    double y2 = y2DV.doubleVal(doc);
+  protected double distance(int doc, DocValues p1DV, DocValues p2DV) {
 
+    double[] p1D = new double[2];
+    double[] p2D = new double[2];
+    p1DV.doubleVal(doc, p1D);
+    p2DV.doubleVal(doc, p2D);
+    double x1;
+    double y1;
+    double x2;
+    double y2;
+    if (convertToRadians) {
+      x1 = p1D[0] * DistanceUtils.DEGREES_TO_RADIANS;
+      y1 = p1D[1] * DistanceUtils.DEGREES_TO_RADIANS;
+      x2 = p2D[0] * DistanceUtils.DEGREES_TO_RADIANS;
+      y2 = p2D[1] * DistanceUtils.DEGREES_TO_RADIANS;
+    } else {
+      x1 = p1D[0];
+      y1 = p1D[1];
+      x2 = p2D[0];
+      y2 = p2D[1];
+    }
     return DistanceUtils.haversine(x1, y1, x2, y2, radius);
   }
 
 
   @Override
   public DocValues getValues(Map context, IndexReader reader) throws IOException {
-    final DocValues x1DV = x1.getValues(context, reader);
-    final DocValues y1DV = y1.getValues(context, reader);
-    final DocValues x2DV = x2.getValues(context, reader);
-    final DocValues y2DV = y2.getValues(context, reader);
+    final DocValues vals1 = p1.getValues(context, reader);
+
+    final DocValues vals2 = p2.getValues(context, reader);
     return new DocValues() {
       public float floatVal(int doc) {
         return (float) doubleVal(doc);
@@ -95,7 +112,7 @@
       }
 
       public double doubleVal(int doc) {
-        return (double) distance(doc, x1DV, y1DV, x2DV, y2DV);
+        return (double) distance(doc, vals1, vals2);
       }
 
       public String strVal(int doc) {
@@ -106,8 +123,7 @@
       public String toString(int doc) {
         StringBuilder sb = new StringBuilder();
         sb.append(name()).append('(');
-        sb.append(x1DV.toString(doc)).append(',').append(y1DV.toString(doc)).append(',')
-                .append(x2DV.toString(doc)).append(',').append(y2DV.toString(doc));
+        sb.append(vals1.toString(doc)).append(',').append(vals2.toString(doc));
         sb.append(')');
         return sb.toString();
       }
@@ -116,10 +132,9 @@
 
   @Override
   public void createWeight(Map context, Searcher searcher) throws IOException {
-    x1.createWeight(context, searcher);
-    x2.createWeight(context, searcher);
-    y1.createWeight(context, searcher);
-    y2.createWeight(context, searcher);
+    p1.createWeight(context, searcher);
+    p2.createWeight(context, searcher);
+
   }
 
   @Override
@@ -127,20 +142,16 @@
     if (this.getClass() != o.getClass()) return false;
     HaversineFunction other = (HaversineFunction) o;
     return this.name().equals(other.name())
-            && x1.equals(other.x1) &&
-            y1.equals(other.y1) &&
-            x2.equals(other.x2) &&
-            y2.equals(other.y2) && radius == other.radius;
+            && p1.equals(other.p1) &&
+            p2.equals(other.p2) && radius == other.radius;
   }
 
   @Override
   public int hashCode() {
     int result;
     long temp;
-    result = x1.hashCode();
-    result = 31 * result + y1.hashCode();
-    result = 31 * result + x2.hashCode();
-    result = 31 * result + y2.hashCode();
+    result = p1.hashCode();
+    result = 31 * result + p2.hashCode();
     result = 31 * result + name().hashCode();
     temp = Double.doubleToRawLongBits(radius);
     result = 31 * result + (int) (temp ^ (temp >>> 32));
@@ -150,7 +161,7 @@
   public String description() {
     StringBuilder sb = new StringBuilder();
     sb.append(name()).append('(');
-    sb.append(x1).append(',').append(y1).append(',').append(x2).append(',').append(y2);
+    sb.append(p1).append(',').append(p2);
     sb.append(')');
     return sb.toString();
   }

Modified: lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/SquaredEuclideanFunction.java
URL: http://svn.apache.org/viewvc/lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/SquaredEuclideanFunction.java?rev=895455&r1=895454&r2=895455&view=diff
==============================================================================
--- lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/SquaredEuclideanFunction.java (original)
+++ lucene/solr/branches/cloud/src/java/org/apache/solr/search/function/distance/SquaredEuclideanFunction.java Sun Jan  3 18:06:36 2010
@@ -17,9 +17,7 @@
  */
 
 import org.apache.solr.search.function.DocValues;
-import org.apache.solr.search.function.ValueSource;
-
-import java.util.List;
+import org.apache.solr.search.function.MultiValueSource;
 
 
 /**
@@ -30,8 +28,8 @@
 public class SquaredEuclideanFunction extends VectorDistanceFunction {
   protected String name = "sqedist";
 
-  public SquaredEuclideanFunction(List<ValueSource> sources1, List<ValueSource> sources2) {
-    super(-1, sources1, sources2);//overriding distance, so power doesn't matter here
+  public SquaredEuclideanFunction(MultiValueSource source1, MultiValueSource source2) {
+    super(-1, source1, source2);//overriding distance, so power doesn't matter here
   }
 
 
@@ -43,11 +41,16 @@
   /**
    * @param doc The doc to score
    */
-  protected double distance(int doc, DocValues[] docValues1, DocValues[] docValues2) {
+  protected double distance(int doc, DocValues dv1, DocValues dv2) {
     double result = 0;
-    for (int i = 0; i < docValues1.length; i++) {
-      result += Math.pow(docValues1[i].doubleVal(doc) - docValues2[i].doubleVal(doc), 2);
-    }
+    double [] vals1 = new double[source1.dimension()];
+    double [] vals2 = new double[source1.dimension()];
+    dv1.doubleVal(doc, vals1);
+    dv2.doubleVal(doc, vals2);
+    for (int i = 0; i < vals1.length; i++) {
+        double v = vals1[i] - vals2[i];
+        result += v * v;
+      }
     return result;
   }
 



Mime
View raw message