You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ry...@apache.org on 2011/03/25 17:24:22 UTC
svn commit: r1085450 [1/2] - in /lucene/dev/trunk/solr: ./
src/common/org/apache/solr/common/ src/common/org/apache/solr/common/util/
src/java/org/apache/solr/handler/ src/java/org/apache/solr/handler/component/
src/java/org/apache/solr/response/ src/j...
Author: ryan
Date: Fri Mar 25 16:24:21 2011
New Revision: 1085450
URL: http://svn.apache.org/viewvc?rev=1085450&view=rev
Log:
SOLR-1566: Transforming documents in the ResponseWriters. This will allow for more complex results in responses and open the door for function queries as results.
Added:
lucene/dev/trunk/solr/src/java/org/apache/solr/response/ResultContext.java (with props)
lucene/dev/trunk/solr/src/java/org/apache/solr/response/ReturnFields.java (with props)
lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/
lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocIdAugmenter.java (with props)
lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocTransformer.java (with props)
lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocTransformers.java (with props)
lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocValuesAugmenter.java (with props)
lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/ExplainAugmenter.java (with props)
lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/ScoreAugmenter.java (with props)
lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/TransformContext.java (with props)
lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/TransformerWithContext.java (with props)
lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/ValueAugmenter.java (with props)
Modified:
lucene/dev/trunk/solr/CHANGES.txt
lucene/dev/trunk/solr/src/common/org/apache/solr/common/SolrDocument.java
lucene/dev/trunk/solr/src/common/org/apache/solr/common/util/JavaBinCodec.java
lucene/dev/trunk/solr/src/java/org/apache/solr/handler/MoreLikeThisHandler.java
lucene/dev/trunk/solr/src/java/org/apache/solr/handler/component/QueryComponent.java
lucene/dev/trunk/solr/src/java/org/apache/solr/response/BaseResponseWriter.java
lucene/dev/trunk/solr/src/java/org/apache/solr/response/BinaryResponseWriter.java
lucene/dev/trunk/solr/src/java/org/apache/solr/response/CSVResponseWriter.java
lucene/dev/trunk/solr/src/java/org/apache/solr/response/JSONResponseWriter.java
lucene/dev/trunk/solr/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java
lucene/dev/trunk/solr/src/java/org/apache/solr/response/SolrQueryResponse.java
lucene/dev/trunk/solr/src/java/org/apache/solr/response/TextResponseWriter.java
lucene/dev/trunk/solr/src/java/org/apache/solr/response/XMLWriter.java
lucene/dev/trunk/solr/src/java/org/apache/solr/util/SolrPluginUtils.java
lucene/dev/trunk/solr/src/test/org/apache/solr/BasicFunctionalityTest.java
lucene/dev/trunk/solr/src/test/org/apache/solr/client/solrj/SolrExampleTests.java
lucene/dev/trunk/solr/src/test/org/apache/solr/response/TestCSVResponseWriter.java
lucene/dev/trunk/solr/src/test/org/apache/solr/search/TestRangeQuery.java
lucene/dev/trunk/solr/src/webapp/src/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java
Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1085450&r1=1085449&r2=1085450&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Fri Mar 25 16:24:21 2011
@@ -108,6 +108,11 @@ New Features
Adding a parameter NOW=<time_in_ms> to the request will override the
current time. (Peter Sturge, yonik)
+* SOLR-1566: Transforming documents in the ResponseWriters. This will allow
+ for more complex results in responses and open the door for function queries
+ as results. (ryan)
+
+
Optimizations
----------------------
Modified: lucene/dev/trunk/solr/src/common/org/apache/solr/common/SolrDocument.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/common/org/apache/solr/common/SolrDocument.java?rev=1085450&r1=1085449&r2=1085450&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/common/org/apache/solr/common/SolrDocument.java (original)
+++ lucene/dev/trunk/solr/src/common/org/apache/solr/common/SolrDocument.java Fri Mar 25 16:24:21 2011
@@ -26,6 +26,8 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
+import org.apache.solr.common.util.NamedList;
+
/**
* A concrete representation of a document within a Solr index. Unlike a lucene
@@ -88,6 +90,9 @@ public class SolrDocument implements Map
else if( value instanceof Collection ) {
// nothing
}
+ else if( value instanceof NamedList ) {
+ // nothing
+ }
else if( value instanceof Iterable ) {
ArrayList<Object> lst = new ArrayList<Object>();
for( Object o : (Iterable)value ) {
Modified: lucene/dev/trunk/solr/src/common/org/apache/solr/common/util/JavaBinCodec.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/common/org/apache/solr/common/util/JavaBinCodec.java?rev=1085450&r1=1085449&r2=1085450&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/common/org/apache/solr/common/util/JavaBinCodec.java (original)
+++ lucene/dev/trunk/solr/src/common/org/apache/solr/common/util/JavaBinCodec.java Fri Mar 25 16:24:21 2011
@@ -295,27 +295,13 @@ public class JavaBinCodec {
}
public void writeSolrDocument(SolrDocument doc) throws IOException {
- writeSolrDocument(doc, null);
- }
-
- public void writeSolrDocument(SolrDocument doc, Set<String> fields) throws IOException {
- int count = 0;
- if (fields == null) {
- count = doc.getFieldNames().size();
- } else {
- for (Map.Entry<String, Object> entry : doc) {
- if (fields.contains(entry.getKey())) count++;
- }
- }
writeTag(SOLRDOC);
- writeTag(ORDERED_MAP, count);
+ writeTag(ORDERED_MAP, doc.size());
for (Map.Entry<String, Object> entry : doc) {
- if (fields == null || fields.contains(entry.getKey())) {
- String name = entry.getKey();
- writeExternString(name);
- Object val = entry.getValue();
- writeVal(val);
- }
+ String name = entry.getKey();
+ writeExternString(name);
+ Object val = entry.getValue();
+ writeVal(val);
}
}
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/handler/MoreLikeThisHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/handler/MoreLikeThisHandler.java?rev=1085450&r1=1085449&r2=1085450&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/handler/MoreLikeThisHandler.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/handler/MoreLikeThisHandler.java Fri Mar 25 16:24:21 2011
@@ -47,6 +47,7 @@ import org.apache.solr.common.util.Simpl
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SimpleFacets;
import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.ReturnFields;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
@@ -77,10 +78,11 @@ public class MoreLikeThisHandler extends
SolrParams params = req.getParams();
// Set field flags
- String fl = params.get(CommonParams.FL);
+ ReturnFields returnFields = ReturnFields.getReturnFields( req );
+ rsp.setReturnFields( returnFields );
int flags = 0;
- if (fl != null) {
- flags |= SolrPluginUtils.setReturnFields(fl, rsp);
+ if (returnFields.getWantsScore()) {
+ flags |= SolrIndexSearcher.GET_SCORES;
}
String defType = params.get(QueryParsing.DEFTYPE, QParserPlugin.DEFAULT_QTYPE);
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/handler/component/QueryComponent.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/handler/component/QueryComponent.java?rev=1085450&r1=1085449&r2=1085450&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/handler/component/QueryComponent.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/handler/component/QueryComponent.java Fri Mar 25 16:24:21 2011
@@ -39,6 +39,8 @@ import org.apache.solr.common.util.Named
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.core.CoreDescriptor;
import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.ResultContext;
+import org.apache.solr.response.ReturnFields;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.SchemaField;
@@ -72,13 +74,14 @@ public class QueryComponent extends Sear
}
SolrQueryResponse rsp = rb.rsp;
- // Set field flags
- String fl = params.get(CommonParams.FL);
- int fieldFlags = 0;
- if (fl != null) {
- fieldFlags |= SolrPluginUtils.setReturnFields(fl, rsp);
+ // Set field flags
+ ReturnFields returnFields = ReturnFields.getReturnFields( req );
+ rsp.setReturnFields( returnFields );
+ int flags = 0;
+ if (returnFields.getWantsScore()) {
+ flags |= SolrIndexSearcher.GET_SCORES;
}
- rb.setFieldFlags( fieldFlags );
+ rb.setFieldFlags( flags );
String defType = params.get(QueryParsing.DEFTYPE,QParserPlugin.DEFAULT_QTYPE);
@@ -294,7 +297,11 @@ public class QueryComponent extends Sear
res.docSet = searcher.getDocSet(queries);
}
rb.setResults(res);
- rsp.add("response",rb.getResults().docList);
+
+ ResultContext ctx = new ResultContext();
+ ctx.docs = rb.getResults().docList;
+ ctx.query = null; // anything?
+ rsp.add("response", ctx);
return;
}
@@ -416,7 +423,10 @@ public class QueryComponent extends Sear
// TODO: get "hits" a different way to log
if (grouping.mainResult != null) {
- rsp.add("response",grouping.mainResult);
+ ResultContext ctx = new ResultContext();
+ ctx.docs = grouping.mainResult;
+ ctx.query = null; // TODO? add the query?
+ rsp.add("response", ctx);
rsp.getToLog().add("hits", grouping.mainResult.matches());
}
@@ -431,7 +441,11 @@ public class QueryComponent extends Sear
searcher.search(result,cmd);
rb.setResult( result );
- rsp.add("response",rb.getResults().docList);
+
+ ResultContext ctx = new ResultContext();
+ ctx.docs = rb.getResults().docList;
+ ctx.query = rb.getQuery();
+ rsp.add("response", ctx);
rsp.getToLog().add("hits", rb.getResults().docList.matches());
doFieldSortValues(rb, searcher);
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/response/BaseResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/BaseResponseWriter.java?rev=1085450&r1=1085449&r2=1085450&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/BaseResponseWriter.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/BaseResponseWriter.java Fri Mar 25 16:24:21 2011
@@ -38,10 +38,14 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
-import java.util.Set;
import java.util.ArrayList;
/**
+ * THIS HAS NO TESTS and is not used anywhere.... no idea how or if it should work...
+ *
+ * I think we should drop it - along with {@link GenericBinaryResponseWriter} and {@link GenericBinaryResponseWriter}
+ *
+ * unless I'm missing something (ryan, March 2011)
*
*
* This class serves as a basis from which {@link QueryResponseWriter}s can be
@@ -60,7 +64,6 @@ public abstract class BaseResponseWriter
private static final Logger LOG = LoggerFactory
.getLogger(BaseResponseWriter.class);
- private static final String SCORE_FIELD = "score";
/**
*
@@ -110,9 +113,6 @@ public abstract class BaseResponseWriter
responseWriter.startDocumentList(name,info);
for (int j = 0; j < sz; j++) {
SolrDocument sdoc = getDoc(iterator.nextDoc(), idxInfo);
- if (idxInfo.includeScore && docList.hasScores()) {
- sdoc.addField(SCORE_FIELD, iterator.score());
- }
responseWriter.writeDoc(sdoc);
}
} else {
@@ -120,9 +120,6 @@ public abstract class BaseResponseWriter
.size());
for (int j = 0; j < sz; j++) {
SolrDocument sdoc = getDoc(iterator.nextDoc(), idxInfo);
- if (idxInfo.includeScore && docList.hasScores()) {
- sdoc.addField(SCORE_FIELD, iterator.score());
- }
list.add(sdoc);
}
responseWriter.writeAllDocs(info, list);
@@ -144,22 +141,13 @@ public abstract class BaseResponseWriter
private static class IdxInfo {
IndexSchema schema;
SolrIndexSearcher searcher;
- Set<String> returnFields;
- boolean includeScore;
+ ReturnFields returnFields;
private IdxInfo(IndexSchema schema, SolrIndexSearcher searcher,
- Set<String> returnFields) {
+ ReturnFields returnFields) {
this.schema = schema;
this.searcher = searcher;
- this.includeScore = returnFields != null
- && returnFields.contains(SCORE_FIELD);
- if (returnFields != null) {
- if (returnFields.size() == 0 || (returnFields.size() == 1 && includeScore) || returnFields.contains("*")) {
- returnFields = null; // null means return all stored fields
- }
- }
this.returnFields = returnFields;
-
}
}
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/response/BinaryResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/BinaryResponseWriter.java?rev=1085450&r1=1085449&r2=1085450&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/BinaryResponseWriter.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/BinaryResponseWriter.java Fri Mar 25 16:24:21 2011
@@ -19,12 +19,14 @@ package org.apache.solr.response;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Fieldable;
import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.JavaBinCodec;
import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.transform.DocTransformer;
+import org.apache.solr.response.transform.TransformContext;
import org.apache.solr.schema.*;
-import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocList;
import org.apache.solr.search.SolrIndexSearcher;
import org.slf4j.Logger;
@@ -62,79 +64,101 @@ public class BinaryResponseWriter implem
protected final SolrQueryRequest solrQueryRequest;
protected IndexSchema schema;
protected SolrIndexSearcher searcher;
- protected final Set<String> returnFields;
- protected final boolean includeScore;
+ protected final ReturnFields returnFields;
// transmit field values using FieldType.toObject()
// rather than the String from FieldType.toExternal()
boolean useFieldObjects = true;
- public Resolver(SolrQueryRequest req, Set<String> returnFields) {
+ public Resolver(SolrQueryRequest req, ReturnFields returnFields) {
solrQueryRequest = req;
- this.includeScore = returnFields != null && returnFields.contains("score");
-
- if (returnFields != null) {
- if (returnFields.size() == 0 || (returnFields.size() == 1 && includeScore) || returnFields.contains("*")) {
- returnFields = null; // null means return all stored fields
- }
- }
this.returnFields = returnFields;
}
public Object resolve(Object o, JavaBinCodec codec) throws IOException {
+ if (o instanceof ResultContext) {
+ writeResults((ResultContext) o, codec);
+ return null; // null means we completely handled it
+ }
if (o instanceof DocList) {
- writeDocList((DocList) o, codec);
+ ResultContext ctx = new ResultContext();
+ ctx.docs = (DocList) o;
+ writeResults(ctx, codec);
return null; // null means we completely handled it
}
+
if (o instanceof SolrDocument) {
- SolrDocument solrDocument = (SolrDocument) o;
- codec.writeSolrDocument(solrDocument, returnFields);
- return null;
- }
- if (o instanceof Document) {
- return getDoc((Document) o);
+ // Remove any fields that were not requested
+ // This typically happens when distributed search adds extra fields to an internal request
+ SolrDocument doc = (SolrDocument)o;
+ for( String fname : doc.getFieldNames() ) {
+ if( !returnFields.contains( fname ) ) {
+ doc.removeFields( fname );
+ }
+ }
+ return doc;
}
-
return o;
}
- public void writeDocList(DocList ids, JavaBinCodec codec) throws IOException {
- codec.writeTag(JavaBinCodec.SOLRDOCLST);
- List l = new ArrayList(3);
- l.add((long) ids.matches());
- l.add((long) ids.offset());
- Float maxScore = null;
- if (includeScore && ids.hasScores()) {
- maxScore = ids.maxScore();
- }
- l.add(maxScore);
- codec.writeArray(l);
-
+ protected void writeResultsBody( ResultContext res, JavaBinCodec codec ) throws IOException
+ {
+ DocList ids = res.docs;
+ TransformContext context = new TransformContext();
+ context.query = res.query;
+ context.wantsScores = returnFields.getWantsScore() && ids.hasScores();
+
int sz = ids.size();
codec.writeTag(JavaBinCodec.ARR, sz);
if(searcher == null) searcher = solrQueryRequest.getSearcher();
if(schema == null) schema = solrQueryRequest.getSchema();
- DocIterator iterator = ids.iterator();
+
+ context.searcher = searcher;
+ DocTransformer transformer = returnFields.getTransformer();
+ if( transformer != null ) {
+ transformer.setContext( context );
+ }
+
+ Set<String> fnames = returnFields.getFieldNames();
+ context.iterator = ids.iterator();
for (int i = 0; i < sz; i++) {
- int id = iterator.nextDoc();
- Document doc = searcher.doc(id, returnFields);
-
+ int id = context.iterator.nextDoc();
+ Document doc = searcher.doc(id, fnames);
SolrDocument sdoc = getDoc(doc);
-
- if (includeScore && ids.hasScores()) {
- sdoc.addField("score", iterator.score());
+ if( transformer != null ) {
+ transformer.transform(sdoc, id );
}
-
codec.writeSolrDocument(sdoc);
}
+ if( transformer != null ) {
+ transformer.setContext( null );
+ }
+ }
+
+ public void writeResults(ResultContext ctx, JavaBinCodec codec) throws IOException {
+ codec.writeTag(JavaBinCodec.SOLRDOCLST);
+ boolean wantsScores = returnFields.getWantsScore() && ctx.docs.hasScores();
+ List l = new ArrayList(3);
+ l.add((long) ctx.docs.matches());
+ l.add((long) ctx.docs.offset());
+
+ Float maxScore = null;
+ if (wantsScores) {
+ maxScore = ctx.docs.maxScore();
+ }
+ l.add(maxScore);
+ codec.writeArray(l);
+
+ // this is a seprate function so that streaming responses can use just that part
+ writeResultsBody( ctx, codec );
}
-
public SolrDocument getDoc(Document doc) {
SolrDocument solrDoc = new SolrDocument();
for (Fieldable f : doc.getFields()) {
String fieldName = f.name();
- if (returnFields != null && !returnFields.contains(fieldName)) continue;
+ if( !returnFields.contains(fieldName) )
+ continue;
SchemaField sf = schema.getFieldOrNull(fieldName);
FieldType ft = null;
if(sf != null) ft =sf.getType();
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/response/CSVResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/CSVResponseWriter.java?rev=1085450&r1=1085449&r2=1085450&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/CSVResponseWriter.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/CSVResponseWriter.java Fri Mar 25 16:24:21 2011
@@ -159,7 +159,6 @@ class CSVWriter extends TextResponseWrit
ResettableFastWriter mvWriter = new ResettableFastWriter(); // writer used for multi-valued fields
String NullValue;
- boolean returnScore = false;
public CSVWriter(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) {
@@ -236,12 +235,9 @@ class CSVWriter extends TextResponseWrit
// encapsulator will already be disabled if it wasn't specified
}
- returnScore = returnFields != null && returnFields.contains("score");
- boolean needListOfFields = returnFields==null || returnFields.size()==0 || (returnFields.size()==1 && returnScore) || returnFields.contains("*");
- Collection<String> fields = returnFields;
-
+ Collection<String> fields = returnFields.getFieldNames();
Object responseObj = rsp.getValues().get("response");
- if (needListOfFields) {
+ if (fields==null) {
if (responseObj instanceof SolrDocumentList) {
// get the list of fields from the SolrDocumentList
fields = new LinkedHashSet<String>();
@@ -252,7 +248,7 @@ class CSVWriter extends TextResponseWrit
// get the list of fields from the index
fields = req.getSearcher().getFieldNames();
}
- if (returnScore) {
+ if (returnFields.getWantsScore()) {
fields.add("score");
} else {
fields.remove("score");
@@ -327,11 +323,15 @@ class CSVWriter extends TextResponseWrit
printer.println();
}
-
- if (responseObj instanceof DocList) {
- writeDocList(null, (DocList)responseObj, null, null);
+ if (responseObj instanceof ResultContext ) {
+ writeDocuments(null, (ResultContext)responseObj, returnFields );
+ }
+ else if (responseObj instanceof DocList) {
+ ResultContext ctx = new ResultContext();
+ ctx.docs = (DocList)responseObj;
+ writeDocuments(null, ctx, returnFields );
} else if (responseObj instanceof SolrDocumentList) {
- writeSolrDocumentList(null, (SolrDocumentList)responseObj, null, null);
+ writeSolrDocumentList(null, (SolrDocumentList)responseObj, returnFields );
}
}
@@ -346,56 +346,21 @@ class CSVWriter extends TextResponseWrit
public void writeNamedList(String name, NamedList val) throws IOException {
}
- @Override
- public void writeDoc(String name, Document doc, Set<String> returnFields, float score, boolean includeScore) throws IOException {
- pass++;
-
- for (Fieldable field: doc.getFields()) {
- CSVField csvField = csvFields.get(field.name());
- if (csvField == null) continue;
- if (csvField.tmp != pass) {
- csvField.tmp = pass;
- csvField.values.clear();
- }
- csvField.values.add(field);
- }
-
- for (CSVField csvField : csvFields.values()) {
- if (csvField.name.equals("score")) {
- writeFloat("score", score);
- continue;
- }
- if (csvField.tmp != pass) {
- writeNull(csvField.name);
- continue;
- }
-
- if (csvField.sf.multiValued() || csvField.values.size() > 1) {
- mvWriter.reset();
- csvField.mvPrinter.reset();
- // switch the printer to use the multi-valued one
- CSVPrinter tmp = printer;
- printer = csvField.mvPrinter;
- for (Fieldable fval : csvField.values) {
- csvField.sf.getType().write(this, csvField.name, fval);
- }
- printer = tmp; // restore the original printer
-
- mvWriter.freeze();
- printer.print(mvWriter.getFrozenBuf(), 0, mvWriter.getFrozenSize(), true);
- } else {
- assert csvField.values.size() == 1;
- csvField.sf.getType().write(this,csvField.name,csvField.values.get(0));
- }
- }
+ public void writeStartDocumentList(String name,
+ long start, int size, long numFound, Float maxScore) throws IOException
+ {
+ // nothing
+ }
- printer.println();
+ public void writeEndDocumentList() throws IOException
+ {
+ // nothing
}
//NOTE: a document cannot currently contain another document
List tmpList;
@Override
- public void writeSolrDocument(String name, SolrDocument doc, Set<String> returnFields, Map pseudoFields) throws IOException {
+ public void writeSolrDocument(String name, SolrDocument doc, ReturnFields returnFields, int idx ) throws IOException {
if (tmpList == null) {
tmpList = new ArrayList(1);
tmpList.add(null);
@@ -446,26 +411,6 @@ class CSVWriter extends TextResponseWrit
}
@Override
- public void writeDocList(String name, DocList ids, Set<String> fields, Map otherFields) throws IOException {
- int sz=ids.size();
- SolrIndexSearcher searcher = req.getSearcher();
- DocIterator iterator = ids.iterator();
- for (int i=0; i<sz; i++) {
- int id = iterator.nextDoc();
- Document doc = searcher.doc(id, fields);
- writeDoc(null, doc, fields, (returnScore ? iterator.score() : 0.0f), returnScore);
- }
- }
-
- Map scoreMap = new HashMap(1);
- @Override
- public void writeSolrDocumentList(String name, SolrDocumentList docs, Set<String> fields, Map otherFields) throws IOException {
- for (SolrDocument doc : docs) {
- writeSolrDocument(name, doc, fields, otherFields);
- }
- }
-
- @Override
public void writeStr(String name, String val, boolean needsEscaping) throws IOException {
printer.print(val, needsEscaping);
}
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/response/JSONResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/JSONResponseWriter.java?rev=1085450&r1=1085449&r2=1085450&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/JSONResponseWriter.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/JSONResponseWriter.java Fri Mar 25 16:24:21 2011
@@ -17,24 +17,23 @@
package org.apache.solr.response;
-import org.apache.lucene.document.Document;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.util.StringHelper;
import org.apache.solr.common.SolrDocument;
-import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.schema.SchemaField;
-import org.apache.solr.schema.TextField;
-import org.apache.solr.search.DocIterator;
-import org.apache.solr.search.DocList;
-import org.apache.solr.search.SolrIndexSearcher;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.*;
/**
* @version $Id$
@@ -73,7 +72,6 @@ class JSONWriter extends TextResponseWri
private static final String JSON_NL_ARROFMAP="arrmap";
private static final String JSON_WRAPPER_FUNCTION="json.wrf";
-
public JSONWriter(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) {
super(writer, req, rsp);
namedListStyle = StringHelper.intern(req.getParams().get(JSON_NL_STYLE, JSON_NL_FLAT));
@@ -312,94 +310,21 @@ class JSONWriter extends TextResponseWri
}
}
- public void writeDoc(String name, Collection<Fieldable> fields, Set<String> returnFields, Map pseudoFields) throws IOException {
- writeMapOpener(-1); // no trivial way to determine map size
- incLevel();
-
- HashMap<String, MultiValueField> multi = new HashMap<String, MultiValueField>();
-
- boolean first=true;
-
- for (Fieldable ff : fields) {
- String fname = ff.name();
- if (returnFields!=null && !returnFields.contains(fname)) {
- continue;
- }
-
- // if the field is multivalued, it may have other values further on... so
- // build up a list for each multi-valued field.
- SchemaField sf = schema.getField(fname);
- if (sf.multiValued()) {
- MultiValueField mf = multi.get(fname);
- if (mf==null) {
- mf = new MultiValueField(sf, ff);
- multi.put(fname, mf);
- } else {
- mf.fields.add(ff);
- }
- } else {
- // not multi-valued, so write it immediately.
- if (first) {
- first=false;
- } else {
- writeMapSeparator();
- }
- indent();
- writeKey(fname,true);
- sf.write(this, fname, ff);
- }
- }
-
- for(MultiValueField mvf : multi.values()) {
- if (first) {
- first=false;
- } else {
- writeMapSeparator();
- }
-
- indent();
- writeKey(mvf.sfield.getName(), true);
-
- boolean indentArrElems=false;
- if (doIndent) {
- // heuristic... TextField is probably the only field type likely to be long enough
- // to warrant indenting individual values.
- indentArrElems = (mvf.sfield.getType() instanceof TextField);
- }
-
- writeArrayOpener(-1); // no trivial way to determine array size
- boolean firstArrElem=true;
- incLevel();
-
- for (Fieldable ff : mvf.fields) {
- if (firstArrElem) {
- firstArrElem=false;
- } else {
- writeArraySeparator();
- }
- if (indentArrElems) indent();
- mvf.sfield.write(this, null, ff);
- }
- writeArrayCloser();
- decLevel();
- }
-
- if (pseudoFields !=null && pseudoFields.size()>0) {
- writeMap(null,pseudoFields,true,first);
- }
-
- decLevel();
- writeMapCloser();
- }
-
@Override
- public void writeSolrDocument(String name, SolrDocument doc, Set<String> returnFields, Map pseudoFields) throws IOException {
- writeMapOpener(-1); // no trivial way to determine map size
- // TODO: could easily figure out size for SolrDocument if needed...
+ public void writeSolrDocument(String name, SolrDocument doc, ReturnFields returnFields, int idx) throws IOException {
+ if( idx > 0 ) {
+ writeArraySeparator();
+ }
+
+ writeMapOpener(doc.size());
incLevel();
boolean first=true;
for (String fname : doc.getFieldNames()) {
+ if (!returnFields.contains(fname)) {
+ continue;
+ }
+
if (first) {
first=false;
}
@@ -424,144 +349,43 @@ class JSONWriter extends TextResponseWri
writeVal(fname, val);
}
}
-
- if (pseudoFields !=null && pseudoFields.size()>0) {
- writeMap(null,pseudoFields,true,first);
- }
}
-
+
decLevel();
writeMapCloser();
}
-
- // reusable map to store the "score" pseudo-field.
- // if a Doc can ever contain another doc, this optimization would have to go.
- private final HashMap scoreMap = new HashMap(1);
-
- @Override
- public void writeDoc(String name, Document doc, Set<String> returnFields, float score, boolean includeScore) throws IOException {
- Map other = null;
- if (includeScore) {
- other = scoreMap;
- scoreMap.put("score",score);
- }
- writeDoc(name, doc.getFields(), returnFields, other);
- }
-
@Override
- public void writeDocList(String name, DocList ids, Set<String> fields, Map otherFields) throws IOException {
- boolean includeScore=false;
- if (fields!=null) {
- includeScore = fields.contains("score");
- if (fields.size()==0 || (fields.size()==1 && includeScore) || fields.contains("*")) {
- fields=null; // null means return all stored fields
- }
- }
-
- int sz=ids.size();
-
- writeMapOpener(includeScore ? 4 : 3);
+ public void writeStartDocumentList(String name,
+ long start, int size, long numFound, Float maxScore) throws IOException
+ {
+ writeMapOpener((maxScore==null) ? 3 : 4);
incLevel();
writeKey("numFound",false);
- writeInt(null,ids.matches());
+ writeLong(null,numFound);
writeMapSeparator();
writeKey("start",false);
- writeInt(null,ids.offset());
+ writeLong(null,start);
- if (includeScore) {
+ if (maxScore!=null) {
writeMapSeparator();
writeKey("maxScore",false);
- writeFloat(null,ids.maxScore());
+ writeFloat(null,maxScore);
}
writeMapSeparator();
// indent();
writeKey("docs",false);
- writeArrayOpener(sz);
+ writeArrayOpener(size);
incLevel();
- boolean first=true;
-
- SolrIndexSearcher searcher = req.getSearcher();
- // be defensive... write out the doc even if we don't have the scores like we should
- includeScore = includeScore && ids.hasScores();
- DocIterator iterator = ids.iterator();
- for (int i=0; i<sz; i++) {
- int id = iterator.nextDoc();
- Document doc = searcher.doc(id, fields);
-
- if (first) {
- first=false;
- } else {
- writeArraySeparator();
- }
- indent();
- writeDoc(null, doc, fields, (includeScore ? iterator.score() : 0.0f), includeScore);
- }
- decLevel();
- writeArrayCloser();
-
- if (otherFields !=null) {
- writeMap(null, otherFields, true, false);
- }
-
- decLevel();
- indent();
- writeMapCloser();
}
-
@Override
- public void writeSolrDocumentList(String name, SolrDocumentList docs, Set<String> fields, Map otherFields) throws IOException {
- boolean includeScore=false;
- if (fields!=null) {
- includeScore = fields.contains("score");
- if (fields.size()==0 || (fields.size()==1 && includeScore) || fields.contains("*")) {
- fields=null; // null means return all stored fields
- }
- }
-
- int sz=docs.size();
-
- writeMapOpener(includeScore ? 4 : 3);
- incLevel();
- writeKey("numFound",false);
- writeLong(null,docs.getNumFound());
- writeMapSeparator();
- writeKey("start",false);
- writeLong(null,docs.getStart());
-
- if (includeScore && docs.getMaxScore() != null) {
- writeMapSeparator();
- writeKey("maxScore",false);
- writeFloat(null,docs.getMaxScore());
- }
- writeMapSeparator();
- // indent();
- writeKey("docs",false);
- writeArrayOpener(sz);
-
- incLevel();
- boolean first=true;
-
- SolrIndexSearcher searcher = req.getSearcher();
- for (SolrDocument doc : docs) {
-
- if (first) {
- first=false;
- } else {
- writeArraySeparator();
- }
- indent();
- writeSolrDocument(null, doc, fields, otherFields);
- }
+ public void writeEndDocumentList() throws IOException
+ {
decLevel();
writeArrayCloser();
- if (otherFields !=null) {
- writeMap(null, otherFields, true, false);
- }
-
decLevel();
indent();
writeMapCloser();
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java?rev=1085450&r1=1085449&r2=1085450&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/PHPSerializedResponseWriter.java Fri Mar 25 16:24:21 2011
@@ -17,23 +17,22 @@
package org.apache.solr.response;
-import java.io.Writer;
import java.io.IOException;
-import java.util.*;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.UnicodeUtil;
+import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.schema.SchemaField;
-import org.apache.solr.search.DocIterator;
-import org.apache.solr.search.DocList;
-import org.apache.solr.search.SolrIndexSearcher;
-import org.apache.solr.common.SolrDocument;
-import org.apache.solr.common.SolrDocumentList;
+
+
/**
* A description of the PHP serialization format can be found here:
* http://www.hurring.com/scott/code/perl/serialize/
@@ -80,126 +79,53 @@ class PHPSerializedWriter extends JSONWr
writeNamedListAsMapMangled(name,val);
}
- @Override
- public void writeDoc(String name, Collection<Fieldable> fields, Set<String> returnFields, Map pseudoFields) throws IOException {
- ArrayList<Fieldable> single = new ArrayList<Fieldable>();
- LinkedHashMap<String, MultiValueField> multi
- = new LinkedHashMap<String, MultiValueField>();
-
- for (Fieldable ff : fields) {
- String fname = ff.name();
- if (returnFields!=null && !returnFields.contains(fname)) {
- continue;
- }
- // if the field is multivalued, it may have other values further on... so
- // build up a list for each multi-valued field.
- SchemaField sf = schema.getField(fname);
- if (sf.multiValued()) {
- MultiValueField mf = multi.get(fname);
- if (mf==null) {
- mf = new MultiValueField(sf, ff);
- multi.put(fname, mf);
- } else {
- mf.fields.add(ff);
- }
- } else {
- single.add(ff);
- }
- }
-
- // obtain number of fields in doc
- writeArrayOpener(single.size() + multi.size() + ((pseudoFields!=null) ? pseudoFields.size() : 0));
-
- // output single value fields
- for(Fieldable ff : single) {
- SchemaField sf = schema.getField(ff.name());
- writeKey(ff.name(),true);
- sf.write(this, ff.name(), ff);
- }
-
- // output multi value fields
- for(MultiValueField mvf : multi.values()) {
- writeKey(mvf.sfield.getName(), true);
- writeArrayOpener(mvf.fields.size());
- int i = 0;
- for (Fieldable ff : mvf.fields) {
- writeKey(i++, false);
- mvf.sfield.write(this, null, ff);
- }
- writeArrayCloser();
- }
-
- // output pseudo fields
- if (pseudoFields !=null && pseudoFields.size()>0) {
- writeMap(null,pseudoFields,true,false);
- }
- writeArrayCloser();
- }
- @Override
- public void writeDocList(String name, DocList ids, Set<String> fields, Map otherFields) throws IOException {
- boolean includeScore=false;
-
- if (fields!=null) {
- includeScore = fields.contains("score");
- if (fields.size()==0 || (fields.size()==1 && includeScore) || fields.contains("*")) {
- fields=null; // null means return all stored fields
- }
- }
-
- int sz=ids.size();
- writeMapOpener(includeScore ? 4 : 3);
+ public void writeStartDocumentList(String name,
+ long start, int size, long numFound, Float maxScore) throws IOException
+ {
+ writeMapOpener((maxScore==null) ? 3 : 4);
writeKey("numFound",false);
- writeInt(null,ids.matches());
+ writeLong(null,numFound);
writeKey("start",false);
- writeInt(null,ids.offset());
+ writeLong(null,start);
- if (includeScore) {
+ if (maxScore!=null) {
writeKey("maxScore",false);
- writeFloat(null,ids.maxScore());
+ writeFloat(null,maxScore);
}
writeKey("docs",false);
- writeArrayOpener(sz);
-
- SolrIndexSearcher searcher = req.getSearcher();
- DocIterator iterator = ids.iterator();
- for (int i=0; i<sz; i++) {
- int id = iterator.nextDoc();
- Document doc = searcher.doc(id, fields);
- writeKey(i, false);
- writeDoc(null, doc, fields, (includeScore ? iterator.score() : 0.0f), includeScore);
- }
- writeMapCloser();
-
- if (otherFields !=null) {
- writeMap(null, otherFields, true, false);
- }
+ writeArrayOpener(size);
+ }
+ public void writeEndDocumentList() throws IOException
+ {
+ writeArrayCloser(); // doc list
writeMapCloser();
}
@Override
- public void writeSolrDocument(String name, SolrDocument doc, Set<String> returnFields, Map pseudoFields) throws IOException {
+ public void writeSolrDocument(String name, SolrDocument doc, ReturnFields returnFields, int idx) throws IOException
+ {
+ writeKey(idx, false);
+
LinkedHashMap <String,Object> single = new LinkedHashMap<String, Object>();
LinkedHashMap <String,Object> multi = new LinkedHashMap<String, Object>();
- int pseudoSize = pseudoFields != null ? pseudoFields.size() : 0;
for (String fname : doc.getFieldNames()) {
- if(returnFields != null && !returnFields.contains(fname)){
+ if(!returnFields.contains(fname)){
continue;
}
Object val = doc.getFieldValue(fname);
- SchemaField sf = schema.getFieldOrNull(fname);
- if (sf != null && sf.multiValued()) {
+ if (val instanceof Collection) {
multi.put(fname, val);
}else{
single.put(fname, val);
}
}
- writeMapOpener(single.size() + multi.size() + pseudoSize);
+ writeMapOpener(single.size() + multi.size());
for(String fname: single.keySet()){
Object val = single.get(fname);
writeKey(fname, true);
@@ -220,51 +146,7 @@ class PHPSerializedWriter extends JSONWr
writeVal(fname, val);
}
}
-
- if (pseudoSize > 0) {
- writeMap(null,pseudoFields,true, false);
- }
- writeMapCloser();
- }
-
-
- @Override
- public void writeSolrDocumentList(String name, SolrDocumentList docs, Set<String> fields, Map otherFields) throws IOException {
- boolean includeScore=false;
- if (fields!=null) {
- includeScore = fields.contains("score");
- if (fields.size()==0 || (fields.size()==1 && includeScore) || fields.contains("*")) {
- fields=null; // null means return all stored fields
- }
- }
-
- int sz = docs.size();
-
- writeMapOpener(includeScore ? 4 : 3);
-
- writeKey("numFound",false);
- writeLong(null,docs.getNumFound());
-
- writeKey("start",false);
- writeLong(null,docs.getStart());
-
- if (includeScore && docs.getMaxScore() != null) {
- writeKey("maxScore",false);
- writeFloat(null,docs.getMaxScore());
- }
-
- writeKey("docs",false);
-
- writeArrayOpener(sz);
- for (int i=0; i<sz; i++) {
- writeKey(i, false);
- writeSolrDocument(null, docs.get(i), fields, otherFields);
- }
- writeArrayCloser();
-
- if (otherFields !=null) {
- writeMap(null, otherFields, true, false);
- }
+
writeMapCloser();
}
Added: lucene/dev/trunk/solr/src/java/org/apache/solr/response/ResultContext.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/ResultContext.java?rev=1085450&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/ResultContext.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/ResultContext.java Fri Mar 25 16:24:21 2011
@@ -0,0 +1,31 @@
+/**
+ * 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.response;
+
+import org.apache.lucene.search.Query;
+import org.apache.solr.search.DocList;
+
+/**
+ * A class to hold the QueryResult and the Query
+ *
+ * @version $Id: JSONResponseWriter.java 1065304 2011-01-30 15:10:15Z rmuir $
+ */
+public class ResultContext {
+ public Query query;
+ public DocList docs;
+}
Added: lucene/dev/trunk/solr/src/java/org/apache/solr/response/ReturnFields.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/ReturnFields.java?rev=1085450&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/ReturnFields.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/ReturnFields.java Fri Mar 25 16:24:21 2011
@@ -0,0 +1,168 @@
+/**
+ * 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.response;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.transform.DocIdAugmenter;
+import org.apache.solr.response.transform.DocTransformer;
+import org.apache.solr.response.transform.DocTransformers;
+import org.apache.solr.response.transform.ExplainAugmenter;
+import org.apache.solr.response.transform.ScoreAugmenter;
+import org.apache.solr.response.transform.ValueAugmenter;
+import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.schema.SchemaField;
+import org.apache.solr.util.SolrPluginUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A class representing the return fields
+ *
+ * @version $Id: JSONResponseWriter.java 1065304 2011-01-30 15:10:15Z rmuir $
+ * @since solr 4.0
+ */
+public class ReturnFields
+{
+ static final Logger log = LoggerFactory.getLogger( ReturnFields.class );
+
+ public static final String SCORE = "score";
+ public static final String DOCID = "_docid_";
+ public static final String SHARD = "_shard_";
+ public static final String EXPLAIN = "_explain_";
+
+ private Set<String> fields; // includes 'augment' names or null
+ private DocTransformer transformer;
+ private boolean wantsScore = false;
+
+
+ public static ReturnFields getReturnFields(SolrQueryRequest req)
+ {
+ return getReturnFields( req.getParams().get(CommonParams.FL), req );
+ }
+
+ public static ReturnFields getReturnFields(String fl, SolrQueryRequest req)
+ {
+ ReturnFields rf = new ReturnFields();
+ rf.wantsScore = false;
+ rf.fields = new LinkedHashSet<String>(); // order is important for CSVResponseWriter
+ boolean allFields = false;
+
+ DocTransformers augmenters = new DocTransformers();
+ if (fl != null) {
+ // TODO - this could become more efficient if widely used.
+ String[] flst = SolrPluginUtils.split(fl);
+ if (flst.length > 0 && !(flst.length==1 && flst[0].length()==0)) {
+ IndexSchema schema = req.getSchema();
+ for (String name : flst) {
+ if( "*".equals( name ) ) {
+ allFields = true;
+ }
+ else if( SCORE.equals( name ) ) {
+ rf.fields.add( name );
+ rf.wantsScore = true;
+ augmenters.addTransformer( new ScoreAugmenter( SCORE ) );
+ }
+ else {
+ rf.fields.add( name );
+
+ // Check if it is a real score
+ SchemaField sf = schema.getFieldOrNull( name );
+ if( sf == null ) {
+ // not a field name, but possibly return value
+ if( DOCID.equals( name ) ) {
+ augmenters.addTransformer( new DocIdAugmenter( DOCID ) );
+ }
+ else if( SHARD.equals( name ) ) {
+ String id = "getshardid???";
+ augmenters.addTransformer( new ValueAugmenter( SHARD, id ) );
+ }
+ else if( EXPLAIN.equals( name ) ) {
+ augmenters.addTransformer( new ExplainAugmenter( EXPLAIN ) );
+ }
+ else if( name.startsWith( "{!func}") ) {
+ // help? not sure how to parse a ValueSorce
+ // -- not to mention, we probably want to reuse existing ones!
+ augmenters.addTransformer( new ValueAugmenter( name, "TODO:"+name ) );
+// try {
+// String func = name.substring( "{!func}".length() );
+// SolrParams local = null;
+// FunctionQParser p = new FunctionQParser( func, local, req.getParams(), req );
+// Query q = p.parse();
+// ValueSource vs = p.parseValueSource();
+// AtomicReaderContext ctx = new AtomicReaderContext( req.getSearcher().getIndexReader() );
+// Map mmm = null; // ?????
+// DocValues values = p.parseValueSource().getValues( mmm, ctx );
+// augmenters.addAugmenter( new DocValuesAugmenter( name, values ) );
+// }
+// catch( Exception ex ) {
+// throw new SolrException( org.apache.solr.common.SolrException.ErrorCode.BAD_REQUEST,
+// "Unable to parse augmented field: "+name, ex );
+// }
+ }
+ else {
+ // maybe throw an exception?
+// throw new SolrException( org.apache.solr.common.SolrException.ErrorCode.BAD_REQUEST,
+// "Unknown Return Field: "+name );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Legacy behavior? "score" == "*,score"
+ if( rf.fields.size() == 1 && rf.wantsScore ) {
+ allFields = true;
+ }
+
+ if( allFields || rf.fields.isEmpty() ) {
+ rf.fields = null;
+ }
+
+ if( augmenters.size() == 1 ) {
+ rf.transformer = augmenters.getTransformer(0);
+ }
+ else if( augmenters.size() > 1 ) {
+ rf.transformer = augmenters;
+ }
+ return rf;
+ }
+
+ public Set<String> getFieldNames()
+ {
+ return fields;
+ }
+
+ public boolean getWantsScore()
+ {
+ return wantsScore;
+ }
+
+ public boolean contains( String name )
+ {
+ return fields==null || fields.contains( name );
+ }
+
+ public DocTransformer getTransformer()
+ {
+ return transformer;
+ }
+}
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/response/SolrQueryResponse.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/SolrQueryResponse.java?rev=1085450&r1=1085449&r2=1085450&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/SolrQueryResponse.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/SolrQueryResponse.java Fri Mar 25 16:24:21 2011
@@ -67,13 +67,14 @@ public class SolrQueryResponse {
* @see <a href="#returnable_data">Note on Returnable Data</a>
*/
protected NamedList<Object> values = new SimpleOrderedMap<Object>();
-
- /**
+
+
+/**
* Container for storing information that should be logged by Solr before returning.
*/
protected NamedList<Object> toLog = new SimpleOrderedMap<Object>();
- protected Set<String> defaultReturnFields;
+ protected ReturnFields returnFields;
// error if this is set...
protected Exception err;
@@ -111,18 +112,19 @@ public class SolrQueryResponse {
* Sets the document field names of fields to return by default when
* returning DocLists
*/
- public void setReturnFields(Set<String> fields) {
- defaultReturnFields=fields;
+ public void setReturnFields(ReturnFields fields) {
+ returnFields=fields;
}
- // TODO: should this be represented as a String[] such
- // that order can be maintained if needed?
/**
* Gets the document field names of fields to return by default when
* returning DocLists
*/
- public Set<String> getReturnFields() {
- return defaultReturnFields;
+ public ReturnFields getReturnFields() {
+ if( returnFields == null ) {
+ returnFields = new ReturnFields(); // by default return everything
+ }
+ return returnFields;
}
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/response/TextResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/TextResponseWriter.java?rev=1085450&r1=1085449&r2=1085450&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/TextResponseWriter.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/TextResponseWriter.java Fri Mar 25 16:24:21 2011
@@ -17,17 +17,22 @@
package org.apache.solr.response;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.*;
+
import org.apache.lucene.document.Document;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.FastWriter;
+import org.apache.lucene.document.Fieldable;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
+import org.apache.solr.common.util.FastWriter;
+import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.transform.DocTransformer;
+import org.apache.solr.response.transform.TransformContext;
import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.DocList;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.*;
/** Base class for text-oriented response writers.
*
@@ -49,7 +54,7 @@ public abstract class TextResponseWriter
protected final SolrQueryResponse rsp;
// the default set of fields to return for each document
- protected Set<String> returnFields;
+ protected ReturnFields returnFields;
protected int level;
protected boolean doIndent;
@@ -114,6 +119,15 @@ public abstract class TextResponseWriter
} else if (val instanceof String) {
writeStr(name, val.toString(), true);
// micro-optimization... using toString() avoids a cast first
+ } else if (val instanceof Fieldable) {
+ Fieldable f = (Fieldable)val;
+ SchemaField sf = schema.getFieldOrNull( f.name() );
+ if( sf != null ) {
+ sf.getType().write(this, name, f);
+ }
+ else {
+ writeStr(name, f.stringValue(), true);
+ }
} else if (val instanceof Integer) {
writeInt(name, val.toString());
} else if (val instanceof Boolean) {
@@ -129,19 +143,25 @@ public abstract class TextResponseWriter
} else if (val instanceof Double) {
writeDouble(name, ((Double)val).doubleValue());
} else if (val instanceof Document) {
- writeDoc(name, (Document)val, returnFields, 0.0f, false);
+ SolrDocument doc = toSolrDocument( (Document)val );
+ writeSolrDocument(name, doc, returnFields, 0 );
} else if (val instanceof SolrDocument) {
- writeSolrDocument(name, (SolrDocument)val, returnFields, null);
- } else if (val instanceof DocList) {
+ writeSolrDocument(name, (SolrDocument)val, returnFields, 0);
+ } else if (val instanceof ResultContext) {
// requires access to IndexReader
- writeDocList(name, (DocList)val, returnFields,null);
+ writeDocuments(name, (ResultContext)val, returnFields);
+ } else if (val instanceof DocList) {
+ // Should not happen normally
+ ResultContext ctx = new ResultContext();
+ ctx.docs = (DocList)val;
+ writeDocuments(name, ctx, returnFields);
// }
// else if (val instanceof DocSet) {
// how do we know what fields to read?
// todo: have a DocList/DocSet wrapper that
// restricts the fields to write...?
} else if (val instanceof SolrDocumentList) {
- writeSolrDocumentList(name, (SolrDocumentList)val, returnFields, null);
+ writeSolrDocumentList(name, (SolrDocumentList)val, returnFields);
} else if (val instanceof Map) {
writeMap(name, (Map)val, false, true);
} else if (val instanceof NamedList) {
@@ -162,20 +182,82 @@ public abstract class TextResponseWriter
// types of formats, including those where the name may come after the value (like
// some XML formats).
- public abstract void writeDoc(String name, Document doc, Set<String> returnFields, float score, boolean includeScore) throws IOException;
+ public abstract void writeStartDocumentList(String name, long start, int size, long numFound, Float maxScore) throws IOException;
- /**
- * @since solr 1.3
- */
- public abstract void writeSolrDocument(String name, SolrDocument doc, Set<String> returnFields, Map pseudoFields) throws IOException;
-
- public abstract void writeDocList(String name, DocList ids, Set<String> fields, Map otherFields) throws IOException;
-
- /**
- * @since solr 1.3
- */
- public abstract void writeSolrDocumentList(String name, SolrDocumentList docs, Set<String> fields, Map otherFields) throws IOException;
+ public abstract void writeSolrDocument(String name, SolrDocument doc, ReturnFields returnFields, int idx) throws IOException;
+
+ public abstract void writeEndDocumentList() throws IOException;
+
+ // Assume each SolrDocument is already transformed
+ public final void writeSolrDocumentList(String name, SolrDocumentList docs, ReturnFields returnFields) throws IOException
+ {
+ writeStartDocumentList(name, docs.getStart(), docs.size(), docs.getNumFound(), docs.getMaxScore() );
+ for( int i=0; i<docs.size(); i++ ) {
+ writeSolrDocument( null, docs.get(i), returnFields, i );
+ }
+ writeEndDocumentList();
+ }
+ public final SolrDocument toSolrDocument( Document doc )
+ {
+ SolrDocument out = new SolrDocument();
+ for( Fieldable f : doc.getFields() ) {
+ if( "gack_i".equals( f.name() ) ) {
+ System.out.println( f );
+ }
+
+ // Make sure multivalued fields are represented as lists
+ Object existing = out.get(f.name());
+ if (existing == null) {
+ SchemaField sf = schema.getFieldOrNull(f.name());
+ if (sf != null && sf.multiValued()) {
+ List<Object> vals = new ArrayList<Object>();
+ vals.add( f );
+ out.setField( f.name(), vals );
+ }
+ else{
+ out.setField( f.name(), f );
+ }
+ }
+ else {
+ out.addField( f.name(), f );
+ }
+ }
+ return out;
+ }
+
+ public final void writeDocuments(String name, ResultContext res, ReturnFields fields ) throws IOException {
+ DocList ids = res.docs;
+ TransformContext context = new TransformContext();
+ context.query = res.query;
+ context.wantsScores = fields.getWantsScore() && ids.hasScores();
+ writeStartDocumentList(name, ids.offset(), ids.size(), ids.matches(),
+ context.wantsScores ? new Float(ids.maxScore()) : null );
+
+ DocTransformer transformer = fields.getTransformer();
+ context.searcher = req.getSearcher();
+ context.iterator = ids.iterator();
+ if( transformer != null ) {
+ transformer.setContext( context );
+ }
+ int sz = ids.size();
+ Set<String> fnames = fields.getFieldNames();
+ for (int i=0; i<sz; i++) {
+ int id = context.iterator.nextDoc();
+ Document doc = context.searcher.doc(id, fnames);
+ SolrDocument sdoc = toSolrDocument( doc );
+ if( transformer != null ) {
+ transformer.transform( sdoc, id );
+ }
+ writeSolrDocument( null, sdoc, returnFields, i );
+ }
+ if( transformer != null ) {
+ transformer.setContext( null );
+ }
+ writeEndDocumentList();
+ }
+
+
public abstract void writeStr(String name, String val, boolean needsEscaping) throws IOException;
public abstract void writeMap(String name, Map val, boolean excludeOuter, boolean isFirstVal) throws IOException;
Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/response/XMLWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/XMLWriter.java?rev=1085450&r1=1085449&r2=1085450&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/XMLWriter.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/XMLWriter.java Fri Mar 25 16:24:21 2011
@@ -17,26 +17,22 @@
package org.apache.solr.response;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
import org.apache.solr.common.SolrDocument;
-import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.XML;
import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.search.SolrIndexSearcher;
-import org.apache.solr.search.DocList;
-import org.apache.solr.search.DocIterator;
-import org.apache.solr.search.DocSet;
import org.apache.solr.schema.SchemaField;
-import org.apache.solr.schema.TextField;
-
-import java.io.Writer;
-import java.io.IOException;
-import java.util.*;
-
-import org.apache.lucene.document.Fieldable;
-import org.apache.lucene.document.Document;
public final class XMLWriter extends TextResponseWriter {
@@ -166,257 +162,59 @@ public final class XMLWriter extends Tex
}
}
- private static final Comparator fieldnameComparator = new Comparator() {
- public int compare(Object o, Object o1) {
- Fieldable f1 = (Fieldable)o; Fieldable f2 = (Fieldable)o1;
- int cmp = f1.name().compareTo(f2.name());
- return cmp;
- // note - the sort is stable, so this should not have affected the ordering
- // of fields with the same name w.r.t eachother.
- }
- };
@Override
- public final void writeDoc(String name, Document doc, Set<String> returnFields, float score, boolean includeScore) throws IOException {
- startTag("doc", name, false);
- incLevel();
-
- if (includeScore) {
- writeFloat("score", score);
- }
-
-
- // Lucene Documents have multivalued types as multiple fields
- // with the same name.
- // The XML needs to represent these as
- // an array. The fastest way to detect multiple fields
- // with the same name is to sort them first.
-
-
- // using global tlst here, so we shouldn't call any other
- // function that uses it until we are done.
- tlst.clear();
- for (Object obj : doc.getFields()) {
- Fieldable ff = (Fieldable)obj;
- // skip this field if it is not a field to be returned.
- if (returnFields!=null && !returnFields.contains(ff.name())) {
- continue;
- }
- tlst.add(ff);
- }
- Collections.sort(tlst, fieldnameComparator);
-
- int sz = tlst.size();
- int fidx1 = 0, fidx2 = 0;
- while (fidx1 < sz) {
- Fieldable f1 = (Fieldable)tlst.get(fidx1);
- String fname = f1.name();
-
- // find the end of fields with this name
- fidx2 = fidx1+1;
- while (fidx2 < sz && fname.equals(((Fieldable)tlst.get(fidx2)).name()) ) {
- fidx2++;
- }
-
- /***
- // more efficient to use getFieldType instead of
- // getField since that way dynamic fields won't have
- // to create a SchemaField on the fly.
- FieldType ft = schema.getFieldType(fname);
- ***/
-
- SchemaField sf = schema.getFieldOrNull(fname);
- if( sf == null ) {
- sf = new SchemaField( fname, new TextField() );
- }
- if (fidx1+1 == fidx2) {
- // single field value
- if (sf.multiValued()) {
- startTag("arr",fname,false);
- doIndent=false;
- sf.write(this, null, f1);
- writer.write("</arr>");
- doIndent=defaultIndent;
- } else {
- sf.write(this, f1.name(), f1);
- }
- } else {
- // multiple fields with same name detected
+ public void writeStartDocumentList(String name,
+ long start, int size, long numFound, Float maxScore) throws IOException
+ {
+ if (doIndent) indent();
- startTag("arr",fname,false);
- incLevel();
- doIndent=false;
- int cnt=0;
- for (int i=fidx1; i<fidx2; i++) {
- if (defaultIndent && ++cnt==4) { // only indent every 4th item
- indent();
- cnt=0;
- }
- sf.write(this, null, (Fieldable)tlst.get(i));
- }
- decLevel();
- // if (doIndent) indent();
- writer.write("</arr>");
- // doIndent=true;
- doIndent=defaultIndent;
- }
- fidx1 = fidx2;
+ writer.write("<result");
+ writeAttr("name",name);
+ writeAttr("numFound",Long.toString(numFound));
+ writeAttr("start",Long.toString(start));
+ if(maxScore!=null) {
+ writeAttr("maxScore",Float.toString(maxScore));
}
-
- decLevel();
- if (doIndent) indent();
- writer.write("</doc>");
+ writer.write(">");
+
+ incLevel();
}
+
+ /**
+ * The SolrDocument should already have multivalued fields implemented as
+ * Collections -- this will not rewrite to <arr>
+ */
@Override
- public void writeSolrDocument(String name, SolrDocument doc, Set<String> returnFields, Map pseudoFields) throws IOException {
+ public void writeSolrDocument(String name, SolrDocument doc, ReturnFields returnFields, int idx ) throws IOException {
startTag("doc", name, false);
incLevel();
for (String fname : doc.getFieldNames()) {
- if (returnFields!=null && !returnFields.contains(fname)) {
+ if (!returnFields.contains(fname)) {
continue;
}
+
Object val = doc.getFieldValue(fname);
-
- if (val instanceof Collection) {
- writeVal(fname, val);
- } else {
- // single valued... figure out if we should put <arr> tags around it anyway
- SchemaField sf = schema.getFieldOrNull(fname);
- if (sf!=null && sf.multiValued()) {
- startTag("arr",fname,false);
- doIndent=false;
- writeVal(fname, val);
- writer.write("</arr>");
- doIndent=defaultIndent;
- } else {
- writeVal(fname, val);
- }
- }
- }
-
- if (pseudoFields != null) {
- for (Object fname : pseudoFields.keySet()) {
- writeVal(fname.toString(), pseudoFields.get(fname));
+ if( "_explain_".equals( fname ) ) {
+ System.out.println( val );
}
+ writeVal(fname, val);
}
-
+
decLevel();
- if (doIndent) indent();
writer.write("</doc>");
}
-
-
- private static interface DocumentListInfo {
- Float getMaxScore();
- int getCount();
- long getNumFound();
- long getStart();
- void writeDocs( boolean includeScore, Set<String> fields ) throws IOException;
- }
-
- private final void writeDocuments(
- String name,
- DocumentListInfo docs,
- Set<String> fields) throws IOException
+
+ @Override
+ public void writeEndDocumentList() throws IOException
{
- boolean includeScore=false;
- if (fields!=null) {
- includeScore = fields.contains("score");
- if (fields.size()==0 || (fields.size()==1 && includeScore) || fields.contains("*")) {
- fields=null; // null means return all stored fields
- }
- }
-
- int sz=docs.getCount();
- if (doIndent) indent();
-
- writer.write("<result");
- writeAttr("name",name);
- writeAttr("numFound",Long.toString(docs.getNumFound()));
- writeAttr("start",Long.toString(docs.getStart()));
- if (includeScore && docs.getMaxScore()!=null) {
- writeAttr("maxScore",Float.toString(docs.getMaxScore()));
- }
- if (sz==0) {
- writer.write("/>");
- return;
- } else {
- writer.write('>');
- }
-
- incLevel();
- docs.writeDocs(includeScore, fields);
decLevel();
-
if (doIndent) indent();
writer.write("</result>");
}
- @Override
- public final void writeSolrDocumentList(String name, final SolrDocumentList docs, Set<String> fields, Map otherFields) throws IOException
- {
- this.writeDocuments( name, new DocumentListInfo()
- {
- public int getCount() {
- return docs.size();
- }
-
- public Float getMaxScore() {
- return docs.getMaxScore();
- }
-
- public long getNumFound() {
- return docs.getNumFound();
- }
-
- public long getStart() {
- return docs.getStart();
- }
-
- public void writeDocs(boolean includeScore, Set<String> fields) throws IOException {
- for( SolrDocument doc : docs ) {
- writeSolrDocument(null, doc, fields, null);
- }
- }
- }, fields );
- }
-
- @Override
- public void writeDocList(String name, final DocList ids, Set<String> fields, Map otherFields) throws IOException
- {
- this.writeDocuments( name, new DocumentListInfo()
- {
- public int getCount() {
- return ids.size();
- }
-
- public Float getMaxScore() {
- return ids.maxScore();
- }
-
- public long getNumFound() {
- return ids.matches();
- }
-
- public long getStart() {
- return ids.offset();
- }
-
- public void writeDocs(boolean includeScore, Set<String> fields) throws IOException {
- SolrIndexSearcher searcher = req.getSearcher();
- DocIterator iterator = ids.iterator();
- int sz = ids.size();
- includeScore = includeScore && ids.hasScores();
- for (int i=0; i<sz; i++) {
- int id = iterator.nextDoc();
- Document doc = searcher.doc(id, fields);
- writeDoc(null, doc, fields, (includeScore ? iterator.score() : 0.0f), includeScore);
- }
- }
- }, fields );
- }
//
Added: lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocIdAugmenter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocIdAugmenter.java?rev=1085450&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocIdAugmenter.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocIdAugmenter.java Fri Mar 25 16:24:21 2011
@@ -0,0 +1,42 @@
+/**
+ * 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.response.transform;
+
+import org.apache.solr.common.SolrDocument;
+
+/**
+ * Simple Transformer to add the lucene docid
+ *
+ * @version $Id: JSONResponseWriter.java 1065304 2011-01-30 15:10:15Z rmuir $
+ * @since solr 4.0
+ */
+public class DocIdAugmenter extends DocTransformer
+{
+ final String name;
+
+ public DocIdAugmenter( String display )
+ {
+ this.name = display;
+ }
+
+ @Override
+ public void transform(SolrDocument doc, int docid) {
+ if( docid >= 0 ) {
+ doc.setField( name, docid );
+ }
+ }
+}
Added: lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocTransformer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocTransformer.java?rev=1085450&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocTransformer.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocTransformer.java Fri Mar 25 16:24:21 2011
@@ -0,0 +1,33 @@
+/**
+ * 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.response.transform;
+
+import java.io.IOException;
+
+import org.apache.solr.common.SolrDocument;
+
+/**
+ * New instance for each request
+ *
+ * @version $Id: JSONResponseWriter.java 1065304 2011-01-30 15:10:15Z rmuir $
+ */
+public abstract class DocTransformer
+{
+ public void setContext( TransformContext context ) {}
+ public abstract void transform(SolrDocument doc, int docid) throws IOException;
+}
Added: lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocTransformers.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocTransformers.java?rev=1085450&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocTransformers.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocTransformers.java Fri Mar 25 16:24:21 2011
@@ -0,0 +1,62 @@
+/**
+ * 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.response.transform;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.solr.common.SolrDocument;
+
+/**
+ * Transform a document before it gets sent out
+ *
+ * @version $Id: JSONResponseWriter.java 1065304 2011-01-30 15:10:15Z rmuir $
+ */
+public class DocTransformers extends DocTransformer
+{
+ final List<DocTransformer> children = new ArrayList<DocTransformer>();
+
+ public void addTransformer( DocTransformer a ) {
+ children.add( a );
+ }
+
+ public int size()
+ {
+ return children.size();
+ }
+
+ public DocTransformer getTransformer( int idx )
+ {
+ return children.get( idx );
+ }
+
+ @Override
+ public void setContext( TransformContext context ) {
+ for( DocTransformer a : children ) {
+ a.setContext( context );
+ }
+ }
+
+ @Override
+ public void transform(SolrDocument doc, int docid) throws IOException {
+ for( DocTransformer a : children ) {
+ a.transform( doc, docid );
+ }
+ }
+}
Added: lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocValuesAugmenter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocValuesAugmenter.java?rev=1085450&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocValuesAugmenter.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/DocValuesAugmenter.java Fri Mar 25 16:24:21 2011
@@ -0,0 +1,45 @@
+/**
+ * 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.response.transform;
+
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.search.function.DocValues;
+
+/**
+ * Add values from a ValueSource (function query etc)
+ *
+ * @version $Id: JSONResponseWriter.java 1065304 2011-01-30 15:10:15Z rmuir $
+ * @since solr 4.0
+ */
+public class DocValuesAugmenter extends DocTransformer
+{
+ final String name;
+ final DocValues values;
+
+ public DocValuesAugmenter( String name, DocValues values )
+ {
+ this.name = name;
+ this.values = values;
+ }
+
+ @Override
+ public void transform(SolrDocument doc, int docid) {
+ // TODO, should know what the real type is -- not always string
+ Object v = values.strVal( docid );
+ doc.setField( name, v );
+ }
+}
Added: lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/ExplainAugmenter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/ExplainAugmenter.java?rev=1085450&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/ExplainAugmenter.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/ExplainAugmenter.java Fri Mar 25 16:24:21 2011
@@ -0,0 +1,55 @@
+/**
+ * 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.response.transform;
+
+import java.io.IOException;
+
+import org.apache.lucene.search.Explanation;
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.util.SolrPluginUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Add query explain info directly to Document
+ *
+ * @version $Id: JSONResponseWriter.java 1065304 2011-01-30 15:10:15Z rmuir $
+ * @since solr 4.0
+ */
+public class ExplainAugmenter extends TransformerWithContext
+{
+ static final Logger log = LoggerFactory.getLogger( ExplainAugmenter.class );
+ final String name;
+
+ public ExplainAugmenter( String display )
+ {
+ this.name = display;
+ }
+
+ @Override
+ public void transform(SolrDocument doc, int docid) {
+ if( context != null && context.query != null ) {
+ try {
+ Explanation exp = context.searcher.explain(context.query, docid);
+ doc.setField( name, SolrPluginUtils.explanationToNamedList(exp) );
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
Added: lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/ScoreAugmenter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/ScoreAugmenter.java?rev=1085450&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/ScoreAugmenter.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/ScoreAugmenter.java Fri Mar 25 16:24:21 2011
@@ -0,0 +1,44 @@
+/**
+ * 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.response.transform;
+
+import org.apache.solr.common.SolrDocument;
+
+/**
+ * Simple Augmenter that adds the docId
+ *
+ * @version $Id: JSONResponseWriter.java 1065304 2011-01-30 15:10:15Z rmuir $
+ * @since solr 4.0
+ */
+public class ScoreAugmenter extends TransformerWithContext
+{
+ final String name;
+
+ public ScoreAugmenter( String display )
+ {
+ this.name = display;
+ }
+
+ @Override
+ public void transform(SolrDocument doc, int docid) {
+ if( context != null && context.wantsScores ) {
+ if( context.iterator != null ) {
+ doc.setField( name, context.iterator.score() );
+ }
+ }
+ }
+}
Added: lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/TransformContext.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/TransformContext.java?rev=1085450&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/TransformContext.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/TransformContext.java Fri Mar 25 16:24:21 2011
@@ -0,0 +1,35 @@
+/**
+ * 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.response.transform;
+
+import org.apache.lucene.search.Query;
+import org.apache.solr.search.DocIterator;
+import org.apache.solr.search.SolrIndexSearcher;
+
+/**
+ * Environment variables for the transformed documents
+ *
+ * @version $Id: JSONResponseWriter.java 1065304 2011-01-30 15:10:15Z rmuir $
+ * @since solr 4.0
+ */
+public class TransformContext
+{
+ public Query query;
+ public boolean wantsScores = false;
+ public DocIterator iterator;
+ public SolrIndexSearcher searcher;
+}
Added: lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/TransformerWithContext.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/TransformerWithContext.java?rev=1085450&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/TransformerWithContext.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/response/transform/TransformerWithContext.java Fri Mar 25 16:24:21 2011
@@ -0,0 +1,32 @@
+/**
+ * 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.response.transform;
+
+
+/**
+ * @version $Id: JSONResponseWriter.java 1065304 2011-01-30 15:10:15Z rmuir $
+ * @since solr 4.0
+ */
+public abstract class TransformerWithContext extends DocTransformer
+{
+ protected TransformContext context = null;
+
+ @Override
+ public void setContext( TransformContext context ) {
+ this.context = context;
+ }
+}