mirror of https://github.com/apache/lucene.git
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:
parent
33c839ab4d
commit
1760d4242d
|
@ -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
|
||||
|
|
|
@ -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>");
|
||||
|
|
|
@ -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>" );
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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+"]";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 + "}";
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue