SOLR-1116

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@778600 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Noble Paul 2009-05-26 07:44:39 +00:00
parent 20e22dbd8b
commit 03a7c58b3e
11 changed files with 561 additions and 40 deletions

View File

@ -224,6 +224,8 @@ New Features
54. SOLR-1179: DocSets can now be used as Lucene Filters via
DocSet.getTopFilter() (yonik)
55. SOLR-1116: Add a Binary FieldType (noble)
Optimizations
----------------------
1. SOLR-374: Use IndexReader.reopen to save resources by re-using parts of the

View File

@ -0,0 +1,153 @@
/**
* 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.util;
/**
* Static methods for translating Base64 encoded strings to byte arrays
* and vice-versa.
*/
public class Base64 {
/**
* This array is a lookup table that translates 6-bit positive integer
* index values into their "Base64 Alphabet" equivalents as specified
* in Table 1 of RFC 2045.
*/
private static final char intToBase64[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
/**
* This array is a lookup table that translates unicode characters
* drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
* into their 6-bit positive integer equivalents. Characters that
* are not in the Base64 alphabet but fall within the bounds of the
* array are translated to -1.
*/
private static final byte base64ToInt[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
};
public static String byteArrayToBase64(byte[] a, int offset, int len) {
int aLen = len;
int numFullGroups = aLen / 3;
int numBytesInPartialGroup = aLen - 3 * numFullGroups;
int resultLen = 4 * ((aLen + 2) / 3);
StringBuffer result = new StringBuffer(resultLen);
char[] intToAlpha = intToBase64;
// Translate all full groups from byte array elements to Base64
int inCursor = offset;
for (int i = 0; i < numFullGroups; i++) {
int byte0 = a[inCursor++] & 0xff;
int byte1 = a[inCursor++] & 0xff;
int byte2 = a[inCursor++] & 0xff;
result.append(intToAlpha[byte0 >> 2]);
result.append(intToAlpha[(byte0 << 4) & 0x3f | (byte1 >> 4)]);
result.append(intToAlpha[(byte1 << 2) & 0x3f | (byte2 >> 6)]);
result.append(intToAlpha[byte2 & 0x3f]);
}
// Translate partial group if present
if (numBytesInPartialGroup != 0) {
int byte0 = a[inCursor++] & 0xff;
result.append(intToAlpha[byte0 >> 2]);
if (numBytesInPartialGroup == 1) {
result.append(intToAlpha[(byte0 << 4) & 0x3f]);
result.append("==");
} else {
// assert numBytesInPartialGroup == 2;
int byte1 = a[inCursor++] & 0xff;
result.append(intToAlpha[(byte0 << 4) & 0x3f | (byte1 >> 4)]);
result.append(intToAlpha[(byte1 << 2) & 0x3f]);
result.append('=');
}
}
return result.toString();
}
public static byte[] base64ToByteArray(String s) {
byte[] alphaToInt = base64ToInt;
int sLen = s.length();
int numGroups = sLen / 4;
if (4 * numGroups != sLen)
throw new IllegalArgumentException(
"String length must be a multiple of four.");
int missingBytesInLastGroup = 0;
int numFullGroups = numGroups;
if (sLen != 0) {
if (s.charAt(sLen - 1) == '=') {
missingBytesInLastGroup++;
numFullGroups--;
}
if (s.charAt(sLen - 2) == '=')
missingBytesInLastGroup++;
}
byte[] result = new byte[3 * numGroups - missingBytesInLastGroup];
// Translate all full groups from base64 to byte array elements
int inCursor = 0, outCursor = 0;
for (int i = 0; i < numFullGroups; i++) {
int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
int ch3 = base64toInt(s.charAt(inCursor++), alphaToInt);
result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
result[outCursor++] = (byte) ((ch2 << 6) | ch3);
}
// Translate partial group, if present
if (missingBytesInLastGroup != 0) {
int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
if (missingBytesInLastGroup == 1) {
int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
}
}
// assert inCursor == s.length()-missingBytesInLastGroup;
// assert outCursor == result.length;
return result;
}
/**
* Translates the specified character, which is assumed to be in the
* "Base 64 Alphabet" into its equivalent 6-bit positive integer.
*
* @throw IllegalArgumentException or ArrayOutOfBoundsException if
* c is not in the Base64 Alphabet.
*/
private static int base64toInt(char c, byte[] alphaToInt) {
int result = alphaToInt[c];
if (result < 0)
throw new IllegalArgumentException("Illegal character " + c);
return result;
}
}

View File

@ -23,6 +23,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.nio.ByteBuffer;
/**
* The class is designed to optimaly serialize/deserialize a NamedList. As we know there are only a limited type of
@ -97,7 +98,7 @@ public class JavaBinCodec {
if (version != VERSION) {
throw new RuntimeException("Invalid version or the data in not in 'javabin' format");
}
return (Object) readVal(dis);
return readVal(dis);
}
@ -523,6 +524,10 @@ public class JavaBinCodec {
} else if (val instanceof byte[]) {
writeByteArray((byte[]) val, 0, ((byte[]) val).length);
return true;
}else if (val instanceof ByteBuffer) {
ByteBuffer buf = (ByteBuffer) val;
writeByteArray(buf.array(),buf.position(),buf.limit() - buf.position());
return true;
} else if (val == END_OBJ) {
writeTag(END);
return true;
@ -530,6 +535,7 @@ public class JavaBinCodec {
return false;
}
public void writeMap(Map val)
throws IOException {
writeTag(MAP, val.size());

View File

@ -210,6 +210,7 @@ public class BinaryResponseWriter implements BinaryQueryResponseWriter {
KNOWN_TYPES.add(StrField.class);
KNOWN_TYPES.add(TextField.class);
KNOWN_TYPES.add(TrieField.class);
KNOWN_TYPES.add(BinaryField.class);
// We do not add UUIDField because UUID object is not a supported type in JavaBinCodec
// and if we write UUIDField.toObject, we wouldn't know how to handle it in the client side
}

View File

@ -0,0 +1,70 @@
package org.apache.solr.schema;
import org.apache.solr.request.XMLWriter;
import org.apache.solr.request.TextResponseWriter;
import org.apache.solr.common.util.Base64;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.document.Field;
import org.apache.lucene.search.SortField;
import java.io.IOException;
import java.nio.ByteBuffer;
public class BinaryField extends FieldType {
public void write(XMLWriter xmlWriter, String name, Fieldable f) throws IOException {
xmlWriter.writeStr( name, toBase64String(toObject(f)) );
}
private String toBase64String(ByteBuffer buf) {
return Base64.byteArrayToBase64(buf.array(), buf.position(), buf.limit()-buf.position());
}
public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
writer.writeStr(name, toBase64String(toObject(f)), false);
}
public SortField getSortField(SchemaField field, boolean top) {
throw new RuntimeException("Cannot sort on a Binary field");
}
public String toExternal(Fieldable f) {
return toBase64String(toObject(f));
}
public ByteBuffer toObject(Fieldable f) {
return ByteBuffer.wrap(f.getBinaryValue(), f.getBinaryOffset(), f.getBinaryLength() ) ;
}
public Field createField(SchemaField field, Object val, float boost) {
if (val == null) return null;
if (!field.stored()) {
log.trace("Ignoring unstored binary field: " + field);
return null;
}
byte[] buf = null;
int offset = 0, len = 0;
if (val instanceof byte[]) {
buf = (byte[]) val;
len = buf.length;
} else if (val instanceof ByteBuffer && ((ByteBuffer)val).hasArray()) {
ByteBuffer byteBuf = (ByteBuffer) val;
buf = byteBuf.array();
offset = byteBuf.position();
len = byteBuf.limit() - byteBuf.position();
} else {
String strVal = val.toString();
//the string has to be a base64 encoded string
buf = Base64.base64ToByteArray(strVal);
offset = 0;
len = buf.length;
}
Field f = new Field(field.getName(), buf, offset, len,
getFieldStore(field, null));
f.setBoost(boost);
return f;
}
}

View File

@ -29,10 +29,7 @@ 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.CopyField;
import org.apache.solr.schema.DateField;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.*;
/**
* @version $Id$
@ -219,8 +216,7 @@ public class DocumentBuilder {
sfield.getName() + ": " +field.getValue() );
}
final List<CopyField> copyFields = schema.getCopyFieldsList(name);
// load each field value
boolean hasField = false;
for( Object v : field ) {
@ -229,39 +225,55 @@ public class DocumentBuilder {
}
String val = null;
hasField = true;
// 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';
}
else if (v != null) {
val = v.toString();
}
if( sfield != null ) {
boolean isBinaryField = false;
if (sfield != null && sfield.getType() instanceof BinaryField) {
isBinaryField = true;
BinaryField binaryField = (BinaryField) sfield.getType();
Field f = binaryField.createField(sfield,v,boost);
if(f != null) out.add(f);
used = true;
Field f = sfield.createField( val, boost );
if( f != null ) { // null fields are not added
out.add( f );
} else {
// 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';
} else if (v != null) {
val = v.toString();
}
if (sfield != null) {
used = true;
Field f = sfield.createField(val, boost);
if (f != null) { // null fields are not added
out.add(f);
}
}
}
// Check if we should copy this field to any other fields.
// This could happen whether it is explicit or not.
for( CopyField cf : copyFields ) {
SchemaField sf = cf.getDestination();
List<CopyField> copyFields = schema.getCopyFieldsList(name);
for (CopyField cf : copyFields) {
SchemaField destinationField = cf.getDestination();
// 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,
"ERROR: multiple values encountered for non multiValued copy field " +
sf.getName() + ": " +val );
if (!destinationField.multiValued() && out.get(destinationField.getName()) != null) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
"ERROR: multiple values encountered for non multiValued copy field " +
destinationField.getName() + ": " + val);
}
used = true;
Field f = sf.createField( cf.getLimitedValue( val ), boost );
if( f != null ) { // null fields are not added
out.add( f );
Field f = null;
if (isBinaryField) {
if (destinationField.getType() instanceof BinaryField) {
BinaryField binaryField = (BinaryField) destinationField.getType();
binaryField.createField(destinationField, v, boost);
}
} else {
f = destinationField.createField(cf.getLimitedValue(val), boost);
}
if (f != null) { // null fields are not added
out.add(f);
}
}
@ -274,7 +286,8 @@ public class DocumentBuilder {
// make sure the field was used somehow...
if( !used && hasField ) {
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"ERROR:unknown field '" + name + "'");
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"ERROR:unknown field '" +
name + "'");
}
}

View File

@ -25,6 +25,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Array;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.nio.ByteBuffer;
/**
* A class to map objects to and from solr documents.
@ -182,7 +183,9 @@ public class DocumentObjectBinder {
if (types != null && types.length > 0) type = (Class) types[0];
}
}*/
} else if (type.isArray()) {
} else if(type == byte[].class){
//no op
}else if (type.isArray()) {
isArray = true;
type = type.getComponentType();
}
@ -221,6 +224,9 @@ public class DocumentObjectBinder {
}
private void set(Object obj, Object v) {
if(v!= null && type == ByteBuffer.class && v.getClass()== byte[].class) {
v = ByteBuffer.wrap((byte[])v);
}
try {
if (field != null) {
field.set(obj, v);

View File

@ -28,6 +28,7 @@ import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.TimeZone;
import java.nio.ByteBuffer;
import org.apache.commons.httpclient.util.DateParseException;
@ -35,10 +36,7 @@ import org.apache.solr.common.SolrDocument;
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;
import org.apache.solr.common.util.XML;
import org.apache.solr.common.util.DateUtil;
import org.apache.solr.common.util.*;
/**
@ -107,11 +105,17 @@ public class ClientUtils
for( Object v : field ) {
if (v instanceof Date) {
v = DateUtil.getThreadLocalDateFormat().format( (Date)v );
}else if (v instanceof byte[]) {
byte[] bytes = (byte[]) v;
v = Base64.byteArrayToBase64(bytes, 0,bytes.length);
} else if (v instanceof ByteBuffer) {
ByteBuffer bytes = (ByteBuffer) v;
v = Base64.byteArrayToBase64(bytes.array(), bytes.position(),bytes.limit() - bytes.position());
}
if( boost != 1.0f ) {
XML.writeXML(writer, "field", v.toString(), "name", name, "boost", boost );
}
else if (v != null) {
} else if (v != null) {
XML.writeXML(writer, "field", v.toString(), "name", name );
}

View File

@ -0,0 +1,163 @@
package org.apache.solr.schema;
import junit.framework.TestCase;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.beans.Field;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.impl.BinaryRequestWriter;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.apache.commons.io.FileUtils;
import java.nio.ByteBuffer;
import java.io.File;
import java.util.List;
public class TestBinaryField extends TestCase {
CommonsHttpSolrServer server;
JettySolrRunner jetty;
int port = 0;
static final String context = "/example";
@Override
public void setUp() throws Exception {
super.setUp();
String home = System.getProperty("java.io.tmpdir")
+ File.separator
+ getClass().getName() + "-" + System.currentTimeMillis();
File homeDir = new File(home, "example");
File dataDir = new File(homeDir, "data");
File confDir = new File(homeDir, "conf");
homeDir.mkdirs();
dataDir.mkdirs();
confDir.mkdirs();
File f = new File(confDir, "solrconfig.xml");
String fname = "." + File.separator + "solr" + File.separator + "conf" + File.separator + "solrconfig-slave1.xml";
FileUtils.copyFile(new File(fname), f);
f = new File(confDir, "schema.xml");
fname = "." + File.separator + "solr" + File.separator + "conf" + File.separator + "schema-binaryfield.xml";
FileUtils.copyFile(new File(fname), f);
jetty = new JettySolrRunner("/solr", port);
System.setProperty("solr.solr.home", homeDir.getAbsolutePath());
System.setProperty("solr.data.dir", dataDir.getAbsolutePath());
jetty.start();
jetty = new JettySolrRunner(context, 0);
jetty.start();
port = jetty.getLocalPort();
String url = "http://localhost:" + jetty.getLocalPort() + context;
server = new CommonsHttpSolrServer(url);
// server.setRequestWriter(new BinaryRequestWriter());
}
public void testSimple() throws Exception {
byte[] buf = new byte[10];
for (int i = 0; i < 10; i++) {
buf[i] = (byte) i;
}
SolrInputDocument doc = null;
doc = new SolrInputDocument();
doc.addField("id", 1);
doc.addField("data", ByteBuffer.wrap(buf, 2, 5));
server.add(doc);
doc = new SolrInputDocument();
doc.addField("id", 2);
doc.addField("data", ByteBuffer.wrap(buf, 4, 3));
server.add(doc);
doc = new SolrInputDocument();
doc.addField("id", 3);
doc.addField("data", buf);
server.add(doc);
server.commit();
QueryResponse resp = server.query(new SolrQuery("*:*"));
SolrDocumentList res = resp.getResults();
List<Bean> beans = resp.getBeans(Bean.class);
assertEquals(3, res.size());
assertEquals(3, beans.size());
for (SolrDocument d : res) {
Integer id = (Integer) d.getFieldValue("id");
byte[] data = (byte[]) d.getFieldValue("data");
if (id == 1) {
assertEquals(5, data.length);
for (int i = 0; i < data.length; i++) {
byte b = data[i];
assertEquals((byte)(i + 2), b);
}
} else if (id == 2) {
assertEquals(3, data.length);
for (int i = 0; i < data.length; i++) {
byte b = data[i];
assertEquals((byte)(i + 4), b);
}
} else if (id == 3) {
assertEquals(10, data.length);
for (int i = 0; i < data.length; i++) {
byte b = data[i];
assertEquals((byte)i, b);
}
}
}
for (Bean d : beans) {
Integer id = d.id;
byte[] data = d.data;
if (id == 1) {
assertEquals(5, data.length);
for (int i = 0; i < data.length; i++) {
byte b = data[i];
assertEquals((byte)(i + 2), b);
}
} else if (id == 2) {
assertEquals(3, data.length);
for (int i = 0; i < data.length; i++) {
byte b = data[i];
assertEquals((byte)(i + 4), b);
}
} else if (id == 3) {
assertEquals(10, data.length);
for (int i = 0; i < data.length; i++) {
byte b = data[i];
assertEquals((byte)i, b);
}
}
}
}
public static class Bean{
@Field
int id;
@Field
byte [] data;
}
protected void tearDown() throws Exception {
jetty.stop();
}
}

View File

@ -0,0 +1,100 @@
<?xml version="1.0" ?>
<!--
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.
-->
<!-- The Solr schema file. This file should be named "schema.xml" and
should be located where the classloader for the Solr webapp can find it.
This schema is used for testing, and as such has everything and the
kitchen sink thrown in. See example/solr/conf/schema.xml for a
more concise example.
$Id: schema-copyfield-test.xml 721758 2008-11-30 04:46:20Z koji $
$Source: /cvs/main/searching/solr-configs/test/WEB-INF/classes/schema.xml,v $
$Name: $
-->
<schema name="test" version="1.0">
<types>
<!-- field type definitions... note that the "name" attribute is
just a label to be used by field definitions. The "class"
attribute and any other attributes determine the real type and
behavior of the fieldtype.
-->
<!-- numeric field types that store and index the text
value verbatim (and hence don't sort correctly or support range queries.)
These are provided more for backward compatability, allowing one
to create a schema that matches an existing lucene index.
-->
<fieldType name="integer" class="solr.IntField"/>
<fieldType name="long" class="solr.LongField"/>
<fieldtype name="float" class="solr.FloatField"/>
<fieldType name="double" class="solr.DoubleField"/>
<!-- numeric field types that manipulate the value into
a string value that isn't human readable in it's internal form,
but sorts correctly and supports range queries.
If sortMissingLast="true" then a sort on this field will cause documents
without the field to come after documents with the field,
regardless of the requested sort order.
If sortMissingFirst="true" then a sort on this field will cause documents
without the field to come before documents with the field,
regardless of the requested sort order.
If sortMissingLast="false" and sortMissingFirst="false" (the default),
then default lucene sorting will be used which places docs without the field
first in an ascending sort and last in a descending sort.
-->
<fieldtype name="sint" class="solr.SortableIntField" sortMissingLast="true"/>
<fieldtype name="slong" class="solr.SortableLongField" sortMissingLast="true"/>
<fieldtype name="sfloat" class="solr.SortableFloatField" sortMissingLast="true"/>
<fieldtype name="sdouble" class="solr.SortableDoubleField" sortMissingLast="true"/>
<fieldtype name="binary" class="solr.BinaryField"/>
<!-- bcd versions of sortable numeric type may provide smaller
storage space and support very large numbers.
-->
<fieldtype name="bcdint" class="solr.BCDIntField" sortMissingLast="true"/>
<fieldtype name="bcdlong" class="solr.BCDLongField" sortMissingLast="true"/>
<fieldtype name="bcdstr" class="solr.BCDStrField" sortMissingLast="true"/>
<fieldtype name="boolean" class="solr.BoolField" sortMissingLast="true"/>
<fieldtype name="string" class="solr.StrField" sortMissingLast="true"/>
<!-- format for date is 1995-12-31T23:59:59.999Z and only the fractional
seconds part (.999) is optional.
-->
<fieldtype name="date" class="solr.DateField" sortMissingLast="true"/>
</types>
<fields>
<field name="id" type="integer" indexed="true" stored="true" multiValued="false" required="true"/>
<field name="data" type="binary" stored="true"/>
</fields>
<uniqueKey>id</uniqueKey>
</schema>

View File

@ -69,6 +69,9 @@
<requestHandler name="/update" class="solr.XmlUpdateRequestHandler"/>
<requestHandler name="/update/javabin" class="solr.BinaryUpdateRequestHandler"/>
<requestHandler name="/replication" class="solr.ReplicationHandler">
</requestHandler>