SOLR-446: TextResponseWriter can write SolrDocuments and SolrDocumentLists the same way it writes Document and DocList.

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@610156 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Ryan McKinley 2008-01-08 21:15:19 +00:00
parent 7c660c8526
commit a405feac80
4 changed files with 246 additions and 16 deletions

View File

@ -181,6 +181,10 @@ New Features
The jsp files /admin/get-file.jsp and /admin/raw-schema.jsp have been deprecated.
(ryan)
36. SOLR-446: TextResponseWriter can write SolrDocuments and SolrDocumentLists the
same way it writes Document and DocList. (yonik, ryan)
Changes in runtime behavior
Optimizations

View File

@ -19,6 +19,8 @@ package org.apache.solr.request;
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.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.schema.SchemaField;
@ -386,6 +388,47 @@ class JSONWriter extends TextResponseWriter {
writeMapCloser();
}
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...
incLevel();
boolean first=true;
for (String fname : doc.getFieldNames()) {
if (first) {
first=false;
}
else {
writeMapSeparator();
}
indent();
writeKey(fname, true);
Object val = doc.getFieldValue(fname);
if (val instanceof Collection) {
writeVal(fname, val);
} else {
// if multivalued field, write single value as an array
SchemaField sf = schema.getFieldOrNull(fname);
if (sf != null && sf.multiValued()) {
writeArrayOpener(-1); // no trivial way to determine array size
writeVal(fname, val);
writeArrayCloser();
}
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);
@ -457,6 +500,64 @@ class JSONWriter extends TextResponseWriter {
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);
writeInt(null,docs.getNumFound());
writeMapSeparator();
writeKey("start",false);
writeInt(null,docs.getStart());
if (includeScore) {
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);
}
decLevel();
writeArrayCloser();
if (otherFields !=null) {
writeMap(null, otherFields, true, false);
}
decLevel();
indent();
writeMapCloser();
}
//
// Data structure tokens
// NOTE: a positive size paramater indicates the number of elements

View File

@ -20,6 +20,8 @@ package org.apache.solr.request;
import org.apache.lucene.document.Document;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.FastWriter;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.search.DocList;
import java.io.IOException;
@ -131,6 +133,8 @@ public abstract class TextResponseWriter {
writeDouble(name, ((Double)val).doubleValue());
} else if (val instanceof Document) {
writeDoc(name, (Document)val, returnFields, 0.0f, false);
} else if (val instanceof SolrDocument) {
writeSolrDocument(name, (SolrDocument)val, returnFields, null);
} else if (val instanceof DocList) {
// requires access to IndexReader
writeDocList(name, (DocList)val, returnFields,null);
@ -139,6 +143,8 @@ public abstract class TextResponseWriter {
// 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);
} else if (val instanceof Map) {
writeMap(name, (Map)val, false, true);
} else if (val instanceof NamedList) {
@ -161,8 +167,18 @@ public abstract class TextResponseWriter {
public abstract void writeDoc(String name, Document doc, Set<String> returnFields, float score, boolean includeScore) 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 writeStr(String name, String val, boolean needsEscaping) throws IOException;
public abstract void writeMap(String name, Map val, boolean excludeOuter, boolean isFirstVal) throws IOException;

View File

@ -17,6 +17,8 @@
package org.apache.solr.request;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.XML;
import org.apache.solr.search.SolrIndexSearcher;
@ -333,7 +335,56 @@ final public class XMLWriter {
writer.write("</doc>");
}
public final void writeDocList(String name, DocList ids, Set<String> fields) throws IOException {
/**
* @since solr 1.3
*/
final void writeDoc(String name, SolrDocument doc, Set<String> returnFields, boolean includeScore) throws IOException {
startTag("doc", name, false);
incLevel();
if (includeScore) {
writeVal("score", doc.getFirstValue("score"));
}
for (String fname : doc.getFieldNames()) {
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 (version>=2100 && sf!=null && sf.multiValued()) {
startTag("arr",fname,false);
doIndent=false;
writeVal(fname, val);
writer.write("</arr>");
doIndent=defaultIndent;
} else {
writeVal(fname, val);
}
}
}
decLevel();
if (doIndent) indent();
writer.write("</doc>");
}
private static interface DocumentListInfo {
Float getMaxScore();
int getCount();
int getNumFound();
int getStart();
void writeDocs( boolean includeScore, Set<String> fields ) throws IOException;
}
private final void writeDocuments(
String name,
DocumentListInfo docs,
Set<String> fields) throws IOException
{
boolean includeScore=false;
if (fields!=null) {
includeScore = fields.contains("score");
@ -342,15 +393,15 @@ final public class XMLWriter {
}
}
int sz=ids.size();
int sz=docs.getCount();
if (doIndent) indent();
writer.write("<result");
writeAttr("name",name);
writeAttr("numFound",Integer.toString(ids.matches()));
writeAttr("start",Integer.toString(ids.offset()));
if (includeScore) {
writeAttr("maxScore",Float.toString(ids.maxScore()));
writeAttr("numFound",Integer.toString(docs.getNumFound())); // TODO: change to long
writeAttr("start",Integer.toString(docs.getStart())); // TODO: change to long
if (includeScore && docs.getMaxScore()!=null) {
writeAttr("maxScore",Float.toString(docs.getMaxScore()));
}
if (sz==0) {
writer.write("/>");
@ -360,17 +411,72 @@ final public class XMLWriter {
}
incLevel();
docs.writeDocs(includeScore, fields);
decLevel();
if (doIndent) indent();
writer.write("</result>");
}
public final void writeSolrDocumentList(String name, final SolrDocumentList docs, Set<String> fields) throws IOException
{
this.writeDocuments( name, new DocumentListInfo()
{
public int getCount() {
return docs.size();
}
public Float getMaxScore() {
return docs.getMaxScore();
}
public int getNumFound() {
return docs.getNumFound();
}
public int getStart() {
return docs.getStart();
}
public void writeDocs(boolean includeScore, Set<String> fields) throws IOException {
for( SolrDocument doc : docs ) {
writeDoc(null, doc, fields, includeScore);
}
}
}, fields );
}
public final void writeDocList(String name, final DocList ids, Set<String> fields) throws IOException
{
this.writeDocuments( name, new DocumentListInfo()
{
public int getCount() {
return ids.size();
}
public Float getMaxScore() {
return ids.maxScore();
}
public int getNumFound() {
return ids.matches();
}
public int getStart() {
return ids.offset();
}
public void writeDocs(boolean includeScore, Set<String> fields) throws IOException {
SolrIndexSearcher searcher = request.getSearcher();
DocIterator iterator = ids.iterator();
int sz = ids.size();
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);
}
decLevel();
if (doIndent) indent();
writer.write("</result>");
}
}, fields );
}
@ -405,7 +511,10 @@ final public class XMLWriter {
} else if (val instanceof DocList) {
// requires access to IndexReader
writeDocList(name, (DocList)val, defaultFieldList);
} else if (val instanceof DocSet) {
}else if (val instanceof SolrDocumentList) {
// requires access to IndexReader
writeSolrDocumentList(name, (SolrDocumentList)val, defaultFieldList);
}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...?