mirror of https://github.com/apache/lucene.git
SOLR-2444 -- moving ReturnFields to search package. Integrating yoniks basic parsing.
(should also fix regression) git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1085564 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ad221cb514
commit
e510d3f530
|
@ -47,7 +47,6 @@ import org.apache.solr.common.util.SimpleOrderedMap;
|
|||
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;
|
||||
|
@ -78,10 +77,10 @@ public class MoreLikeThisHandler extends RequestHandlerBase
|
|||
SolrParams params = req.getParams();
|
||||
|
||||
// Set field flags
|
||||
ReturnFields returnFields = ReturnFields.getReturnFields( req );
|
||||
ReturnFields returnFields = new ReturnFields( req );
|
||||
rsp.setReturnFields( returnFields );
|
||||
int flags = 0;
|
||||
if (returnFields.getWantsScore()) {
|
||||
if (returnFields.wantsScore()) {
|
||||
flags |= SolrIndexSearcher.GET_SCORES;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ 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;
|
||||
|
@ -75,10 +74,10 @@ public class QueryComponent extends SearchComponent
|
|||
SolrQueryResponse rsp = rb.rsp;
|
||||
|
||||
// Set field flags
|
||||
ReturnFields returnFields = ReturnFields.getReturnFields( req );
|
||||
ReturnFields returnFields = new ReturnFields( req );
|
||||
rsp.setReturnFields( returnFields );
|
||||
int flags = 0;
|
||||
if (returnFields.getWantsScore()) {
|
||||
if (returnFields.wantsScore()) {
|
||||
flags |= SolrIndexSearcher.GET_SCORES;
|
||||
}
|
||||
rb.setFieldFlags( flags );
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.solr.common.SolrInputDocument;
|
|||
import org.apache.solr.common.params.CommonParams;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.search.DocList;
|
||||
import org.apache.solr.search.ReturnFields;
|
||||
import org.apache.solr.search.SolrIndexSearcher;
|
||||
import org.apache.solr.search.DocIterator;
|
||||
import org.apache.solr.schema.FieldType;
|
||||
|
@ -156,7 +157,7 @@ public abstract class BaseResponseWriter {
|
|||
SolrDocument solrDoc = new SolrDocument();
|
||||
for (Fieldable f : doc.getFields()) {
|
||||
String fieldName = f.name();
|
||||
if (info.returnFields != null && !info.returnFields.contains(fieldName))
|
||||
if (info.returnFields != null && !info.returnFields.wantsField(fieldName))
|
||||
continue;
|
||||
SchemaField sf = info.schema.getFieldOrNull(fieldName);
|
||||
FieldType ft = null;
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.apache.solr.response.transform.DocTransformer;
|
|||
import org.apache.solr.response.transform.TransformContext;
|
||||
import org.apache.solr.schema.*;
|
||||
import org.apache.solr.search.DocList;
|
||||
import org.apache.solr.search.ReturnFields;
|
||||
import org.apache.solr.search.SolrIndexSearcher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -92,7 +93,7 @@ public class BinaryResponseWriter implements BinaryQueryResponseWriter {
|
|||
// 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 ) ) {
|
||||
if( !returnFields.wantsField( fname ) ) {
|
||||
doc.removeFields( fname );
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +107,7 @@ public class BinaryResponseWriter implements BinaryQueryResponseWriter {
|
|||
DocList ids = res.docs;
|
||||
TransformContext context = new TransformContext();
|
||||
context.query = res.query;
|
||||
context.wantsScores = returnFields.getWantsScore() && ids.hasScores();
|
||||
context.wantsScores = returnFields.wantsScore() && ids.hasScores();
|
||||
|
||||
int sz = ids.size();
|
||||
codec.writeTag(JavaBinCodec.ARR, sz);
|
||||
|
@ -119,7 +120,7 @@ public class BinaryResponseWriter implements BinaryQueryResponseWriter {
|
|||
transformer.setContext( context );
|
||||
}
|
||||
|
||||
Set<String> fnames = returnFields.getFieldNames();
|
||||
Set<String> fnames = returnFields.getLuceneFieldNames();
|
||||
context.iterator = ids.iterator();
|
||||
for (int i = 0; i < sz; i++) {
|
||||
int id = context.iterator.nextDoc();
|
||||
|
@ -137,7 +138,7 @@ public class BinaryResponseWriter implements BinaryQueryResponseWriter {
|
|||
|
||||
public void writeResults(ResultContext ctx, JavaBinCodec codec) throws IOException {
|
||||
codec.writeTag(JavaBinCodec.SOLRDOCLST);
|
||||
boolean wantsScores = returnFields.getWantsScore() && ctx.docs.hasScores();
|
||||
boolean wantsScores = returnFields.wantsScore() && ctx.docs.hasScores();
|
||||
List l = new ArrayList(3);
|
||||
l.add((long) ctx.docs.matches());
|
||||
l.add((long) ctx.docs.offset());
|
||||
|
@ -157,7 +158,7 @@ public class BinaryResponseWriter implements BinaryQueryResponseWriter {
|
|||
SolrDocument solrDoc = new SolrDocument();
|
||||
for (Fieldable f : doc.getFields()) {
|
||||
String fieldName = f.name();
|
||||
if( !returnFields.contains(fieldName) )
|
||||
if( !returnFields.wantsField(fieldName) )
|
||||
continue;
|
||||
SchemaField sf = schema.getFieldOrNull(fieldName);
|
||||
FieldType ft = null;
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.apache.solr.schema.SchemaField;
|
|||
import org.apache.solr.schema.StrField;
|
||||
import org.apache.solr.search.DocIterator;
|
||||
import org.apache.solr.search.DocList;
|
||||
import org.apache.solr.search.ReturnFields;
|
||||
import org.apache.solr.search.SolrIndexSearcher;
|
||||
|
||||
import java.io.CharArrayWriter;
|
||||
|
@ -235,7 +236,7 @@ class CSVWriter extends TextResponseWriter {
|
|||
// encapsulator will already be disabled if it wasn't specified
|
||||
}
|
||||
|
||||
Collection<String> fields = returnFields.getFieldNames();
|
||||
Collection<String> fields = returnFields.getLuceneFieldNames();
|
||||
Object responseObj = rsp.getValues().get("response");
|
||||
if (fields==null) {
|
||||
if (responseObj instanceof SolrDocumentList) {
|
||||
|
@ -248,7 +249,7 @@ class CSVWriter extends TextResponseWriter {
|
|||
// get the list of fields from the index
|
||||
fields = req.getSearcher().getFieldNames();
|
||||
}
|
||||
if (returnFields.getWantsScore()) {
|
||||
if (returnFields.wantsScore()) {
|
||||
fields.add("score");
|
||||
} else {
|
||||
fields.remove("score");
|
||||
|
|
|
@ -34,6 +34,7 @@ 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.search.ReturnFields;
|
||||
|
||||
/**
|
||||
* @version $Id$
|
||||
|
@ -321,7 +322,7 @@ class JSONWriter extends TextResponseWriter {
|
|||
|
||||
boolean first=true;
|
||||
for (String fname : doc.getFieldNames()) {
|
||||
if (!returnFields.contains(fname)) {
|
||||
if (!returnFields.wantsField(fname)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ 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.ReturnFields;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -113,7 +114,7 @@ class PHPSerializedWriter extends JSONWriter {
|
|||
LinkedHashMap <String,Object> multi = new LinkedHashMap<String, Object>();
|
||||
|
||||
for (String fname : doc.getFieldNames()) {
|
||||
if(!returnFields.contains(fname)){
|
||||
if(!returnFields.wantsField(fname)){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,168 +0,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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ package org.apache.solr.response;
|
|||
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||
import org.apache.solr.search.ReturnFields;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ 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 org.apache.solr.search.ReturnFields;
|
||||
|
||||
/** Base class for text-oriented response writers.
|
||||
*
|
||||
|
@ -230,7 +231,7 @@ public abstract class TextResponseWriter {
|
|||
DocList ids = res.docs;
|
||||
TransformContext context = new TransformContext();
|
||||
context.query = res.query;
|
||||
context.wantsScores = fields.getWantsScore() && ids.hasScores();
|
||||
context.wantsScores = fields.wantsScore() && ids.hasScores();
|
||||
writeStartDocumentList(name, ids.offset(), ids.size(), ids.matches(),
|
||||
context.wantsScores ? new Float(ids.maxScore()) : null );
|
||||
|
||||
|
@ -241,7 +242,7 @@ public abstract class TextResponseWriter {
|
|||
transformer.setContext( context );
|
||||
}
|
||||
int sz = ids.size();
|
||||
Set<String> fnames = fields.getFieldNames();
|
||||
Set<String> fnames = fields.getLuceneFieldNames();
|
||||
for (int i=0; i<sz; i++) {
|
||||
int id = context.iterator.nextDoc();
|
||||
Document doc = context.searcher.doc(id, fnames);
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.apache.solr.common.util.NamedList;
|
|||
import org.apache.solr.common.util.XML;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
import org.apache.solr.search.ReturnFields;
|
||||
|
||||
|
||||
public final class XMLWriter extends TextResponseWriter {
|
||||
|
@ -192,7 +193,7 @@ public final class XMLWriter extends TextResponseWriter {
|
|||
incLevel();
|
||||
|
||||
for (String fname : doc.getFieldNames()) {
|
||||
if (!returnFields.contains(fname)) {
|
||||
if (!returnFields.wantsField(fname)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.slf4j.LoggerFactory;
|
|||
*/
|
||||
public class ExplainAugmenter extends TransformerWithContext
|
||||
{
|
||||
static enum Style {
|
||||
public static enum Style {
|
||||
NL,
|
||||
TEXT,
|
||||
HTML
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* 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.common.util.NamedList;
|
||||
|
||||
/**
|
||||
* Return a field with a name that is different that what is indexed
|
||||
*
|
||||
* @version $Id: JSONResponseWriter.java 1065304 2011-01-30 15:10:15Z rmuir $
|
||||
* @since solr 4.0
|
||||
*/
|
||||
public class RenameFieldsTransformer extends DocTransformer
|
||||
{
|
||||
final NamedList<String> rename;
|
||||
|
||||
public RenameFieldsTransformer( NamedList<String> rename )
|
||||
{
|
||||
this.rename = rename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(SolrDocument doc, int docid) {
|
||||
for( int i=0; i<rename.size(); i++ ) {
|
||||
Object v = doc.remove( rename.getName(i) );
|
||||
if( v != null ) {
|
||||
doc.setField(rename.getVal(i), v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,29 +17,35 @@
|
|||
package org.apache.solr.response.transform;
|
||||
|
||||
import org.apache.solr.common.SolrDocument;
|
||||
import org.apache.solr.search.function.DocValues;
|
||||
import org.apache.solr.search.QParser;
|
||||
import org.apache.solr.search.function.ValueSource;
|
||||
|
||||
/**
|
||||
* Add values from a ValueSource (function query etc)
|
||||
*
|
||||
* NOT really sure how or if this could work...
|
||||
*
|
||||
* @version $Id: JSONResponseWriter.java 1065304 2011-01-30 15:10:15Z rmuir $
|
||||
* @since solr 4.0
|
||||
*/
|
||||
public class DocValuesAugmenter extends DocTransformer
|
||||
public class ValueSourceAugmenter extends DocTransformer
|
||||
{
|
||||
final String name;
|
||||
final DocValues values;
|
||||
public final String name;
|
||||
public final QParser qparser;
|
||||
public final ValueSource values;
|
||||
|
||||
public DocValuesAugmenter( String name, DocValues values )
|
||||
public ValueSourceAugmenter( String name, QParser qparser, ValueSource values )
|
||||
{
|
||||
this.name = name;
|
||||
this.qparser = qparser;
|
||||
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 );
|
||||
// how do we get to docvalues?
|
||||
Object v = "now what..."; //values.g.strVal( docid );
|
||||
doc.setField( name, v );
|
||||
}
|
||||
}
|
|
@ -582,7 +582,7 @@ public class QueryParsing {
|
|||
|
||||
boolean opt(char ch) {
|
||||
eatws();
|
||||
if (val.charAt(pos) == ch) {
|
||||
if (pos < end && val.charAt(pos) == ch) {
|
||||
pos++;
|
||||
return true;
|
||||
}
|
||||
|
@ -707,6 +707,28 @@ public class QueryParsing {
|
|||
return null;
|
||||
}
|
||||
|
||||
public String getGlobbedId(String errMessage) throws ParseException {
|
||||
eatws();
|
||||
int id_start = pos;
|
||||
char ch;
|
||||
if (pos < end && (ch = val.charAt(pos)) != '$' && (Character.isJavaIdentifierStart(ch) || ch=='?' || ch=='*')) {
|
||||
pos++;
|
||||
while (pos < end) {
|
||||
ch = val.charAt(pos);
|
||||
if (!(Character.isJavaIdentifierPart(ch) || ch=='?' || ch=='*') && ch != '.') {
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
return val.substring(id_start, pos);
|
||||
}
|
||||
|
||||
if (errMessage != null) {
|
||||
throw new ParseException(errMessage + " at pos " + pos + " str='" + val + "'");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips leading whitespace and returns whatever sequence of non
|
||||
* whitespace it can find (or hte empty string)
|
||||
|
|
|
@ -0,0 +1,362 @@
|
|||
/**
|
||||
* 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.search;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.lucene.queryParser.ParseException;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.params.CommonParams;
|
||||
import org.apache.solr.common.params.ShardParams;
|
||||
import org.apache.solr.common.params.SolrParams;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
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.RenameFieldsTransformer;
|
||||
import org.apache.solr.response.transform.ScoreAugmenter;
|
||||
import org.apache.solr.response.transform.ValueAugmenter;
|
||||
import org.apache.solr.response.transform.ValueSourceAugmenter;
|
||||
import org.apache.solr.search.function.FunctionQuery;
|
||||
import org.apache.solr.search.function.QueryValueSource;
|
||||
import org.apache.solr.search.function.ValueSource;
|
||||
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 );
|
||||
|
||||
// Special Field Keys
|
||||
public static final String SCORE = "score";
|
||||
// some special syntax for these guys?
|
||||
// Should these have factories... via plugin utils...
|
||||
public static final String DOCID = "_docid_";
|
||||
public static final String SHARD = "_shard_";
|
||||
public static final String EXPLAIN = "_explain_";
|
||||
|
||||
private final List<String> globs = new ArrayList<String>(1);
|
||||
private final Set<String> fields = new LinkedHashSet<String>(); // order is important for CSVResponseWriter
|
||||
private Set<String> okFieldNames = new HashSet<String>(); // Collection of everything that could match
|
||||
|
||||
private DocTransformer transformer;
|
||||
private boolean _wantsScore = false;
|
||||
private boolean _wantsAllFields = false;
|
||||
|
||||
public ReturnFields() {
|
||||
_wantsAllFields = true;
|
||||
}
|
||||
|
||||
public ReturnFields(SolrQueryRequest req) {
|
||||
this( req.getParams().get(CommonParams.FL), req );
|
||||
}
|
||||
|
||||
public ReturnFields(String fl, SolrQueryRequest req) {
|
||||
// this( (fl==null)?null:SolrPluginUtils.split(fl), req );
|
||||
if( fl == null ) {
|
||||
parseFieldList((String[])null, req);
|
||||
}
|
||||
else {
|
||||
if( fl.trim().length() == 0 ) {
|
||||
// legacy thing to support fl=' ' => fl=*,score!
|
||||
// maybe time to drop support for this?
|
||||
// See ConvertedLegacyTest
|
||||
_wantsScore = true;
|
||||
_wantsAllFields = true;
|
||||
transformer = new ScoreAugmenter(SCORE);
|
||||
}
|
||||
else {
|
||||
parseFieldList( new String[]{fl}, req);
|
||||
}
|
||||
}
|
||||
req.getCore().log.info("fields=" + fields + "\t globs="+globs + "\t transformer="+transformer); // nocommit
|
||||
}
|
||||
|
||||
public ReturnFields(String[] fl, SolrQueryRequest req) {
|
||||
parseFieldList(fl, req);
|
||||
req.getCore().log.info("fields=" + fields + "\t globs="+globs + "\t transformer="+transformer); // nocommit
|
||||
}
|
||||
|
||||
private void parseFieldList(String[] fl, SolrQueryRequest req) {
|
||||
_wantsScore = false;
|
||||
_wantsAllFields = false;
|
||||
if (fl == null || fl.length == 0 || fl.length == 1 && fl[0].length()==0) {
|
||||
_wantsAllFields = true;
|
||||
return;
|
||||
}
|
||||
|
||||
NamedList<String> rename = new NamedList<String>();
|
||||
DocTransformers augmenters = new DocTransformers();
|
||||
for (String fieldList : fl) {
|
||||
add(fieldList,rename,augmenters,req);
|
||||
}
|
||||
if( rename.size() > 0 ) {
|
||||
for( int i=0; i<rename.size(); i++ ) {
|
||||
okFieldNames.add( rename.getVal(i) );
|
||||
}
|
||||
augmenters.addTransformer( new RenameFieldsTransformer( rename ) );
|
||||
}
|
||||
|
||||
// Legacy behavior? "score" == "*,score" Distributed tests for this
|
||||
if( fields.size() == 1 && _wantsScore ) {
|
||||
_wantsAllFields = true;
|
||||
}
|
||||
|
||||
if( !_wantsAllFields ) {
|
||||
if( !globs.isEmpty() ) {
|
||||
// TODO??? need to fill up the fields with matching field names in the index
|
||||
// and add them to okFieldNames?
|
||||
// maybe just get all fields?
|
||||
// this would disable field selection optimization... i think thatis OK
|
||||
fields.clear(); // this will get all fields, and use wantsField to limit
|
||||
}
|
||||
okFieldNames.addAll( fields );
|
||||
}
|
||||
|
||||
if( augmenters.size() == 1 ) {
|
||||
transformer = augmenters.getTransformer(0);
|
||||
}
|
||||
else if( augmenters.size() > 1 ) {
|
||||
transformer = augmenters;
|
||||
}
|
||||
}
|
||||
|
||||
private void add(String fl, NamedList<String> rename, DocTransformers augmenters, SolrQueryRequest req) {
|
||||
if( fl == null ) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
QueryParsing.StrParser sp = new QueryParsing.StrParser(fl);
|
||||
|
||||
for(;;) {
|
||||
sp.opt(',');
|
||||
sp.eatws();
|
||||
if (sp.pos >= sp.end) break;
|
||||
|
||||
int start = sp.pos;
|
||||
|
||||
// short circuit test for a really simple field name
|
||||
String key = null;
|
||||
String field = sp.getId(null);
|
||||
char ch = sp.ch();
|
||||
|
||||
if (field != null) {
|
||||
if (sp.opt('=')) {
|
||||
// this was a key, not a field name
|
||||
key = field;
|
||||
field = null;
|
||||
sp.eatws();
|
||||
start = sp.pos;
|
||||
} else {
|
||||
if (ch==' ' || ch == ',' || ch==0) {
|
||||
String disp = (key==null) ? field : key;
|
||||
fields.add( field ); // need to put in the map to maintain order for things like CSVResponseWriter
|
||||
okFieldNames.add( field );
|
||||
okFieldNames.add( key );
|
||||
// a valid field name
|
||||
if(SCORE.equals(field)) {
|
||||
_wantsScore = true;
|
||||
augmenters.addTransformer( new ScoreAugmenter( disp ) );
|
||||
}
|
||||
else if( DOCID.equals( field ) ) {
|
||||
augmenters.addTransformer( new DocIdAugmenter( disp ) );
|
||||
}
|
||||
else if( SHARD.equals( field ) ) {
|
||||
String id = "TODO! getshardid???";
|
||||
augmenters.addTransformer( new ValueAugmenter( disp, id ) );
|
||||
}
|
||||
else if( EXPLAIN.equals( field ) ) {
|
||||
// TODO? pass params to transformers?
|
||||
augmenters.addTransformer( new ExplainAugmenter( disp, ExplainAugmenter.Style.NL ) );
|
||||
}
|
||||
else if( key != null ){
|
||||
rename.add(field, key);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// an invalid field name... reset the position pointer to retry
|
||||
sp.pos = start;
|
||||
field = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (field == null && sp.pos > start) {
|
||||
// if we are here, we must have read "key = "
|
||||
field = sp.getId(null);
|
||||
ch = sp.ch();
|
||||
if (field != null && (ch==' ' || ch == ',' || ch==0)) {
|
||||
rename.add(field, key);
|
||||
okFieldNames.add( field );
|
||||
okFieldNames.add( key );
|
||||
continue;
|
||||
}
|
||||
// an invalid field name... reset the position pointer to retry
|
||||
sp.pos = start;
|
||||
field = null;
|
||||
}
|
||||
|
||||
if (field == null) {
|
||||
// We didn't find a simple name, so let's see if it's a globbed field name.
|
||||
// Globbing only works with recommended field names.
|
||||
|
||||
field = sp.getGlobbedId(null);
|
||||
ch = sp.ch();
|
||||
if (field != null && (ch==' ' || ch == ',' || ch==0)) {
|
||||
// "*" looks and acts like a glob, but we give it special treatment
|
||||
if ("*".equals(field)) {
|
||||
_wantsAllFields = true;
|
||||
} else {
|
||||
globs.add(field);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// an invalid glob
|
||||
sp.pos = start;
|
||||
}
|
||||
|
||||
// let's try it as a function instead
|
||||
String funcStr = sp.val.substring(start);
|
||||
|
||||
QParser parser = QParser.getParser(funcStr, FunctionQParserPlugin.NAME, req);
|
||||
Query q = null;
|
||||
ValueSource vs = null;
|
||||
|
||||
try {
|
||||
if (parser instanceof FunctionQParser) {
|
||||
FunctionQParser fparser = (FunctionQParser)parser;
|
||||
fparser.setParseMultipleSources(false);
|
||||
fparser.setParseToEnd(false);
|
||||
|
||||
q = fparser.getQuery();
|
||||
|
||||
if (fparser.localParams != null) {
|
||||
if (fparser.valFollowedParams) {
|
||||
// need to find the end of the function query via the string parser
|
||||
int leftOver = fparser.sp.end - fparser.sp.pos;
|
||||
sp.pos = sp.end - leftOver; // reset our parser to the same amount of leftover
|
||||
} else {
|
||||
// the value was via the "v" param in localParams, so we need to find
|
||||
// the end of the local params themselves to pick up where we left off
|
||||
sp.pos = start + fparser.localParamsEnd;
|
||||
}
|
||||
} else {
|
||||
// need to find the end of the function query via the string parser
|
||||
int leftOver = fparser.sp.end - fparser.sp.pos;
|
||||
sp.pos = sp.end - leftOver; // reset our parser to the same amount of leftover
|
||||
}
|
||||
} else {
|
||||
// A QParser that's not for function queries.
|
||||
// It must have been specified via local params.
|
||||
q = parser.getQuery();
|
||||
|
||||
assert parser.getLocalParams() != null;
|
||||
sp.pos = start + parser.localParamsEnd;
|
||||
}
|
||||
|
||||
|
||||
if (q instanceof FunctionQuery) {
|
||||
vs = ((FunctionQuery)q).getValueSource();
|
||||
} else {
|
||||
vs = new QueryValueSource(q, 0.0f);
|
||||
}
|
||||
|
||||
if (key==null) {
|
||||
SolrParams localParams = parser.getLocalParams();
|
||||
if (localParams != null) {
|
||||
key = localParams.get("key");
|
||||
}
|
||||
if (key == null) {
|
||||
// use the function name itself as the field name
|
||||
key = sp.val.substring(start, sp.pos);
|
||||
}
|
||||
}
|
||||
|
||||
augmenters.addTransformer( new ValueSourceAugmenter( key, parser, vs ) );
|
||||
}
|
||||
catch (ParseException e) {
|
||||
// try again, simple rules for a field name with no whitespace
|
||||
sp.pos = start;
|
||||
field = sp.getSimpleString();
|
||||
|
||||
if (req.getSchema().getFieldOrNull(field) != null) {
|
||||
// OK, it was an oddly named field
|
||||
fields.add(field);
|
||||
if( key != null ) {
|
||||
rename.add(field, key);
|
||||
}
|
||||
} else {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Error parsing fieldname: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// end try as function
|
||||
|
||||
} // end for(;;)
|
||||
} catch (ParseException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Error parsing fieldname", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getLuceneFieldNames()
|
||||
{
|
||||
return (_wantsAllFields || fields.isEmpty()) ? null : fields;
|
||||
}
|
||||
|
||||
public boolean wantsAllFields()
|
||||
{
|
||||
return _wantsAllFields;
|
||||
}
|
||||
|
||||
public boolean wantsScore()
|
||||
{
|
||||
return _wantsScore;
|
||||
}
|
||||
|
||||
public boolean wantsField( String name )
|
||||
{
|
||||
if( _wantsAllFields || okFieldNames.contains( name ) ){
|
||||
return true;
|
||||
}
|
||||
for( String s : globs ) {
|
||||
// TODO something better?
|
||||
if( FilenameUtils.wildcardMatch( name, s ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public DocTransformer getTransformer()
|
||||
{
|
||||
return transformer;
|
||||
}
|
||||
}
|
|
@ -37,7 +37,6 @@ import org.apache.solr.handler.component.HighlightComponent;
|
|||
import org.apache.solr.handler.component.ResponseBuilder;
|
||||
import org.apache.solr.highlight.SolrHighlighter;
|
||||
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;
|
||||
|
@ -147,8 +146,8 @@ public class SolrPluginUtils {
|
|||
}
|
||||
|
||||
ReturnFields returnFields = res.getReturnFields();
|
||||
if(returnFields.getFieldNames() != null) {
|
||||
Set<String> fieldFilter = returnFields.getFieldNames();
|
||||
if(returnFields.getLuceneFieldNames() != null) {
|
||||
Set<String> fieldFilter = returnFields.getLuceneFieldNames();
|
||||
|
||||
if (rb.doHighlights) {
|
||||
// copy return fields list
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.apache.solr.common.SolrDocument;
|
|||
import org.apache.solr.common.SolrDocumentList;
|
||||
import org.apache.solr.common.util.DateUtil;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.search.ReturnFields;
|
||||
import org.junit.*;
|
||||
|
||||
import java.io.StringWriter;
|
||||
|
@ -128,19 +129,19 @@ public class TestCSVResponseWriter extends SolrTestCaseJ4 {
|
|||
rsp.add("response", sdl);
|
||||
QueryResponseWriter w = new CSVResponseWriter();
|
||||
|
||||
rsp.setReturnFields( ReturnFields.getReturnFields("id,foo_s", req) );
|
||||
rsp.setReturnFields( new ReturnFields("id,foo_s", req) );
|
||||
StringWriter buf = new StringWriter();
|
||||
w.write(buf, req, rsp);
|
||||
assertEquals("id,foo_s\n1,hi\n2,\n", buf.toString());
|
||||
|
||||
// try scores
|
||||
rsp.setReturnFields( ReturnFields.getReturnFields("id,score,foo_s", req) );
|
||||
rsp.setReturnFields( new ReturnFields("id,score,foo_s", req) );
|
||||
buf = new StringWriter();
|
||||
w.write(buf, req, rsp);
|
||||
assertEquals("id,score,foo_s\n1,2.718,hi\n2,89.83,\n", buf.toString());
|
||||
|
||||
// get field values from docs... should be ordered and not include score unless requested
|
||||
rsp.setReturnFields( ReturnFields.getReturnFields("*", req) );
|
||||
rsp.setReturnFields( new ReturnFields("*", req) );
|
||||
buf = new StringWriter();
|
||||
w.write(buf, req, rsp);
|
||||
assertEquals("id,foo_i,foo_s,foo_l,foo_b,foo_f,foo_d,foo_dt,v_ss,v2_ss\n" +
|
||||
|
@ -150,7 +151,7 @@ public class TestCSVResponseWriter extends SolrTestCaseJ4 {
|
|||
|
||||
|
||||
// get field values and scores - just check that the scores are there... we don't guarantee where
|
||||
rsp.setReturnFields( ReturnFields.getReturnFields("*,score", req) );
|
||||
rsp.setReturnFields( new ReturnFields("*,score", req) );
|
||||
buf = new StringWriter();
|
||||
w.write(buf, req, rsp);
|
||||
String s = buf.toString();
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package org.apache.solr.search;
|
||||
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.response.transform.ExplainAugmenter;
|
||||
import org.apache.solr.response.transform.ScoreAugmenter;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -49,4 +51,40 @@ public class TestSolrQueryParser extends SolrTestCaseJ4 {
|
|||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReturnFields() {
|
||||
ReturnFields rf = new ReturnFields( req("fl", "id,score") );
|
||||
assertTrue( rf.wantsScore() );
|
||||
assertTrue( rf.wantsField( "score" ) );
|
||||
assertTrue( rf.wantsField( "id" ) );
|
||||
assertFalse( rf.wantsField( "xxx" ) );
|
||||
assertTrue( rf.getTransformer() instanceof ScoreAugmenter );
|
||||
|
||||
rf = new ReturnFields( req("fl", "*") );
|
||||
assertFalse( rf.wantsScore() );
|
||||
assertTrue( rf.wantsField( "xxx" ) );
|
||||
assertTrue( rf.wantsAllFields() );
|
||||
assertNull( rf.getTransformer() );
|
||||
|
||||
rf = new ReturnFields( req("fl", "_explain_") );
|
||||
assertFalse( rf.wantsScore() );
|
||||
assertFalse( rf.wantsField( "id" ) );
|
||||
assertTrue( rf.getTransformer() instanceof ExplainAugmenter );
|
||||
|
||||
// Check that we want wildcards
|
||||
rf = new ReturnFields( req("fl", "id,aaa*,*bbb") );
|
||||
assertTrue( rf.wantsField( "id" ) );
|
||||
assertTrue( rf.wantsField( "aaaa" ) );
|
||||
assertTrue( rf.wantsField( "xxxbbb" ) );
|
||||
assertFalse( rf.wantsField( "aa" ) );
|
||||
assertFalse( rf.wantsField( "bb" ) );
|
||||
|
||||
|
||||
// From ConvertedLegacyTest, maybe we drop support?
|
||||
rf = new ReturnFields( req("fl", " ") );
|
||||
assertTrue( rf.wantsScore() );
|
||||
assertTrue( rf.wantsField( "xxx" ) );
|
||||
assertTrue( rf.wantsAllFields() );
|
||||
assertTrue( rf.getTransformer() instanceof ScoreAugmenter );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue