Fail will IAE if a numeric field is used for the anaysis endpoint.

Analysing a numeric field will return UTF-16 representations of
of Lucenes numeric prefix terms. Those terms are meaningless in general
unless used for lookups in the lucene index. Passing a numeric field
to the analysis action is most likely a bug.

Closes #2953 #2952
This commit is contained in:
Simon Willnauer 2013-04-30 13:39:56 +02:00
parent 8c6ba59b83
commit 773ea0306b
6 changed files with 55 additions and 8 deletions

View File

@ -124,10 +124,14 @@ public class TransportAnalyzeAction extends TransportSingleCustomOperationAction
if (indexService == null) {
throw new ElasticSearchIllegalArgumentException("No index provided, and trying to analyzer based on a specific field which requires the index parameter");
}
FieldMapper fieldMapper = indexService.mapperService().smartNameFieldMapper(request.field());
FieldMapper<?> fieldMapper = indexService.mapperService().smartNameFieldMapper(request.field());
if (fieldMapper != null) {
if (fieldMapper.isNumeric()) {
throw new ElasticSearchIllegalArgumentException("Can't process field [" + request.field() + "], Analysis requests are not supported on numeric fields");
}
analyzer = fieldMapper.indexAnalyzer();
field = fieldMapper.names().indexName();
}
}
if (field == null) {

View File

@ -31,26 +31,22 @@ import java.io.Reader;
public abstract class NumericTokenizer extends Tokenizer {
private final NumericTokenStream numericTokenStream;
private final char[] buffer;
protected final Object extra;
protected NumericTokenizer(Reader reader, NumericTokenStream numericTokenStream, Object extra) throws IOException {
super(numericTokenStream, reader);
this.numericTokenStream = numericTokenStream;
this.extra = extra;
reset();
this(reader, numericTokenStream, new char[32], extra);
}
protected NumericTokenizer(Reader reader, NumericTokenStream numericTokenStream, char[] buffer, Object extra) throws IOException {
super(numericTokenStream, reader);
this.numericTokenStream = numericTokenStream;
this.extra = extra;
reset(buffer);
this.buffer = buffer;
}
@Override
public void reset() throws IOException {
char[] buffer = new char[32];
reset(buffer);
}

View File

@ -200,4 +200,6 @@ public interface FieldMapper<T> {
FieldDataType fieldDataType();
PostingsFormatProvider postingsFormatProvider();
boolean isNumeric();
}

View File

@ -706,4 +706,9 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T>, Mapper {
// nothing to do here, sub classes to override if needed
}
@Override
public boolean isNumeric() {
return false;
}
}

View File

@ -288,4 +288,9 @@ public abstract class NumberFieldMapper<T extends Number> extends AbstractFieldM
builder.field("ignore_malformed", ignoreMalformed.value());
}
}
@Override
public boolean isNumeric() {
return true;
}
}

View File

@ -19,10 +19,17 @@
package org.elasticsearch.test.integration.indices.analyze;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequestBuilder;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.Priority;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.test.integration.AbstractNodesTests;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
@ -75,6 +82,34 @@ public class AnalyzeActionTests extends AbstractNodesTests {
assertThat(token.getEndOffset(), equalTo(14));
}
}
@Test
public void analyzeNumericField() throws ElasticSearchException, IOException {
try {
client.admin().indices().prepareDelete("test").execute().actionGet();
} catch (Exception e) {
// ignore
}
client.admin().indices().prepareCreate("test").execute().actionGet();
client.admin().cluster().prepareHealth().setWaitForEvents(Priority.LANGUID).setWaitForGreenStatus().execute().actionGet();
client.prepareIndex("test", "test", "1")
.setSource(XContentFactory.jsonBuilder()
.startObject()
.field("long", 1l)
.field("double", 1.0d)
.endObject())
.setRefresh(true).execute().actionGet();
try {
client.admin().indices().prepareAnalyze("test", "123").setField("long").execute().actionGet();
} catch (ElasticSearchIllegalArgumentException ex) {
}
try {
client.admin().indices().prepareAnalyze("test", "123.0").setField("double").execute().actionGet();
} catch (ElasticSearchIllegalArgumentException ex) {
}
}
@Test
public void analyzeWithNoIndex() throws Exception {