Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 61 additions & 4 deletions src/main/java/org/elasticsearch/index/query/SimpleQueryParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@
package org.elasticsearch.index.query;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

Expand Down Expand Up @@ -109,7 +114,7 @@ public Query newPhraseQuery(String text, int slop) {

/**
* Dispatches to Lucene's SimpleQueryParser's newPrefixQuery, optionally
* lowercasing the term first
* lowercasing the term first or trying to analyze terms
*/
@Override
public Query newPrefixQuery(String text) {
Expand All @@ -119,16 +124,59 @@ public Query newPrefixQuery(String text) {
BooleanQuery bq = new BooleanQuery(true);
for (Map.Entry<String,Float> entry : weights.entrySet()) {
try {
PrefixQuery prefix = new PrefixQuery(new Term(entry.getKey(), text));
prefix.setBoost(entry.getValue());
bq.add(prefix, BooleanClause.Occur.SHOULD);
if (settings.analyzeWildcard()) {
Query analyzedQuery = newPossiblyAnalyzedQuery(entry.getKey(), text);
analyzedQuery.setBoost(entry.getValue());
bq.add(analyzedQuery, BooleanClause.Occur.SHOULD);
} else {
PrefixQuery prefix = new PrefixQuery(new Term(entry.getKey(), text));
prefix.setBoost(entry.getValue());
bq.add(prefix, BooleanClause.Occur.SHOULD);
}
} catch (RuntimeException e) {
return rethrowUnlessLenient(e);
}
}
return super.simplify(bq);
}

private Query newPossiblyAnalyzedQuery(String field, String termStr) {
TokenStream source;
try {
source = getAnalyzer().tokenStream(field, termStr);
source.reset();
} catch (IOException e) {
return new PrefixQuery(new Term(field, termStr));
}
List<String> tlist = new ArrayList<>();
CharTermAttribute termAtt = source.addAttribute(CharTermAttribute.class);
while (true) {
try {
if (!source.incrementToken()) {
break;
}
} catch (IOException e) {
break;
}
tlist.add(termAtt.toString());
}
try {
source.close();
} catch (IOException e) {
// ignore
}
if (tlist.size() == 1) {
return new PrefixQuery(new Term(field, tlist.get(0)));
} else {
// build a boolean query with prefix on each one...
BooleanQuery bq = new BooleanQuery();
for (String token : tlist) {
bq.add(new BooleanClause(new PrefixQuery(new Term(field, token)), BooleanClause.Occur.SHOULD));
}
return bq;
}
}

/**
* Class encapsulating the settings for the SimpleQueryString query, with
* their default values
Expand All @@ -137,6 +185,7 @@ public static class Settings {
private Locale locale = Locale.ROOT;
private boolean lowercaseExpandedTerms = true;
private boolean lenient = false;
private boolean analyzeWildcard = false;

public Settings() {

Expand Down Expand Up @@ -165,5 +214,13 @@ public void lenient(boolean lenient) {
public boolean lenient() {
return this.lenient;
}

public void analyzeWildcard(boolean analyzeWildcard) {
this.analyzeWildcard = analyzeWildcard;
}

public boolean analyzeWildcard() {
return analyzeWildcard;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class SimpleQueryStringBuilder extends BaseQueryBuilder {
private int flags = -1;
private Boolean lowercaseExpandedTerms;
private Boolean lenient;
private Boolean analyzeWildcard;
private Locale locale;

/**
Expand Down Expand Up @@ -128,6 +129,11 @@ public SimpleQueryStringBuilder lenient(boolean lenient) {
return this;
}

public SimpleQueryStringBuilder analyzeWildcard(boolean analyzeWildcard) {
this.analyzeWildcard = analyzeWildcard;
return this;
}

@Override
public void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(SimpleQueryStringParser.NAME);
Expand Down Expand Up @@ -168,6 +174,10 @@ public void doXContent(XContentBuilder builder, Params params) throws IOExceptio
builder.field("lenient", lenient);
}

if (analyzeWildcard != null) {
builder.field("analyze_wildcard", analyzeWildcard);
}

if (locale != null) {
builder.field("locale", locale.toString());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ public Query parse(QueryParseContext parseContext) throws IOException, QueryPars
sqsSettings.lowercaseExpandedTerms(parser.booleanValue());
} else if ("lenient".equals(currentFieldName)) {
sqsSettings.lenient(parser.booleanValue());
} else if ("analyze_wildcard".equals(currentFieldName)) {
sqsSettings.analyzeWildcard(parser.booleanValue());
} else if ("_name".equals(currentFieldName)) {
queryName = parser.text();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

package org.elasticsearch.search.query;

import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.SimpleQueryStringBuilder;
import org.elasticsearch.index.query.SimpleQueryStringFlag;
Expand Down Expand Up @@ -266,4 +268,30 @@ public void testLenientFlagBeingTooLenient() throws Exception {
assertHitCount(resp, 1);
assertSearchHits(resp, "1");
}

@Test
public void testSimpleQueryStringAnalyzeWildcard() throws ExecutionException, InterruptedException, IOException {
String mapping = XContentFactory.jsonBuilder()
.startObject()
.startObject("type1")
.startObject("properties")
.startObject("location")
.field("type", "string")
.field("analyzer", "german")
.endObject()
.endObject()
.endObject()
.endObject().string();

CreateIndexRequestBuilder mappingRequest = client().admin().indices().prepareCreate("test1").addMapping("type1", mapping);
mappingRequest.execute().actionGet();
indexRandom(true, client().prepareIndex("test1", "type1", "1").setSource("location", "Köln"));
refresh();

SearchResponse searchResponse = client().prepareSearch().setQuery(simpleQueryString("Köln*").analyzeWildcard(true).field("location")).get();
assertNoFailures(searchResponse);
assertHitCount(searchResponse, 1l);
assertSearchHits(searchResponse, "1");
}

}