SOLR-2348: Fix field types to explicitly generate an error if you attempt to get a ValueSource for a multiValued field.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1071459 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Chris M. Hostetter 2011-02-17 00:38:04 +00:00
parent 4dd86bf8ab
commit 0d57f3b786
26 changed files with 101 additions and 58 deletions

View File

@ -53,12 +53,13 @@ Upgrading from Solr 3.1-dev
legacy behavior should set a default value for the 'mm' param in legacy behavior should set a default value for the 'mm' param in
their solrconfig.xml file. their solrconfig.xml file.
* In previous releases, sorting on fields that are "multiValued" * In previous releases, sorting or evaluating function queries on
(either by explicit declaration in schema.xml or by implict behavior fields that were "multiValued" (either by explicit declaration in
because the "version" attribute on the schema was less then 1.2) did schema.xml or by implict behavior because the "version" attribute on
not generally work, but it would sometimes silently act as if it the schema was less then 1.2) did not generally work, but it would
succeeded and order the docs arbitrarily. Solr will now fail on any sometimes silently act as if it succeeded and order the docs
attempt to sort on a multivalued field arbitrarily. Solr will now fail on any attempt to sort, or apply a
function to, multi-valued fields
@ -182,6 +183,9 @@ Bug Fixes
* SOLR-2339: Fix sorting to explicitly generate an error if you * SOLR-2339: Fix sorting to explicitly generate an error if you
attempt to sort on a multiValued field. (hossman) attempt to sort on a multiValued field. (hossman)
* SOLR-2348: Fix field types to explicitly generate an error if you
attempt to get a ValueSource for a multiValued field. (hossman)
Other Changes Other Changes
---------------------- ----------------------

View File

@ -85,6 +85,7 @@ public abstract class AbstractSubTypeFieldType extends FieldType implements Sche
//Just set these, delegate everything else to the field type //Just set these, delegate everything else to the field type
props.put("indexed", "true"); props.put("indexed", "true");
props.put("stored", "false"); props.put("stored", "false");
props.put("multiValued", "false");
int p = SchemaField.calcProps(name, type, props); int p = SchemaField.calcProps(name, type, props);
SchemaField proto = SchemaField.create(name, SchemaField proto = SchemaField.create(name,
type, p, null); type, p, null);

View File

@ -49,6 +49,7 @@ public class BoolField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser qparser) { public ValueSource getValueSource(SchemaField field, QParser qparser) {
field.checkFieldCacheSource(qparser);
return new OrdFieldSource(field.name); return new OrdFieldSource(field.name);
} }

View File

@ -47,6 +47,7 @@ public class ByteField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser qparser) { public ValueSource getValueSource(SchemaField field, QParser qparser) {
field.checkFieldCacheSource(qparser);
return new ByteFieldSource( new ByteValuesCreator( field.name, null, CachedArrayCreator.CACHE_VALUES_AND_BITS ) ); return new ByteFieldSource( new ByteValuesCreator( field.name, null, CachedArrayCreator.CACHE_VALUES_AND_BITS ) );
} }

View File

@ -220,10 +220,6 @@ public class DateField extends FieldType {
return getStringSort(field,reverse); return getStringSort(field,reverse);
} }
public ValueSource getValueSource(SchemaField field) {
return new OrdFieldSource(field.name);
}
@Override @Override
public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException { public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
writer.writeDate(name, toExternal(f)); writer.writeDate(name, toExternal(f));
@ -408,6 +404,7 @@ public class DateField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser parser) { public ValueSource getValueSource(SchemaField field, QParser parser) {
field.checkFieldCacheSource(parser);
return new DateFieldSource(field.getName(), field.getType()); return new DateFieldSource(field.getName(), field.getType());
} }

View File

@ -47,7 +47,7 @@ public class DoubleField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser qparser) { public ValueSource getValueSource(SchemaField field, QParser qparser) {
// fieldCache doesn't support double field.checkFieldCacheSource(qparser);
return new DoubleFieldSource( new DoubleValuesCreator( field.name, null, CachedArrayCreator.CACHE_VALUES_AND_BITS ) ); return new DoubleFieldSource( new DoubleValuesCreator( field.name, null, CachedArrayCreator.CACHE_VALUES_AND_BITS ) );
} }

View File

@ -496,6 +496,7 @@ public abstract class FieldType extends FieldProperties {
* Lucene FieldCache.) * Lucene FieldCache.)
*/ */
public ValueSource getValueSource(SchemaField field, QParser parser) { public ValueSource getValueSource(SchemaField field, QParser parser) {
field.checkFieldCacheSource(parser);
return new StrFieldSource(field.name); return new StrFieldSource(field.name);
} }

View File

@ -45,6 +45,7 @@ public class FloatField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser qparser) { public ValueSource getValueSource(SchemaField field, QParser qparser) {
field.checkFieldCacheSource(qparser);
return new FloatFieldSource( new FloatValuesCreator( field.name, null, CachedArrayCreator.CACHE_VALUES_AND_BITS ) ); return new FloatFieldSource( new FloatValuesCreator( field.name, null, CachedArrayCreator.CACHE_VALUES_AND_BITS ) );
} }

View File

@ -97,6 +97,7 @@ public class GeoHashField extends FieldType implements SpatialQueryable {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser parser) { public ValueSource getValueSource(SchemaField field, QParser parser) {
field.checkFieldCacheSource(parser);
return new StrFieldSource(field.name); return new StrFieldSource(field.name);
} }

View File

@ -45,6 +45,7 @@ public class IntField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser qparser) { public ValueSource getValueSource(SchemaField field, QParser qparser) {
field.checkFieldCacheSource(qparser);
return new IntFieldSource(new IntValuesCreator( field.name, null, CachedArrayCreator.CACHE_VALUES_AND_BITS ) ); return new IntFieldSource(new IntValuesCreator( field.name, null, CachedArrayCreator.CACHE_VALUES_AND_BITS ) );
} }

View File

@ -47,6 +47,7 @@ public class LongField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser qparser) { public ValueSource getValueSource(SchemaField field, QParser qparser) {
field.checkFieldCacheSource(qparser);
return new LongFieldSource( new LongValuesCreator( field.name, null, CachedArrayCreator.CACHE_VALUES_AND_BITS ) ); return new LongFieldSource( new LongValuesCreator( field.name, null, CachedArrayCreator.CACHE_VALUES_AND_BITS ) );
} }

View File

@ -22,6 +22,7 @@ import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.lucene.document.Field; import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable; import org.apache.lucene.document.Fieldable;
import org.apache.lucene.search.SortField; import org.apache.lucene.search.SortField;
import org.apache.solr.search.QParser;
import org.apache.solr.response.TextResponseWriter; import org.apache.solr.response.TextResponseWriter;
@ -133,8 +134,8 @@ public final class SchemaField extends FieldProperties {
/** /**
* Sanity checks that the properties of this field type are plausible * Sanity checks that the properties of this field type are plausible
* for a field that may be used in sorting, throwing an appropraite * for a field that may be used in sorting, throwing an appropriate
* exception (including hte field name) if it is not. FieldType subclasses * exception (including the field name) if it is not. FieldType subclasses
* can choose to call this method in their getSortField implementation * can choose to call this method in their getSortField implementation
* @see FieldType#getSortField * @see FieldType#getSortField
*/ */
@ -152,6 +153,27 @@ public final class SchemaField extends FieldProperties {
} }
/**
* Sanity checks that the properties of this field type are plausible
* for a field that may be used to get a FieldCacheSource, throwing
* an appropriate exception (including the field name) if it is not.
* FieldType subclasses can choose to call this method in their
* getValueSource implementation
* @see FieldType#getValueSource
*/
public void checkFieldCacheSource(QParser parser) throws SolrException {
if (! indexed() ) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
"can not use FieldCache on unindexed field: "
+ getName());
}
if ( multiValued() ) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
"can not use FieldCache on multivalued field: "
+ getName());
}
}
static SchemaField create(String name, FieldType ft, Map<String,String> props) { static SchemaField create(String name, FieldType ft, Map<String,String> props) {

View File

@ -50,7 +50,7 @@ public class ShortField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser qparser) { public ValueSource getValueSource(SchemaField field, QParser qparser) {
field.checkFieldCacheSource(qparser);
return new ShortFieldSource(new ShortValuesCreator( field.name, null, CachedArrayCreator.CACHE_VALUES_AND_BITS ) ); return new ShortFieldSource(new ShortValuesCreator( field.name, null, CachedArrayCreator.CACHE_VALUES_AND_BITS ) );
} }

View File

@ -53,6 +53,7 @@ public class SortableDoubleField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser qparser) { public ValueSource getValueSource(SchemaField field, QParser qparser) {
field.checkFieldCacheSource(qparser);
return new SortableDoubleFieldSource(field.name); return new SortableDoubleFieldSource(field.name);
} }

View File

@ -53,6 +53,7 @@ public class SortableFloatField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser qparser) { public ValueSource getValueSource(SchemaField field, QParser qparser) {
field.checkFieldCacheSource(qparser);
return new SortableFloatFieldSource(field.name); return new SortableFloatFieldSource(field.name);
} }

View File

@ -53,6 +53,7 @@ public class SortableIntField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser qparser) { public ValueSource getValueSource(SchemaField field, QParser qparser) {
field.checkFieldCacheSource(qparser);
return new SortableIntFieldSource(field.name); return new SortableIntFieldSource(field.name);
} }

View File

@ -53,6 +53,7 @@ public class SortableLongField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser qparser) { public ValueSource getValueSource(SchemaField field, QParser qparser) {
field.checkFieldCacheSource(qparser);
return new SortableLongFieldSource(field.name); return new SortableLongFieldSource(field.name);
} }

View File

@ -48,6 +48,7 @@ public class StrField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser parser) { public ValueSource getValueSource(SchemaField field, QParser parser) {
field.checkFieldCacheSource(parser);
return new StrFieldSource(field.getName()); return new StrFieldSource(field.getName());
} }

View File

@ -82,13 +82,9 @@ public class TrieDateField extends DateField {
return new SortField(new LongValuesCreator( field.getName(), FieldCache.NUMERIC_UTILS_LONG_PARSER, CachedArrayCreator.CACHE_VALUES_AND_BITS ), top); return new SortField(new LongValuesCreator( field.getName(), FieldCache.NUMERIC_UTILS_LONG_PARSER, CachedArrayCreator.CACHE_VALUES_AND_BITS ), top);
} }
@Override
public ValueSource getValueSource(SchemaField field) {
return new TrieDateFieldSource( new LongValuesCreator( field.getName(), FieldCache.NUMERIC_UTILS_LONG_PARSER, CachedArrayCreator.CACHE_VALUES_AND_BITS ));
}
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser parser) { public ValueSource getValueSource(SchemaField field, QParser parser) {
field.checkFieldCacheSource(parser);
return new TrieDateFieldSource( new LongValuesCreator( field.getName(), FieldCache.NUMERIC_UTILS_LONG_PARSER, CachedArrayCreator.CACHE_VALUES_AND_BITS )); return new TrieDateFieldSource( new LongValuesCreator( field.getName(), FieldCache.NUMERIC_UTILS_LONG_PARSER, CachedArrayCreator.CACHE_VALUES_AND_BITS ));
} }

View File

@ -179,6 +179,7 @@ public class TrieField extends FieldType {
@Override @Override
public ValueSource getValueSource(SchemaField field, QParser qparser) { public ValueSource getValueSource(SchemaField field, QParser qparser) {
field.checkFieldCacheSource(qparser);
int flags = CachedArrayCreator.CACHE_VALUES_AND_BITS; int flags = CachedArrayCreator.CACHE_VALUES_AND_BITS;
switch (type) { switch (type) {
case INTEGER: case INTEGER:

View File

@ -385,7 +385,7 @@
<fieldType name="x" class="solr.PointType" dimension="1" subFieldType="double"/> <fieldType name="x" class="solr.PointType" dimension="1" subFieldType="double"/>
<fieldType name="tenD" class="solr.PointType" dimension="10" subFieldType="double"/> <fieldType name="tenD" class="solr.PointType" dimension="10" subFieldType="double"/>
<!-- Use the sub field suffix --> <!-- Use the sub field suffix -->
<fieldType name="xyd" class="solr.PointType" dimension="2" subFieldSuffix="*_d"/> <fieldType name="xyd" class="solr.PointType" dimension="2" subFieldSuffix="_d1"/>
<fieldtype name="geohash" class="solr.GeoHashField"/> <fieldtype name="geohash" class="solr.GeoHashField"/>
@ -533,6 +533,7 @@
<dynamicField name="*_tf1" type="tfloat" indexed="true" stored="true" multiValued="false"/> <dynamicField name="*_tf1" type="tfloat" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_td" type="tdouble" indexed="true" stored="true"/> <dynamicField name="*_td" type="tdouble" indexed="true" stored="true"/>
<dynamicField name="*_td1" type="tdouble" indexed="true" stored="true" multiValued="false"/> <dynamicField name="*_td1" type="tdouble" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_tds" type="tdouble" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_tdt" type="tdate" indexed="true" stored="true"/> <dynamicField name="*_tdt" type="tdate" indexed="true" stored="true"/>
<dynamicField name="*_tdt1" type="tdate" indexed="true" stored="true" multiValued="false"/> <dynamicField name="*_tdt1" type="tdate" indexed="true" stored="true" multiValued="false"/>

View File

@ -102,10 +102,10 @@ public class QueryParsingTest extends SolrTestCaseJ4 {
assertEquals(flds[0].getField(), "pow(float(weight),const(2.0))"); assertEquals(flds[0].getField(), "pow(float(weight),const(2.0))");
//test functions (more deep) //test functions (more deep)
sort = QueryParsing.parseSort("sum(product(r_f,sum(d_f,t_f,1)),a_f) asc", req); sort = QueryParsing.parseSort("sum(product(r_f1,sum(d_f1,t_f1,1)),a_f1) asc", req);
flds = sort.getSort(); flds = sort.getSort();
assertEquals(flds[0].getType(), SortField.CUSTOM); assertEquals(flds[0].getType(), SortField.CUSTOM);
assertEquals(flds[0].getField(), "sum(product(float(r_f),sum(float(d_f),float(t_f),const(1.0))),float(a_f))"); assertEquals(flds[0].getField(), "sum(product(float(r_f1),sum(float(d_f1),float(t_f1),const(1.0))),float(a_f1))");
sort = QueryParsing.parseSort("pow(weight, 2) desc", req); sort = QueryParsing.parseSort("pow(weight, 2) desc", req);
flds = sort.getSort(); flds = sort.getSort();
@ -135,11 +135,11 @@ public class QueryParsingTest extends SolrTestCaseJ4 {
assertEquals(flds[0].getField(), "weight"); assertEquals(flds[0].getField(), "weight");
//Test literals in functions //Test literals in functions
sort = QueryParsing.parseSort("strdist(foo_s, \"junk\", jw) desc", req); sort = QueryParsing.parseSort("strdist(foo_s1, \"junk\", jw) desc", req);
flds = sort.getSort(); flds = sort.getSort();
assertEquals(flds[0].getType(), SortField.CUSTOM); assertEquals(flds[0].getType(), SortField.CUSTOM);
//the value sources get wrapped, so the out field is different than the input //the value sources get wrapped, so the out field is different than the input
assertEquals(flds[0].getField(), "strdist(str(foo_s),literal(junk), dist=org.apache.lucene.search.spell.JaroWinklerDistance)"); assertEquals(flds[0].getField(), "strdist(str(foo_s1),literal(junk), dist=org.apache.lucene.search.spell.JaroWinklerDistance)");
sort = QueryParsing.parseSort("", req); sort = QueryParsing.parseSort("", req);
assertNull(sort); assertNull(sort);

View File

@ -59,18 +59,18 @@ public class TestIndexSearcher extends SolrTestCaseJ4 {
public void testReopen() throws Exception { public void testReopen() throws Exception {
assertU(adoc("id","1", "v_t","Hello Dude", "v_s","string1")); assertU(adoc("id","1", "v_t","Hello Dude", "v_s1","string1"));
assertU(adoc("id","2", "v_t","Hello Yonik", "v_s","string2")); assertU(adoc("id","2", "v_t","Hello Yonik", "v_s1","string2"));
assertU(commit()); assertU(commit());
SolrQueryRequest sr1 = req("q","foo"); SolrQueryRequest sr1 = req("q","foo");
ReaderContext rCtx1 = sr1.getSearcher().getTopReaderContext(); ReaderContext rCtx1 = sr1.getSearcher().getTopReaderContext();
String sval1 = getStringVal(sr1, "v_s",0); String sval1 = getStringVal(sr1, "v_s1",0);
assertEquals("string1", sval1); assertEquals("string1", sval1);
assertU(adoc("id","3", "v_s","{!literal}")); assertU(adoc("id","3", "v_s1","{!literal}"));
assertU(adoc("id","4", "v_s","other stuff")); assertU(adoc("id","4", "v_s1","other stuff"));
assertU(commit()); assertU(commit());
SolrQueryRequest sr2 = req("q","foo"); SolrQueryRequest sr2 = req("q","foo");
@ -81,7 +81,7 @@ public class TestIndexSearcher extends SolrTestCaseJ4 {
assertEquals(ReaderUtil.leaves(rCtx1)[0].reader, ReaderUtil.leaves(rCtx2)[0].reader); assertEquals(ReaderUtil.leaves(rCtx1)[0].reader, ReaderUtil.leaves(rCtx2)[0].reader);
assertU(adoc("id","5", "v_f","3.14159")); assertU(adoc("id","5", "v_f","3.14159"));
assertU(adoc("id","6", "v_f","8983", "v_s","string6")); assertU(adoc("id","6", "v_f","8983", "v_s1","string6"));
assertU(commit()); assertU(commit());
SolrQueryRequest sr3 = req("q","foo"); SolrQueryRequest sr3 = req("q","foo");

View File

@ -87,7 +87,6 @@ public class TestQueryTypes extends AbstractSolrTestCase {
,"//*[@name='id'][.='999.0']" ,"//*[@name='id'][.='999.0']"
,"//*[@name='" + f + "'][.='" + v + "']" ,"//*[@name='" + f + "'][.='" + v + "']"
); );
// System.out.println("#########################################" + f + "=" + v);
// field qparser // field qparser
assertQ(req( "q", "{!field f="+f+"}"+v) assertQ(req( "q", "{!field f="+f+"}"+v)
@ -98,6 +97,22 @@ public class TestQueryTypes extends AbstractSolrTestCase {
assertQ(req( "q", f + ":[\"" + v + "\" TO \"" + v + "\"]" ) assertQ(req( "q", f + ":[\"" + v + "\" TO \"" + v + "\"]" )
,"//result[@numFound='1']" ,"//result[@numFound='1']"
); );
}
// frange and function query only work on single valued field types
Object[] fc_vals = new Object[] {
"id",999.0
,"v_s","wow dude"
,"v_ti",-1
,"v_tl",-1234567891234567890L
,"v_tf",-2.0f
,"v_td",-2.0
,"v_tdt","2000-05-10T01:01:01Z"
};
for (int i=0; i<fc_vals.length; i+=2) {
String f = fc_vals[i].toString();
String v = fc_vals[i+1].toString();
// frange qparser // frange qparser
assertQ(req( "q", "{!frange v="+f+" l='"+v+"' u='"+v+"'}" ) assertQ(req( "q", "{!frange v="+f+" l='"+v+"' u='"+v+"'}" )
@ -105,13 +120,11 @@ public class TestQueryTypes extends AbstractSolrTestCase {
); );
// function query... just make sure it doesn't throw an exception // function query... just make sure it doesn't throw an exception
assertQ(req( "q", "+id:999 _val_:\"" + f + "\"") assertQ(req( "q", "+id:999 _val_:\"" + f + "\"")
,"//result[@numFound='1']" ,"//result[@numFound='1']"
); );
} }
// Some basic tests to ensure that parsing local params is working // Some basic tests to ensure that parsing local params is working
assertQ("test prefix query", assertQ("test prefix query",
req("q","{!prefix f=v_t}hel") req("q","{!prefix f=v_t}hel")

View File

@ -35,10 +35,10 @@ public class SortByFunctionTest extends AbstractSolrTestCase {
} }
public void test() throws Exception { public void test() throws Exception {
assertU(adoc("id", "1", "x_td", "0", "y_td", "2", "w_td1", "25", "z_td", "5", "f_t", "ipod")); assertU(adoc("id", "1", "x_td1", "0", "y_td1", "2", "w_td1", "25", "z_td1", "5", "f_t", "ipod"));
assertU(adoc("id", "2", "x_td", "2", "y_td", "2", "w_td1", "15", "z_td", "5", "f_t", "ipod ipod ipod ipod ipod")); assertU(adoc("id", "2", "x_td1", "2", "y_td1", "2", "w_td1", "15", "z_td1", "5", "f_t", "ipod ipod ipod ipod ipod"));
assertU(adoc("id", "3", "x_td", "3", "y_td", "2", "w_td1", "55", "z_td", "5", "f_t", "ipod ipod ipod ipod ipod ipod ipod ipod ipod")); assertU(adoc("id", "3", "x_td1", "3", "y_td1", "2", "w_td1", "55", "z_td1", "5", "f_t", "ipod ipod ipod ipod ipod ipod ipod ipod ipod"));
assertU(adoc("id", "4", "x_td", "4", "y_td", "2", "w_td1", "45", "z_td", "5", "f_t", "ipod ipod ipod ipod ipod ipod ipod")); assertU(adoc("id", "4", "x_td1", "4", "y_td1", "2", "w_td1", "45", "z_td1", "5", "f_t", "ipod ipod ipod ipod ipod ipod ipod"));
assertU(commit()); assertU(commit());
assertQ(req("fl", "*,score", "q", "*:*"), assertQ(req("fl", "*,score", "q", "*:*"),
@ -66,7 +66,7 @@ public class SortByFunctionTest extends AbstractSolrTestCase {
); );
assertQ(req("fl", "*,score", "q", "*:*", "sort", "sum(x_td, y_td) desc"), assertQ(req("fl", "*,score", "q", "*:*", "sort", "sum(x_td1, y_td1) desc"),
"//*[@numFound='4']", "//*[@numFound='4']",
"//float[@name='score']='1.0'", "//float[@name='score']='1.0'",
"//result/doc[1]/int[@name='id'][.='4']", "//result/doc[1]/int[@name='id'][.='4']",
@ -74,7 +74,7 @@ public class SortByFunctionTest extends AbstractSolrTestCase {
"//result/doc[3]/int[@name='id'][.='2']", "//result/doc[3]/int[@name='id'][.='2']",
"//result/doc[4]/int[@name='id'][.='1']" "//result/doc[4]/int[@name='id'][.='1']"
); );
assertQ(req("fl", "*,score", "q", "*:*", "sort", "sum(x_td, y_td) asc"), assertQ(req("fl", "*,score", "q", "*:*", "sort", "sum(x_td1, y_td1) asc"),
"//*[@numFound='4']", "//*[@numFound='4']",
"//float[@name='score']='1.0'", "//float[@name='score']='1.0'",
"//result/doc[1]/int[@name='id'][.='1']", "//result/doc[1]/int[@name='id'][.='1']",
@ -83,7 +83,7 @@ public class SortByFunctionTest extends AbstractSolrTestCase {
"//result/doc[4]/int[@name='id'][.='4']" "//result/doc[4]/int[@name='id'][.='4']"
); );
//the function is equal, w_td1 separates //the function is equal, w_td1 separates
assertQ(req("q", "*:*", "fl", "id", "sort", "sum(z_td, y_td) asc, w_td1 asc"), assertQ(req("q", "*:*", "fl", "id", "sort", "sum(z_td1, y_td1) asc, w_td1 asc"),
"//*[@numFound='4']", "//*[@numFound='4']",
"//result/doc[1]/int[@name='id'][.='2']", "//result/doc[1]/int[@name='id'][.='2']",
"//result/doc[2]/int[@name='id'][.='1']", "//result/doc[2]/int[@name='id'][.='1']",
@ -124,7 +124,3 @@ public class SortByFunctionTest extends AbstractSolrTestCase {
); );
} }
} }
/*
<lst name="responseHeader"><int name="status">0</int><int name="QTime">93</int></lst><result name="response" numFound="4" start="0" maxScore="1.0"><doc><float name="score">1.0</float><int name="id">4</int><int name="intDefault">42</int><arr name="multiDefault"><str>muLti-Default</str></arr><date name="timestamp">2009-12-12T12:59:46.412Z</date><arr name="x_td"><double>4.0</double></arr><arr name="y_td"><double>2.0</double></arr></doc><doc><float name="score">1.0</float><int name="id">3</int><int name="intDefault">42</int><arr name="multiDefault"><str>muLti-Default</str></arr><date name="timestamp">2009-12-12T12:59:46.409Z</date><arr name="x_td"><double>3.0</double></arr><arr name="y_td"><double>2.0</double></arr></doc><doc><float name="score">1.0</float><int name="id">2</int><int name="intDefault">42</int><arr name="multiDefault"><str>muLti-Default</str></arr><date name="timestamp">2009-12-12T12:59:46.406Z</date><arr name="x_td"><double>2.0</double></arr><arr name="y_td"><double>2.0</double></arr></doc><doc><float name="score">1.0</float><int name="id">1</int><int name="intDefault">42</int><arr name="multiDefault"><str>muLti-Default</str></arr><date name="timestamp">2009-12-12T12:59:46.361Z</date><arr name="x_td"><double>0.0</double></arr><arr name="y_td"><double>2.0</double></arr></doc></result>
*/

View File

@ -36,12 +36,12 @@ public class DistanceFunctionTest extends SolrTestCaseJ4 {
@Test @Test
public void testHaversine() throws Exception { public void testHaversine() throws Exception {
clearIndex(); clearIndex();
assertU(adoc("id", "1", "x_td", "0", "y_td", "0", "gh_s", GeoHashUtils.encode(32.7693246, -79.9289094))); assertU(adoc("id", "1", "x_td", "0", "y_td", "0", "gh_s1", GeoHashUtils.encode(32.7693246, -79.9289094)));
assertU(adoc("id", "2", "x_td", "0", "y_td", String.valueOf(Math.PI / 2), "gh_s", GeoHashUtils.encode(32.7693246, -78.9289094))); assertU(adoc("id", "2", "x_td", "0", "y_td", String.valueOf(Math.PI / 2), "gh_s1", GeoHashUtils.encode(32.7693246, -78.9289094)));
assertU(adoc("id", "3", "x_td", String.valueOf(Math.PI / 2), "y_td", String.valueOf(Math.PI / 2), "gh_s", GeoHashUtils.encode(32.7693246, -80.9289094))); assertU(adoc("id", "3", "x_td", String.valueOf(Math.PI / 2), "y_td", String.valueOf(Math.PI / 2), "gh_s1", GeoHashUtils.encode(32.7693246, -80.9289094)));
assertU(adoc("id", "4", "x_td", String.valueOf(Math.PI / 4), "y_td", String.valueOf(Math.PI / 4), "gh_s", GeoHashUtils.encode(32.7693246, -81.9289094))); assertU(adoc("id", "4", "x_td", String.valueOf(Math.PI / 4), "y_td", String.valueOf(Math.PI / 4), "gh_s1", GeoHashUtils.encode(32.7693246, -81.9289094)));
assertU(adoc("id", "5", "x_td", "45.0", "y_td", "45.0", assertU(adoc("id", "5", "x_td", "45.0", "y_td", "45.0",
"gh_s", GeoHashUtils.encode(32.7693246, -81.9289094))); "gh_s1", GeoHashUtils.encode(32.7693246, -81.9289094)));
assertU(adoc("id", "6", "point_hash", "32.5, -79.0", "point", "32.5, -79.0")); assertU(adoc("id", "6", "point_hash", "32.5, -79.0", "point", "32.5, -79.0"));
assertU(adoc("id", "7", "point_hash", "32.6, -78.0", "point", "32.6, -78.0")); assertU(adoc("id", "7", "point_hash", "32.6, -78.0", "point", "32.6, -78.0"));
assertU(commit()); assertU(commit());
@ -56,7 +56,7 @@ public class DistanceFunctionTest extends SolrTestCaseJ4 {
//Geo Hash Haversine //Geo Hash Haversine
//Can verify here: http://www.movable-type.co.uk/scripts/latlong.html, but they use a slightly different radius for the earth, so just be close //Can verify here: http://www.movable-type.co.uk/scripts/latlong.html, but they use a slightly different radius for the earth, so just be close
assertQ(req("fl", "*,score", "q", "{!func}ghhsin(" + DistanceUtils.EARTH_MEAN_RADIUS_KM + ", gh_s, \"" + GeoHashUtils.encode(32, -79) + assertQ(req("fl", "*,score", "q", "{!func}ghhsin(" + DistanceUtils.EARTH_MEAN_RADIUS_KM + ", gh_s1, \"" + GeoHashUtils.encode(32, -79) +
"\",)", "fq", "id:1"), "//float[@name='score']='122.171875'"); "\",)", "fq", "id:1"), "//float[@name='score']='122.171875'");
assertQ(req("fl", "id,point_hash,score", "q", "{!func}recip(ghhsin(" + DistanceUtils.EARTH_MEAN_RADIUS_KM + ", point_hash, \"" + GeoHashUtils.encode(32, -79) + "\"), 1, 1, 0)"), assertQ(req("fl", "id,point_hash,score", "q", "{!func}recip(ghhsin(" + DistanceUtils.EARTH_MEAN_RADIUS_KM + ", point_hash, \"" + GeoHashUtils.encode(32, -79) + "\"), 1, 1, 0)"),
@ -66,7 +66,7 @@ public class DistanceFunctionTest extends SolrTestCaseJ4 {
); );
assertQ(req("fl", "*,score", "q", "{!func}ghhsin(" + DistanceUtils.EARTH_MEAN_RADIUS_KM + ", gh_s, geohash(32, -79))", "fq", "id:1"), "//float[@name='score']='122.171875'"); assertQ(req("fl", "*,score", "q", "{!func}ghhsin(" + DistanceUtils.EARTH_MEAN_RADIUS_KM + ", gh_s1, geohash(32, -79))", "fq", "id:1"), "//float[@name='score']='122.171875'");
} }