SOLR-280 -- changing the SolrDocument/SolrInputDocument implementation so each one as as efficient as it can be. The API changes mostly affect solrj users.

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@552405 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Ryan McKinley 2007-07-02 05:19:22 +00:00
parent 33c839ab4d
commit 1760d4242d
12 changed files with 464 additions and 230 deletions

View File

@ -26,6 +26,10 @@ Changes in runtime behavior
1. SOLR-278: Modify LukeRequest/Response to support SOLR-266 schema display.
(Will Johnson via ryan)
2. SOLR-280: Changed the SolrDocument / SolrInputDocument implementation.
The API to build documents has changed -- you need to pass a boost
(or null) with every field. (ryan)
Bug Fixes
Other Changes

View File

@ -33,6 +33,7 @@ import java.util.TimeZone;
import org.apache.commons.httpclient.util.DateParseException;
import org.apache.commons.httpclient.util.DateUtil;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.SolrInputField;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.ContentStream;
import org.apache.solr.common.util.ContentStreamBase;
@ -81,20 +82,15 @@ public class ClientUtils
public static void writeXML( SolrInputDocument doc, Writer writer ) throws IOException
{
if( doc.getBoost( null ) != null ) {
writer.write("<doc boost=\""+doc.getBoost( null )+"\">");
}
else {
writer.write("<doc>");
}
for( String name : doc.getFieldNames() ) {
Float boost = doc.getBoost( name );
for( Object o : doc.getFieldValues( name ) ) {
writeFieldValue(writer, name, boost, o );
// only write the boost for the first mulit-valued field
writer.write("<doc boost=\""+doc.getDocumentBoost()+"\">");
for( SolrInputField field : doc ) {
float boost = field.getBoost();
for( Object o : field ) {
writeFieldValue(writer, field.getName(), boost, o );
// only write the boost for the first multi-valued field
// otherwise, the used boost is the product of all the boost values
boost = null;
boost = 1.0f;
}
}
writer.write("</doc>");

View File

@ -64,11 +64,11 @@ abstract public class SolrExampleTestBase extends AbstractSolrTestCase
// Now add something...
SolrInputDocument doc = new SolrInputDocument();
String docID = "1112211111";
doc.addField( "id", docID );
doc.addField( "name", "my name!" );
doc.addField( "id", docID, null );
doc.addField( "name", "my name!", null );
Assert.assertEquals( null, doc.getFieldValue("foo"));
Assert.assertTrue(doc.getFieldValue("name") != null );
Assert.assertEquals( null, doc.getField("foo") );
Assert.assertTrue(doc.getField("name").getValue() != null );
UpdateResponse upres = server.add( doc );
System.out.println( "ADD:"+upres.getResponse() );
@ -91,28 +91,28 @@ abstract public class SolrExampleTestBase extends AbstractSolrTestCase
// Now add a few docs for facet testing...
List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
SolrInputDocument doc2 = new SolrInputDocument();
doc2.addField( "id", "2" );
doc2.addField( "inStock", true );
doc2.addField( "price", 2 );
doc2.addField( "timestamp", new java.util.Date() );
doc2.addField( "id", "2", null );
doc2.addField( "inStock", true, null );
doc2.addField( "price", 2, null );
doc2.addField( "timestamp", new java.util.Date(), null );
docs.add(doc2);
SolrInputDocument doc3 = new SolrInputDocument();
doc3.addField( "id", "3" );
doc3.addField( "inStock", false );
doc3.addField( "price", 3 );
doc3.addField( "timestamp", new java.util.Date() );
doc3.addField( "id", "3", null );
doc3.addField( "inStock", false, null );
doc3.addField( "price", 3, null );
doc3.addField( "timestamp", new java.util.Date(), null );
docs.add(doc3);
SolrInputDocument doc4 = new SolrInputDocument();
doc4.addField( "id", "4" );
doc4.addField( "inStock", true );
doc4.addField( "price", 4 );
doc4.addField( "timestamp", new java.util.Date() );
doc4.addField( "id", "4", null );
doc4.addField( "inStock", true, null );
doc4.addField( "price", 4, null );
doc4.addField( "timestamp", new java.util.Date(), null );
docs.add(doc4);
SolrInputDocument doc5 = new SolrInputDocument();
doc5.addField( "id", "5" );
doc5.addField( "inStock", false );
doc5.addField( "price", 5 );
doc5.addField( "timestamp", new java.util.Date() );
doc5.addField( "id", "5", null );
doc5.addField( "inStock", false, null );
doc5.addField( "price", 5, null );
doc5.addField( "timestamp", new java.util.Date(), null );
docs.add(doc5);
upres = server.add( docs );
@ -171,9 +171,9 @@ abstract public class SolrExampleTestBase extends AbstractSolrTestCase
SolrInputDocument[] doc = new SolrInputDocument[3];
for( int i=0; i<3; i++ ) {
doc[i] = new SolrInputDocument();
doc[i].setField( "id", i + " & 222" );
doc[i].setField( "id", i + " & 222", null );
}
String id = (String) doc[0].getFieldValue( "id" );
String id = (String) doc[0].getField( "id" ).getFirstValue();
server.add( doc[0] );
server.commit();
@ -204,7 +204,7 @@ abstract public class SolrExampleTestBase extends AbstractSolrTestCase
xml.append( "<delete>" );
for( SolrInputDocument d : doc ) {
xml.append( "<id>" );
XML.escapeCharData( (String)d.getFieldValue( "id" ), xml );
XML.escapeCharData( (String)d.getField( "id" ).getFirstValue(), xml );
xml.append( "</id>" );
}
xml.append( "</delete>" );

View File

@ -38,20 +38,11 @@ import java.util.Set;
*/
public class SolrDocument
{
private Map<String,Collection<Object>> _fields = null;
private Map<String,Object> _fields = null;
public SolrDocument()
{
_fields = new HashMap<String,Collection<Object>>();
}
/**
* Let sub classes return something other then a List.
* Perhaps a Set or LinkedHashSet
*/
protected Collection<Object> getEmptyCollection( String name )
{
return new ArrayList<Object>( 1 );
_fields = new HashMap<String,Object>();
}
/**
@ -73,7 +64,6 @@ public class SolrDocument
_fields.clear();
}
/**
* Remove all fields with the name
*/
@ -83,45 +73,61 @@ public class SolrDocument
}
/**
* Set a field with the given object. If the object is an Array or Iterable, it will
* Set a field with the given object. If the object is an Array, it will
* set multiple fields with the included contents. This will replace any existing
* field with the given name
*/
@SuppressWarnings("unchecked")
public void setField(String name, Object value)
{
Collection<Object> existing = _fields.get( name );
if( existing != null ) {
existing.clear();
if( value instanceof Object[] ) {
Object[] arr = (Object[])value;
Collection<Object> c = new ArrayList<Object>( arr.length );
for( Object o : arr ) {
c.add( o );
}
value = c;
}
this.addField(name, value);
_fields.put(name, value);
}
/**
* This will add a field to the document. If fields already exist with this name
* it will append the collection
*/
@SuppressWarnings("unchecked")
public void addField(String name, Object value)
{
Collection<Object> existing = _fields.get( name );
if( existing == null ) {
existing = getEmptyCollection(name);
_fields.put( name, existing );
Object existing = _fields.get(name);
if (existing == null) {
this.setField( name, value );
return;
}
// Arrays are iterable? They appear to be, but not in the docs...
Collection<Object> vals = null;
if( existing instanceof Collection ) {
vals = (Collection<Object>)existing;
}
else {
vals = new ArrayList<Object>( 3 );
vals.add( existing );
}
// Add the values to the collection
if( value instanceof Iterable ) {
for( Object o : (Iterable)value ) {
this.addField( name, o );
for( Object o : (Iterable<Object>)value ) {
vals.add( o );
}
}
else if( value instanceof Object[] ) {
for( Object o : (Object[])value ) {
this.addField( name, o );
vals.add( o );
}
}
else {
existing.add( value );
vals.add( value );
}
_fields.put( name, vals );
}
///////////////////////////////////////////////////////////////////
@ -129,57 +135,88 @@ public class SolrDocument
///////////////////////////////////////////////////////////////////
/**
* returns the first value for this field
* returns the first value for a field
*/
public Object getFieldValue(String name) {
Collection v = _fields.get( name );
if( v != null && v.size() > 0 ) {
return v.iterator().next();
public Object getFirstValue(String name) {
Object v = _fields.get( name );
if (v == null || !(v instanceof Collection)) return v;
Collection c = (Collection)v;
if (c.size() > 0 ) {
return c.iterator().next();
}
return null;
}
/**
* Get a collection or all the values for a given field name
* Get the value or collection of values for a given field.
*/
public Collection<Object> getFieldValues(String name) {
public Object getFieldValue(String name) {
return _fields.get( name );
}
// TODO? should this be in the API?
// /**
// * Return a named list version
// */
// public NamedList<Object> toNamedList()
// {
// NamedList<Object> nl = new NamedList<Object>();
// for( Map.Entry<String, Collection<Object>> entry : _fields.entrySet() ) {
// Collection<Object> v = entry.getValue();
// if( v.size() == 0 ) {
// nl.add( entry.getKey(), null );
// }
// else if( v.size() > 1 ) {
// nl.add( entry.getKey(), v );
// }
// else { // Add a single value
// nl.add( entry.getKey(), v.iterator().next() );
// }
// }
// return nl;
// }
/**
* Get a collection of values for a given field name
*/
@SuppressWarnings("unchecked")
public Collection<Object> getFieldValues(String name) {
Object v = _fields.get( name );
if( v instanceof Collection ) {
return (Collection<Object>)v;
}
if( v != null ) {
ArrayList<Object> arr = new ArrayList<Object>(1);
arr.add( v );
return arr;
}
return null;
}
@Override
public String toString()
{
return "SolrDocument["+getFieldNames()+"]";
return "SolrDocument["+_fields.toString()+"]";
}
//-----------------------------------------------------------------------------------------
// JSTL Helpers
//-----------------------------------------------------------------------------------------
/**
* Expose a Map interface to the solr field value collection.
*/
public Map<String,Collection<Object>> getFieldValuesMap()
{
return _fields;
return new Map<String,Collection<Object>>() {
/** Get the field Value */
public Collection<Object> get(Object key) {
return getFieldValues( (String)key );
}
/** Set the field Value */
public Collection<Object> put(String key, Collection<Object> value) {
setField( key, value );
return null;
}
/** Remove the field Value */
public Collection<Object> remove(Object key) {
removeFields( (String)key );
return null;
}
// Easily Supported methods
public boolean containsKey(Object key) { return _fields.containsKey( key ); }
public Set<String> keySet() { return _fields.keySet(); }
public int size() { return _fields.size(); }
public boolean isEmpty() { return _fields.isEmpty(); }
// Unsupported operations. These are not necessary for JSTL
public void clear() { throw new UnsupportedOperationException(); }
public boolean containsValue(Object value) {throw new UnsupportedOperationException();}
public Set<java.util.Map.Entry<String, Collection<Object>>> entrySet() {throw new UnsupportedOperationException();}
public void putAll(Map<? extends String, ? extends Collection<Object>> t) {throw new UnsupportedOperationException();}
public Collection<Collection<Object>> values() {throw new UnsupportedOperationException();}
};
}
/**
@ -189,7 +226,7 @@ public class SolrDocument
return new Map<String,Object>() {
/** Get the field Value */
public Object get(Object key) {
return getFieldValue( (String)key );
return getFirstValue( (String)key );
}
/** Set the field Value */

View File

@ -17,15 +17,14 @@
package org.apache.solr.common;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
/**
* Represent the field and boost information needed to construct and index
* a Lucene Document. Like the SolrDocument, the field values need to
* a Lucene Document. Like the SolrDocument, the field values should
* match those specified in schema.xml
*
* By default, this will keep every field value added to the document. To only
@ -35,90 +34,79 @@ import java.util.Map;
* @version $Id$
* @since solr 1.3
*/
public class SolrInputDocument extends SolrDocument
public class SolrInputDocument implements Iterable<SolrInputField>
{
private Map<String,Float> _boost = null;
private final Map<String,SolrInputField> _fields;
private Map<String,Boolean> _removeDuplicates = null;
/**
* Return a base collection to manage the fields for a given value. If
* the field is defined to be "distinct", the field will be backed as
* a Set rather then a List. Adding the same value multiple times will
* only keep a single instance of that value.
*/
@Override
protected Collection<Object> getEmptyCollection( String name )
{
boolean distint = false;
if( _removeDuplicates != null ) {
Boolean v = _removeDuplicates.get( name );
if( v == null ) {
v = _removeDuplicates.get( null );
}
distint = (v == Boolean.TRUE);
}
return distint ? new LinkedHashSet<Object>() : new ArrayList<Object>(1); // keep the order? -- perhaps HashSet?
}
private float _documentBoost = 1.0f;
public SolrInputDocument()
{
_fields = new HashMap<String,SolrInputField>();
}
/**
* Remove all fields and boosts from the document
*/
@Override
public void clear()
{
super.clear();
if( _boost != null ) {
_boost.clear();
if( _fields != null ) {
_fields.clear();
}
if(_removeDuplicates != null ) {
_removeDuplicates.clear();
}
}
/**
* Set the document boost. null will remove the boost
*/
public void setDocumentBoost( Float v )
///////////////////////////////////////////////////////////////////
// Add / Set fields
///////////////////////////////////////////////////////////////////
private boolean isDistinct( String name )
{
this.setBoost( null, v );
}
/**
* @return the document boost. or null if not set
*/
public Float getDocumentBoost()
{
return this.getBoost( null );
}
/**
* Get the lucene document boost for a field. Passing in <code>null</code> returns the
* document boost, not a field boost.
*/
public void setBoost(String name, Float boost) {
if( _boost == null ) {
_boost = new HashMap<String, Float>();
if( _removeDuplicates != null ) {
Boolean v = _removeDuplicates.get( name );
if( v == null ) {
v = _removeDuplicates.get( null );
}
return (v == Boolean.TRUE);
}
if( boost == null ) {
_boost.remove( name );
return false;
}
public void setField(String name, Object value, Float boost )
{
SolrInputField field = new SolrInputField( name );
_fields.put( name, field );
if( isDistinct( name ) ) {
field.value = new LinkedHashSet<Object>();
this.addField(name, value, boost);
}
else {
_boost.put( name, boost );
field.setValue( value, boost );
}
}
/**
* Set the field boost. All fields with the name will have the same boost.
* Passing in <code>null</code> sets the document boost.
* @param boost
* Remove all fields and boosts from the document
*/
public Float getBoost(String name) {
if( _boost == null ) {
return null;
public void addField(String name, Object value, Float boost )
{
SolrInputField field = _fields.get( name );
if( field == null || field.value == null ) {
setField(name, value, boost);
}
else {
field.addValue( value, boost );
}
return _boost.get( name );
}
public boolean removeField(String name) {
if( name != null ) {
return _fields.remove( name ) != null;
}
return false;
}
/**
* Should the Document be able to contain duplicate values for the same field?
@ -132,7 +120,7 @@ public class SolrInputDocument extends SolrDocument
*/
public void setRemoveDuplicateFieldValues( String name, boolean v )
{
if( this.getFieldValues( name ) != null ) {
if( _fields.get( name ) != null ) {
// If it was not distinct and changed to distinct, we could, but this seems like a better rule
throw new RuntimeException( "You can't change a fields distinctness after it is initialized." );
}
@ -148,4 +136,30 @@ public class SolrInputDocument extends SolrDocument
_removeDuplicates.put( name, v );
}
///////////////////////////////////////////////////////////////////
// Get the field values
///////////////////////////////////////////////////////////////////
public SolrInputField getField( String field )
{
return _fields.get( field );
}
public Iterator<SolrInputField> iterator() {
return _fields.values().iterator();
}
public float getDocumentBoost() {
return _documentBoost;
}
public void setDocumentBoost(float documentBoost) {
_documentBoost = documentBoost;
}
@Override
public String toString()
{
return "SolrInputDocumnt["+_fields+"]";
}
}

View File

@ -0,0 +1,204 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.common;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author ryan
* @version $Id$
* @since solr 1.3
*/
public class SolrInputField implements Iterable<Object>
{
String name;
Object value = null;
float boost = 1.0f;
public SolrInputField( String n )
{
this.name = n;
}
//---------------------------------------------------------------
//---------------------------------------------------------------
/**
* Set the value for a field. Arrays will be converted to a collection.
*/
public void setValue(Object v, Float b) {
boost = (b==null) ? 1.0f : b.floatValue();
if( v instanceof Object[] ) {
Object[] arr = (Object[])v;
Collection<Object> c = new ArrayList<Object>( arr.length );
for( Object o : arr ) {
c.add( o );
}
value = c;
}
else {
value = v;
}
}
/**
* Add values to a field. if the added value is a collection, each value
* will be added individually
*/
@SuppressWarnings("unchecked")
public void addValue(Object v, Float b) {
if( value == null ) {
setValue(v, b);
return;
}
// The lucene API and solr XML field specification make it possible to set boosts
// on multi-value fields even though lucene indexing does not support this.
// To keep behavior consistent with what happens in the lucene index, we accumulate
// the product of all boosts specified for this field.
if( b != null ) {
boost *= b.floatValue();
}
Collection<Object> vals = null;
if( value instanceof Collection ) {
vals = (Collection<Object>)value;
}
else {
vals = new ArrayList<Object>( 3 );
vals.add( value );
value = vals;
}
// Add the new values to a collection
if( v instanceof Iterable ) {
for( Object o : (Iterable<Object>)v ) {
vals.add( o );
}
}
else if( v instanceof Object[] ) {
for( Object o : (Object[])v ) {
vals.add( o );
}
}
else {
vals.add( v );
}
}
//---------------------------------------------------------------
//---------------------------------------------------------------
@SuppressWarnings("unchecked")
public Object getFirstValue() {
if( value instanceof Collection ) {
Collection c = (Collection<Object>)value;
if( c.size() > 0 ) {
return c.iterator().next();
}
return null;
}
return value;
}
/**
* @return the value for this field. If the field has multiple values, this
* will be a collection.
*/
public Object getValue() {
return value;
}
/**
* @return the values for this field. This will return a collection even
* if the field is not multi-valued
*/
@SuppressWarnings("unchecked")
public Collection<Object> getValues() {
if( value instanceof Collection ) {
return (Collection<Object>)value;
}
if( value != null ) {
Collection<Object> vals = new ArrayList<Object>(1);
vals.add( value );
return vals;
}
return null;
}
/**
* @return the number of values for this field
*/
public int getValueCount() {
if( value instanceof Collection ) {
return ((Collection)value).size();
}
return (value == null) ? 0 : 1;
}
//---------------------------------------------------------------
//---------------------------------------------------------------
public float getBoost() {
return boost;
}
public void setBoost(float boost) {
this.boost = boost;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@SuppressWarnings("unchecked")
public Iterator<Object> iterator() {
if( value instanceof Collection ) {
return ((Collection)value).iterator();
}
return new Iterator<Object>() {
boolean nxt = (value!=null);
public boolean hasNext() {
return nxt;
}
public Object next() {
nxt = false;
return value;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override
public String toString()
{
return name + "("+boost+")={" + value + "}";
}
}

View File

@ -21,6 +21,7 @@ import java.io.IOException;
import java.util.logging.Logger;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.SolrInputField;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest;
@ -122,7 +123,10 @@ public class UpdateRequestProcessor
long start = System.currentTimeMillis();
Object id = null;
if (uniqueKeyField != null) {
id = doc.getFieldValue( uniqueKeyField.getName() );
SolrInputField f = doc.getField( uniqueKeyField.getName() );
if( f != null ) {
id = f.getFirstValue();
}
}
cmd.doc = DocumentBuilder.toDocument( doc, schema );
updateHandler.addDoc(cmd);

View File

@ -309,7 +309,7 @@ public class XmlUpdateRequestHandler extends RequestHandlerBase
for (int i = 0; i < parser.getAttributeCount(); i++) {
attrName = parser.getAttributeLocalName(i);
if ("boost".equals(attrName)) {
doc.setBoost( null, Float.parseFloat(parser.getAttributeValue(i)) );
doc.setDocumentBoost( Float.parseFloat(parser.getAttributeValue(i)) );
} else {
log.warning("Unknown attribute doc/@" + attrName);
}
@ -317,7 +317,7 @@ public class XmlUpdateRequestHandler extends RequestHandlerBase
StringBuilder text = new StringBuilder();
String name = null;
Float boost = null;
float boost = 1.0f;
boolean isNull = false;
while (true) {
int event = parser.next();
@ -335,20 +335,8 @@ public class XmlUpdateRequestHandler extends RequestHandlerBase
}
else if ("field".equals(parser.getLocalName())) {
if (!isNull) {
if(boost != null) {
// The lucene API and solr XML field specification make it possible to set boosts
// on multi-value fields even though lucene indexing does not support this.
// To keep behavior consistent with what happens in the lucene index, we accumulate
// the product of all boosts specified for this field.
Float old = doc.getBoost( name );
if( old != null ) {
doc.setBoost( name, boost*old );
}
else {
doc.setBoost( name, boost );
}
}
doc.addField(name, text.toString() );
doc.addField(name, text.toString(), boost );
boost = 1.0f;
}
}
break;
@ -361,7 +349,7 @@ public class XmlUpdateRequestHandler extends RequestHandlerBase
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
"unexpected XML tag doc/" + localName);
}
boost = null;
boost = 1.0f;
String attrVal = "";
for (int i = 0; i < parser.getAttributeCount(); i++) {
attrName = parser.getAttributeLocalName(i);

View File

@ -29,6 +29,7 @@ import org.apache.lucene.document.Fieldable;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.SolrInputField;
import org.apache.solr.schema.DateField;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
@ -169,29 +170,29 @@ public class DocumentBuilder {
public static Document toDocument( SolrInputDocument doc, IndexSchema schema )
{
Document out = new Document();
out.setBoost( doc.getDocumentBoost() );
// Load fields from SolrDocument to Document
for( String name : doc.getFieldNames() ) {
for( SolrInputField field : doc ) {
String name = field.getName();
SchemaField sfield = schema.getFieldOrNull(name);
Float b = doc.getBoost( name );
float boost = (b==null) ? 1.0f : b.floatValue();
boolean used = false;
float boost = field.getBoost();
// Make sure it has the correct number
Collection<Object> vals = doc.getFieldValues( name );
if(vals.size() > 1 && sfield!=null && !sfield.multiValued() ) {
if( sfield!=null && !sfield.multiValued() && field.getValueCount() > 1 ) {
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
"ERROR: multiple values encountered for non multiValued field " +
sfield.getName() + ": " +vals.toString() );
sfield.getName() + ": " +field.getValue() );
}
SchemaField[] destArr = schema.getCopyFields(name);
// load each field value
for( Object v : vals ) {
for( Object v : field ) {
String val = null;
// HACK -- date conversion
// TODO!!! HACK -- date conversion
if( sfield != null && v instanceof Date && sfield.getType() instanceof DateField ) {
DateField df = (DateField)sfield.getType();
val = df.toInternal( (Date)v )+'Z';
@ -210,7 +211,6 @@ public class DocumentBuilder {
// Add the copy fields
for( SchemaField sf : destArr ) {
// check if the copy field is a multivalued or not
if( !sf.multiValued() && out.get( sf.getName() ) != null ) {
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
@ -253,11 +253,6 @@ public class DocumentBuilder {
}
}
}
// set the full document boost
if( doc.getBoost( null ) != null ) {
out.setBoost( doc.getBoost( null ) );
}
return out;
}

View File

@ -18,6 +18,7 @@
package org.apache.solr.common;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@ -45,7 +46,9 @@ public class SolrDocumentTest extends TestCase
doc.addField( "f", 100 ); // again, but something else
// make sure we can pull values out of it
assertEquals( fval, doc.getFieldValue( "f" ) );
assertEquals( fval, doc.getFirstValue( "f" ) );
assertEquals( fval, doc.getFieldValues( "f" ).iterator().next() );
assertEquals( fval, ((Collection<Object>)doc.getFieldValue( "f" )).iterator().next() );
assertEquals( bval, doc.getFieldValue( "b" ) );
assertEquals( sval, doc.getFieldValue( "s" ) );
assertEquals( 2, doc.getFieldValues( "f" ).size() );
@ -74,17 +77,7 @@ public class SolrDocumentTest extends TestCase
assertNull( doc.getFieldValue( "f" ) );
assertNull( doc.getFieldValues( "f" ) );
}
public void testDocumentBoosts()
{
SolrInputDocument doc = new SolrInputDocument();
assertEquals( null, doc.getBoost( "aaa" ) );
doc.setBoost( "aaa", 10.0f );
assertEquals( 10.0f, doc.getBoost( "aaa" ) );
doc.setBoost( "aaa", null );
assertEquals( null, doc.getBoost( "aaa" ) );
}
public void testUnsupportedStuff()
{
SolrDocument doc = new SolrDocument();
@ -134,13 +127,13 @@ public class SolrDocumentTest extends TestCase
SolrInputDocument doc = new SolrInputDocument();
doc.setRemoveDuplicateFieldValues( "f1", true );
doc.setRemoveDuplicateFieldValues( "f2", false );
doc.addField( "f1", c0 );
doc.addField( "f2", c0 );
assertEquals( 3, doc.getFieldValues("f1").size() );
assertEquals( 5, doc.getFieldValues("f2").size() );
doc.addField( "f1", c0, null );
doc.addField( "f2", c0, null );
assertEquals( 3, doc.getField("f1").getValueCount() );
assertEquals( 5, doc.getField("f2").getValueCount() );
assertEquals( "[aaa, bbb, ccc]", doc.getFieldValues( "f1" ).toString() );
assertEquals( "[aaa, bbb, aaa, aaa, ccc]", doc.getFieldValues( "f2" ).toString() );
assertEquals( "[aaa, bbb, ccc]", doc.getField( "f1" ).getValues().toString() );
assertEquals( "[aaa, bbb, aaa, aaa, ccc]", doc.getField( "f2" ).getValues().toString() );
}
public void testDuplicate()
@ -152,11 +145,11 @@ public class SolrDocumentTest extends TestCase
// Set up a simple document
SolrInputDocument doc = new SolrInputDocument();
for( int i=0; i<5; i++ ) {
doc.addField( "f", fval0 );
doc.addField( "f", fval1 );
doc.addField( "f", fval2 );
doc.addField( "f", fval0, null );
doc.addField( "f", fval1, null );
doc.addField( "f", fval2, null );
}
assertEquals( (3*5), doc.getFieldValues("f").size() );
assertEquals( (3*5), doc.getField("f").getValueCount() );
try {
doc.setRemoveDuplicateFieldValues( "f", true );
@ -164,14 +157,14 @@ public class SolrDocumentTest extends TestCase
}
catch( Exception ex ) {}
doc.removeFields( "f" );
doc.removeField( "f" );
doc.setRemoveDuplicateFieldValues( "f", true );
for( int i=0; i<5; i++ ) {
doc.addField( "f", fval0 );
doc.addField( "f", fval1 );
doc.addField( "f", fval2 );
doc.addField( "f", fval0, null );
doc.addField( "f", fval1, null );
doc.addField( "f", fval2, null );
}
assertEquals( (3), doc.getFieldValues("f").size() );
assertEquals( (3), doc.getField("f").getValueCount() );
}
}

View File

@ -46,19 +46,18 @@ public class XmlUpdateRequestHandlerTest extends TestCase
SolrInputDocument doc = handler.readDoc( parser );
// Read boosts
assertEquals( new Float(5.5f), doc.getBoost(null) );
assertEquals( null, doc.getBoost( "name" ) );
assertEquals( new Float(2.2f), doc.getBoost( "id" ) );
assertEquals( null, doc.getBoost( "ab" ) );
assertEquals( 5.5f, doc.getDocumentBoost() );
assertEquals( 1.0f, doc.getField( "name" ).getBoost() );
assertEquals( 2.2f, doc.getField( "id" ).getBoost() );
// Boost is the product of each value
assertEquals( new Float(3*4*5), doc.getBoost( "cat" ) );
assertEquals( (3*4*5.0f), doc.getField( "cat" ).getBoost() );
// Read values
assertEquals( "12345", doc.getFieldValue( "id") );
assertEquals( "kitten", doc.getFieldValue( "name") );
assertEquals( "a&b", doc.getFieldValue( "ab") ); // read something with escaped characters
assertEquals( "12345", doc.getField( "id" ).getValue() );
assertEquals( "kitten", doc.getField( "name").getValue() );
assertEquals( "a&b", doc.getField( "ab").getValue() ); // read something with escaped characters
Collection<Object> out = doc.getFieldValues( "cat" );
Collection<Object> out = doc.getField( "cat" ).getValues();
assertEquals( 3, out.size() );
assertEquals( "[aaa, bbb, bbb]", out.toString() );
}

View File

@ -40,7 +40,7 @@ public class DocumentBuilderTest extends AbstractSolrTestCase {
// undefined field
try {
SolrInputDocument doc = new SolrInputDocument();
doc.setField( "unknown field", 12345 );
doc.setField( "unknown field", 12345, null );
DocumentBuilder.toDocument( doc, core.getSchema() );
fail( "should throw an error" );
}