SOLR-10237: Poly-Fields should work with subfield that have docValues=true

This commit is contained in:
Tomas Fernandez Lobbe 2017-03-17 11:55:15 -07:00 committed by Shalin Shekhar Mangar
parent 78de123645
commit 359dc1ce45
7 changed files with 68 additions and 36 deletions

View File

@ -303,6 +303,8 @@ Bug Fixes
* SOLR-10283: Learning to Rank (LTR) SolrFeature to reject searches with missing efi (External Feature Information) used by fq.
(Christine Poerschke)
* SOLR-10237: Poly-fields should work with subfields that have docValues=true (Tomás Fernández Löbbe, David Smiley)
Optimizations
----------------------

View File

@ -76,20 +76,25 @@ public abstract class AbstractSubTypeFieldType extends FieldType implements Sche
* and props of indexed=true, stored=false.
*
* @param schema the IndexSchema
* @param type The {@link FieldType} of the prototype.
* @param subType The {@link FieldType} of the prototype.
* @param polyField The poly {@link FieldType}.
* @return The {@link SchemaField}
*/
static SchemaField registerPolyFieldDynamicPrototype(IndexSchema schema, FieldType type) {
String name = "*" + FieldType.POLY_FIELD_SEPARATOR + type.typeName;
static SchemaField registerPolyFieldDynamicPrototype(IndexSchema schema, FieldType subType, FieldType polyField) {
String name = "*" + FieldType.POLY_FIELD_SEPARATOR + subType.typeName;
Map<String, String> props = new HashMap<>();
//Just set these, delegate everything else to the field type
props.put("indexed", "true");
props.put("stored", "false");
props.put("multiValued", "false");
int p = SchemaField.calcProps(name, type, props);
// if polyField enables dv, add them to the subtypes
if (polyField.hasProperty(DOC_VALUES)) {
props.put("docValues", "true");
}
int p = SchemaField.calcProps(name, subType, props);
SchemaField proto = SchemaField.create(name,
type, p, null);
subType, p, null);
schema.registerDynamicFields(proto);
return proto;
}
@ -107,7 +112,7 @@ public abstract class AbstractSubTypeFieldType extends FieldType implements Sche
this.schema = schema;
//Can't do this until here b/c the Dynamic Fields are not initialized until here.
if (subType != null) {
SchemaField proto = registerPolyFieldDynamicPrototype(schema, subType);
SchemaField proto = registerPolyFieldDynamicPrototype(schema, subType, this);
dynFieldProps = proto.getProperties();
}
}

View File

@ -75,10 +75,10 @@ public class LatLonType extends AbstractSubTypeFieldType implements SpatialQuery
Point point = SpatialUtils.parsePointSolrException(externalVal, SpatialContext.GEO);
//latitude
SchemaField subLatSF = subField(field, LAT, schema);
f.add(subLatSF.createField(String.valueOf(point.getY())));
f.addAll(subLatSF.createFields(String.valueOf(point.getY())));
//longitude
SchemaField subLonSF = subField(field, LON, schema);
f.add(subLonSF.createField(String.valueOf(point.getX())));
f.addAll(subLonSF.createFields(String.valueOf(point.getX())));
}
if (field.stored()) {
@ -86,6 +86,14 @@ public class LatLonType extends AbstractSubTypeFieldType implements SpatialQuery
}
return f;
}
@Override
protected void checkSupportsDocValues() {
// DocValues supported only when enabled at the fieldType
if (!hasProperty(DOC_VALUES)) {
throw new UnsupportedOperationException("LatLonType can't have docValues=true in the field definition, use docValues=true in the fieldType definition, or in subFieldType/subFieldSuffix");
}
}
@Override

View File

@ -71,12 +71,12 @@ public class PointType extends CoordinateFieldType implements SpatialQueryable {
String[] point = parseCommaSeparatedList(externalVal, dimension);
// TODO: this doesn't currently support polyFields as sub-field types
List<IndexableField> f = new ArrayList<>(dimension+1);
List<IndexableField> f = new ArrayList<>((dimension*2)+1);
if (field.indexed()) {
for (int i=0; i<dimension; i++) {
SchemaField sf = subField(field, i, schema);
f.add(sf.createField(point[i]));
f.addAll(sf.createFields(point[i]));
}
}
@ -84,7 +84,7 @@ public class PointType extends CoordinateFieldType implements SpatialQueryable {
String storedVal = externalVal; // normalize or not?
f.add(createField(field.getName(), storedVal, StoredField.TYPE));
}
return f;
}
@ -155,6 +155,14 @@ public class PointType extends CoordinateFieldType implements SpatialQueryable {
}
return bq.build();
}
@Override
protected void checkSupportsDocValues() {
// DocValues supported only when enabled at the fieldType
if (!hasProperty(DOC_VALUES)) {
throw new UnsupportedOperationException("PointType can't have docValues=true in the field definition, use docValues=true in the fieldType definition, or in subFieldType/subFieldSuffix");
}
}
/**
* Calculates the range and creates a RangeQuery (bounding box) wrapped in a BooleanQuery (unless the dimension is

View File

@ -392,15 +392,14 @@
<fieldType name="uuid" class="solr.UUIDField"/>
<!-- Try out some point types -->
<fieldType name="xy" class="solr.PointType" dimension="2" subFieldType="double"/>
<fieldType name="x" class="solr.PointType" dimension="1" subFieldType="double"/>
<fieldType name="tenD" class="solr.PointType" dimension="10" subFieldType="double"/>
<!-- Use the sub field suffix -->
<fieldType name="xyd" class="solr.PointType" dimension="2" subFieldSuffix="_d1_ndv"/>
<fieldType name="xy" class="solr.PointType" dimension="2" subFieldType="${solr.tests.doubleClass:pdouble}" docValues="true"/>
<fieldType name="x" class="solr.PointType" dimension="1" subFieldType="${solr.tests.doubleClass:pdouble}"/>
<fieldType name="tenD" class="solr.PointType" dimension="10" subFieldType="${solr.tests.doubleClass:pdouble}"/>
<fieldType name="xyd" class="solr.PointType" dimension="2" subFieldSuffix="_d1"/>
<fieldType name="geohash" class="solr.GeoHashField"/>
<fieldType name="latLon" class="solr.LatLonType" subFieldType="double"/>
<fieldType name="latLon" class="solr.LatLonType" subFieldType="${solr.tests.doubleClass:pdouble}"/>
<!-- Currency type -->
<fieldType name="currency" class="solr.CurrencyField" currencyConfig="currency.xml" multiValued="false"/>
@ -621,7 +620,7 @@
<dynamicField name="*_f1" type="${solr.tests.floatClass:pfloat}" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_d" type="${solr.tests.doubleClass:pdouble}" indexed="true" stored="true"/>
<dynamicField name="*_d1" type="${solr.tests.doubleClass:pdouble}" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_d1_ndv" type="${solr.tests.doubleClass:pdouble}" indexed="true" docValues="false" stored="true" multiValued="false"/>
<dynamicField name="*_d1_dv" type="${solr.tests.doubleClass:pdouble}" indexed="true" docValues="true" stored="true" multiValued="false"/>
<dynamicField name="*_dt" type="${solr.tests.dateClass:pdate}" indexed="true" stored="true"/>
<dynamicField name="*_dt1" type="${solr.tests.dateClass:pdate}" indexed="true" stored="true" multiValued="false"/>
@ -671,7 +670,7 @@
<dynamicField name="*_mfacet" type="string" indexed="true" stored="false" multiValued="true"/>
<!-- Type used to index the lat and lon components for the "location" FieldType -->
<dynamicField name="*_coordinate" type="${solr.tests.doubleClass:pdouble}" indexed="true" stored="false" omitNorms="true"/>
<dynamicField name="*_coordinate" type="${solr.tests.doubleClass:pdouble}" indexed="true" stored="false" omitNorms="true" docValues="false"/>
<dynamicField name="*_path" type="path" indexed="true" stored="true" omitNorms="true" multiValued="true"/>
<dynamicField name="*_ancestor" type="ancestor_path" indexed="true" stored="true" omitNorms="true"

View File

@ -15,6 +15,7 @@
* limitations under the License.
*/
package org.apache.solr.schema;
import java.util.Arrays;
import java.util.List;
import org.apache.lucene.index.IndexableField;
@ -45,11 +46,16 @@ public class PolyFieldTest extends SolrTestCaseJ4 {
SchemaField home = schema.getField("home");
assertNotNull(home);
assertTrue(home.isPolyField());
String subFieldType = "double";
if (usingPointFields()) {
subFieldType = "pdouble";
}
SchemaField[] dynFields = schema.getDynamicFieldPrototypes();
boolean seen = false;
for (SchemaField dynField : dynFields) {
if (dynField.getName().equals("*" + FieldType.POLY_FIELD_SEPARATOR + "double")) {
if (dynField.getName().equals("*" + FieldType.POLY_FIELD_SEPARATOR + subFieldType)) {
seen = true;
}
}
@ -60,7 +66,7 @@ public class PolyFieldTest extends SolrTestCaseJ4 {
assertNotNull(xy);
assertTrue(xy instanceof PointType);
assertTrue(xy.isPolyField());
home = schema.getFieldOrNull("home_0" + FieldType.POLY_FIELD_SEPARATOR + "double");
home = schema.getFieldOrNull("home_0" + FieldType.POLY_FIELD_SEPARATOR + subFieldType);
assertNotNull(home);
home = schema.getField("home");
assertNotNull(home);
@ -84,9 +90,14 @@ public class PolyFieldTest extends SolrTestCaseJ4 {
double[] xy = new double[]{35.0, -79.34};
String point = xy[0] + "," + xy[1];
List<IndexableField> fields = home.createFields(point);
assertEquals(fields.size(), 3);//should be 3, we have a stored field
//first two fields contain the values, third is just stored and contains the original
for (int i = 0; i < 3; i++) {
assertNotNull(pt.getSubType());
int expectdNumFields = 3;//If DV=false, we expect one field per dimension plus a stored field
if (pt.subField(home, 0, schema).hasDocValues()) {
expectdNumFields+=2; // If docValues=true, then we expect two more fields
}
assertEquals("Unexpected fields created: " + Arrays.toString(fields.toArray()), expectdNumFields, fields.size());
//first two/four fields contain the values, last one is just stored and contains the original
for (int i = 0; i < expectdNumFields; i++) {
boolean hasValue = fields.get(i).binaryValue() != null
|| fields.get(i).stringValue() != null
|| fields.get(i).numericValue() != null;
@ -100,7 +111,7 @@ public class PolyFieldTest extends SolrTestCaseJ4 {
home = schema.getField("home_ns");
assertNotNull(home);
fields = home.createFields(point);
assertEquals(fields.size(), 2);//should be 2, since we aren't storing
assertEquals(expectdNumFields - 1, fields.size(), 2);//one less field than with "home", since we aren't storing
home = schema.getField("home_ns");
assertNotNull(home);
@ -111,17 +122,12 @@ public class PolyFieldTest extends SolrTestCaseJ4 {
//
}
SchemaField s1 = schema.getField("test_p");
SchemaField s2 = schema.getField("test_p");
// If we use [Int/Double/Long/Float]PointField, we can't get the valueSource, since docValues is false
if (s1.createFields("1,2").get(0).fieldType().pointDimensionCount() == 0) {
assertFalse(s2.getType().isPointField());
ValueSource v1 = s1.getType().getValueSource(s1, null);
ValueSource v2 = s2.getType().getValueSource(s2, null);
assertEquals(v1, v2);
assertEquals(v1.hashCode(), v2.hashCode());
}
ValueSource v1 = s1.getType().getValueSource(s1, null);
ValueSource v2 = s2.getType().getValueSource(s2, null);
assertEquals(v1, v2);
assertEquals(v1.hashCode(), v2.hashCode());
}
@Test
@ -181,5 +187,9 @@ public class PolyFieldTest extends SolrTestCaseJ4 {
assertEquals(2, bq.clauses().size());
clearIndex();
}
private boolean usingPointFields() {
return h.getCore().getLatestSchema().getField("foo_d1_dv").getType().isPointField();
}
}

View File

@ -131,8 +131,8 @@ public class DocumentBuilderTest extends SolrTestCaseJ4 {
doc.addField( "home", "2.2,3.3" );
Document out = DocumentBuilder.toDocument( doc, core.getLatestSchema() );
assertNotNull( out.get( "home" ) );//contains the stored value and term vector, if there is one
assertNotNull( out.getField( "home_0" + FieldType.POLY_FIELD_SEPARATOR + "double" ) );
assertNotNull( out.getField( "home_1" + FieldType.POLY_FIELD_SEPARATOR + "double" ) );
assertNotNull( out.getField( "home_0" + FieldType.POLY_FIELD_SEPARATOR + System.getProperty("solr.tests.doubleClass", "pdouble") ) );
assertNotNull( out.getField( "home_1" + FieldType.POLY_FIELD_SEPARATOR + System.getProperty("solr.tests.doubleClass", "pdouble") ) );
}
/**