mirror of https://github.com/apache/lucene.git
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:
parent
20e22dbd8b
commit
03a7c58b3e
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -69,6 +69,9 @@
|
|||
|
||||
<requestHandler name="/update" class="solr.XmlUpdateRequestHandler"/>
|
||||
|
||||
|
||||
<requestHandler name="/update/javabin" class="solr.BinaryUpdateRequestHandler"/>
|
||||
|
||||
<requestHandler name="/replication" class="solr.ReplicationHandler">
|
||||
|
||||
</requestHandler>
|
||||
|
|
Loading…
Reference in New Issue