Query DSL: Allow to provide pattern field names when using query_string query, closes #511.
This commit is contained in:
parent
6839cc6965
commit
38d77f8cf3
|
@ -29,6 +29,13 @@ import java.util.regex.Pattern;
|
|||
*/
|
||||
public class Regex {
|
||||
|
||||
/**
|
||||
* Is the str a simple match pattern.
|
||||
*/
|
||||
public static boolean isSimpleMatchPattern(String str) {
|
||||
return str.indexOf('*') != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match a String against the given pattern, supporting the following simple
|
||||
* pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy" matches (with an
|
||||
|
|
|
@ -20,14 +20,13 @@
|
|||
package org.elasticsearch.index.mapper;
|
||||
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.elasticsearch.common.collect.ImmutableList;
|
||||
import org.elasticsearch.common.collect.ImmutableMap;
|
||||
import org.elasticsearch.common.collect.Iterables;
|
||||
import org.elasticsearch.common.collect.UnmodifiableIterator;
|
||||
import org.elasticsearch.common.collect.*;
|
||||
import org.elasticsearch.common.regex.Regex;
|
||||
import org.elasticsearch.common.util.concurrent.Immutable;
|
||||
import org.elasticsearch.index.analysis.FieldNameAnalyzer;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.common.collect.Lists.*;
|
||||
import static org.elasticsearch.common.collect.Maps.*;
|
||||
|
@ -119,6 +118,20 @@ public class DocumentFieldMappers implements Iterable<FieldMapper> {
|
|||
return fullNameFieldMappers.get(fullName);
|
||||
}
|
||||
|
||||
public Set<String> simpleMatchToIndexNames(String pattern) {
|
||||
Set<String> fields = Sets.newHashSet();
|
||||
for (FieldMapper fieldMapper : fieldMappers) {
|
||||
if (Regex.simpleMatch(pattern, fieldMapper.names().fullName())) {
|
||||
fields.add(fieldMapper.names().indexName());
|
||||
} else if (Regex.simpleMatch(pattern, fieldMapper.names().indexName())) {
|
||||
fields.add(fieldMapper.names().name());
|
||||
} else if (Regex.simpleMatch(pattern, fieldMapper.names().name())) {
|
||||
fields.add(fieldMapper.names().indexName());
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to find first based on {@link #fullName(String)}, then by {@link #indexName(String)}, and last
|
||||
* by {@link #name(String)}.
|
||||
|
|
|
@ -26,9 +26,11 @@ import org.apache.lucene.index.Term;
|
|||
import org.apache.lucene.search.Filter;
|
||||
import org.apache.lucene.search.TermsFilter;
|
||||
import org.elasticsearch.common.collect.ImmutableMap;
|
||||
import org.elasticsearch.common.collect.Sets;
|
||||
import org.elasticsearch.common.collect.UnmodifiableIterator;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.io.Streams;
|
||||
import org.elasticsearch.common.regex.Regex;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadSafe;
|
||||
import org.elasticsearch.env.Environment;
|
||||
|
@ -46,6 +48,8 @@ import java.io.InputStreamReader;
|
|||
import java.io.Reader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.common.collect.MapBuilder.*;
|
||||
|
||||
|
@ -280,6 +284,44 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
|
|||
return null;
|
||||
}
|
||||
|
||||
public Set<String> simpleMatchToIndexNames(String pattern) {
|
||||
int dotIndex = pattern.indexOf('.');
|
||||
if (dotIndex != -1) {
|
||||
String possibleType = pattern.substring(0, dotIndex);
|
||||
DocumentMapper possibleDocMapper = mappers.get(possibleType);
|
||||
if (possibleDocMapper != null) {
|
||||
Set<String> typedFields = Sets.newHashSet();
|
||||
for (String indexName : possibleDocMapper.mappers().simpleMatchToIndexNames(pattern)) {
|
||||
typedFields.add(possibleType + "." + indexName);
|
||||
}
|
||||
return typedFields;
|
||||
}
|
||||
}
|
||||
Set<String> fields = Sets.newHashSet();
|
||||
for (Map.Entry<String, FieldMappers> entry : fullNameFieldMappers.entrySet()) {
|
||||
if (Regex.simpleMatch(pattern, entry.getKey())) {
|
||||
for (FieldMapper mapper : entry.getValue()) {
|
||||
fields.add(mapper.names().indexName());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, FieldMappers> entry : indexNameFieldMappers.entrySet()) {
|
||||
if (Regex.simpleMatch(pattern, entry.getKey())) {
|
||||
for (FieldMapper mapper : entry.getValue()) {
|
||||
fields.add(mapper.names().indexName());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, FieldMappers> entry : nameFieldMappers.entrySet()) {
|
||||
if (Regex.simpleMatch(pattern, entry.getKey())) {
|
||||
for (FieldMapper mapper : entry.getValue()) {
|
||||
fields.add(mapper.names().indexName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #smartName(String)}, except it returns just the field mappers.
|
||||
*/
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.cache.query.parser.QueryParserCache;
|
|||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.collect.Lists;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.regex.Regex;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.trove.ExtTObjectFloatHashMap;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
@ -95,12 +96,25 @@ public class QueryStringQueryParser extends AbstractIndexComponent implements XC
|
|||
if (qpSettings.fields() == null) {
|
||||
qpSettings.fields(Lists.<String>newArrayList());
|
||||
}
|
||||
qpSettings.fields().add(fField);
|
||||
if (fBoost != -1) {
|
||||
if (qpSettings.boosts() == null) {
|
||||
qpSettings.boosts(new ExtTObjectFloatHashMap<String>().defaultReturnValue(1.0f));
|
||||
|
||||
if (Regex.isSimpleMatchPattern(fField)) {
|
||||
for (String field : parseContext.mapperService().simpleMatchToIndexNames(fField)) {
|
||||
qpSettings.fields().add(field);
|
||||
if (fBoost != -1) {
|
||||
if (qpSettings.boosts() == null) {
|
||||
qpSettings.boosts(new ExtTObjectFloatHashMap<String>().defaultReturnValue(1.0f));
|
||||
}
|
||||
qpSettings.boosts().put(field, fBoost);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qpSettings.fields().add(fField);
|
||||
if (fBoost != -1) {
|
||||
if (qpSettings.boosts() == null) {
|
||||
qpSettings.boosts(new ExtTObjectFloatHashMap<String>().defaultReturnValue(1.0f));
|
||||
}
|
||||
qpSettings.boosts().put(fField, fBoost);
|
||||
}
|
||||
qpSettings.boosts().put(fField, fBoost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,6 +140,17 @@ public class SimpleIndexQueryParserTests {
|
|||
assertThat(((TermQuery) bQuery.clauses().get(1).getQuery()).getTerm(), equalTo(new Term("name", "test")));
|
||||
}
|
||||
|
||||
@Test public void testQueryStringFieldsMatch() throws Exception {
|
||||
IndexQueryParser queryParser = queryParser();
|
||||
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/xcontent/query-fields-match.json");
|
||||
Query parsedQuery = queryParser.parse(query).query();
|
||||
assertThat(parsedQuery, instanceOf(BooleanQuery.class));
|
||||
BooleanQuery bQuery = (BooleanQuery) parsedQuery;
|
||||
assertThat(bQuery.clauses().size(), equalTo(2));
|
||||
assertThat(((TermQuery) bQuery.clauses().get(0).getQuery()).getTerm(), equalTo(new Term("name.first", "test")));
|
||||
assertThat(((TermQuery) bQuery.clauses().get(1).getQuery()).getTerm(), equalTo(new Term("name.last", "test")));
|
||||
}
|
||||
|
||||
@Test public void testQueryStringFields2Builder() throws Exception {
|
||||
IndexQueryParser queryParser = queryParser();
|
||||
Query parsedQuery = queryParser.parse(queryString("test").field("content").field("name").useDisMax(true)).query();
|
||||
|
@ -400,7 +411,7 @@ public class SimpleIndexQueryParserTests {
|
|||
|
||||
@Test public void testPrefixFilteredQueryBuilder() throws IOException {
|
||||
IndexQueryParser queryParser = queryParser();
|
||||
Query parsedQuery = queryParser.parse(filtered(termQuery("name.first", "shay"), prefixFilter("name.first", "sh"))).query();
|
||||
Query parsedQuery = queryParser.parse(filteredQuery(termQuery("name.first", "shay"), prefixFilter("name.first", "sh"))).query();
|
||||
assertThat(parsedQuery, instanceOf(FilteredQuery.class));
|
||||
FilteredQuery filteredQuery = (FilteredQuery) parsedQuery;
|
||||
PrefixFilter prefixFilter = (PrefixFilter) filteredQuery.getFilter();
|
||||
|
@ -507,7 +518,7 @@ public class SimpleIndexQueryParserTests {
|
|||
|
||||
@Test public void testRangeFilteredQueryBuilder() throws IOException {
|
||||
IndexQueryParser queryParser = queryParser();
|
||||
Query parsedQuery = queryParser.parse(filtered(termQuery("name.first", "shay"), rangeFilter("age").from(23).to(54).includeLower(true).includeUpper(false))).query();
|
||||
Query parsedQuery = queryParser.parse(filteredQuery(termQuery("name.first", "shay"), rangeFilter("age").from(23).to(54).includeLower(true).includeUpper(false))).query();
|
||||
// since age is automatically registered in data, we encode it as numeric
|
||||
assertThat(parsedQuery, instanceOf(FilteredQuery.class));
|
||||
Filter filter = ((FilteredQuery) parsedQuery).getFilter();
|
||||
|
@ -554,7 +565,7 @@ public class SimpleIndexQueryParserTests {
|
|||
|
||||
@Test public void testNumericRangeFilteredQueryBuilder() throws IOException {
|
||||
IndexQueryParser queryParser = queryParser();
|
||||
Query parsedQuery = queryParser.parse(filtered(termQuery("name.first", "shay"), numericRangeFilter("age").from(23).to(54).includeLower(true).includeUpper(false))).query();
|
||||
Query parsedQuery = queryParser.parse(filteredQuery(termQuery("name.first", "shay"), numericRangeFilter("age").from(23).to(54).includeLower(true).includeUpper(false))).query();
|
||||
assertThat(parsedQuery, instanceOf(FilteredQuery.class));
|
||||
Filter filter = ((FilteredQuery) parsedQuery).getFilter();
|
||||
assertThat(filter, instanceOf(NumericRangeFieldDataFilter.class));
|
||||
|
@ -594,7 +605,7 @@ public class SimpleIndexQueryParserTests {
|
|||
|
||||
@Test public void testAndFilteredQueryBuilder() throws IOException {
|
||||
IndexQueryParser queryParser = queryParser();
|
||||
Query parsedQuery = queryParser.parse(filtered(matchAllQuery(), andFilter(termFilter("name.first", "shay1"), termFilter("name.first", "shay4")))).query();
|
||||
Query parsedQuery = queryParser.parse(filteredQuery(matchAllQuery(), andFilter(termFilter("name.first", "shay1"), termFilter("name.first", "shay4")))).query();
|
||||
assertThat(parsedQuery, instanceOf(FilteredQuery.class));
|
||||
FilteredQuery filteredQuery = (FilteredQuery) parsedQuery;
|
||||
|
||||
|
@ -646,7 +657,7 @@ public class SimpleIndexQueryParserTests {
|
|||
|
||||
@Test public void testOrFilteredQueryBuilder() throws IOException {
|
||||
IndexQueryParser queryParser = queryParser();
|
||||
Query parsedQuery = queryParser.parse(filtered(matchAllQuery(), orFilter(termFilter("name.first", "shay1"), termFilter("name.first", "shay4")))).query();
|
||||
Query parsedQuery = queryParser.parse(filteredQuery(matchAllQuery(), orFilter(termFilter("name.first", "shay1"), termFilter("name.first", "shay4")))).query();
|
||||
assertThat(parsedQuery, instanceOf(FilteredQuery.class));
|
||||
FilteredQuery filteredQuery = (FilteredQuery) parsedQuery;
|
||||
|
||||
|
@ -684,7 +695,7 @@ public class SimpleIndexQueryParserTests {
|
|||
|
||||
@Test public void testNotFilteredQueryBuilder() throws IOException {
|
||||
IndexQueryParser queryParser = queryParser();
|
||||
Query parsedQuery = queryParser.parse(filtered(matchAllQuery(), notFilter(termFilter("name.first", "shay1")))).query();
|
||||
Query parsedQuery = queryParser.parse(filteredQuery(matchAllQuery(), notFilter(termFilter("name.first", "shay1")))).query();
|
||||
assertThat(parsedQuery, instanceOf(FilteredQuery.class));
|
||||
FilteredQuery filteredQuery = (FilteredQuery) parsedQuery;
|
||||
|
||||
|
@ -751,7 +762,7 @@ public class SimpleIndexQueryParserTests {
|
|||
|
||||
@Test public void testFilteredQueryBuilder() throws IOException {
|
||||
IndexQueryParser queryParser = queryParser();
|
||||
Query parsedQuery = queryParser.parse(filtered(termQuery("name.first", "shay"), termFilter("name.last", "banon"))).query();
|
||||
Query parsedQuery = queryParser.parse(filteredQuery(termQuery("name.first", "shay"), termFilter("name.last", "banon"))).query();
|
||||
assertThat(parsedQuery, instanceOf(FilteredQuery.class));
|
||||
FilteredQuery filteredQuery = (FilteredQuery) parsedQuery;
|
||||
assertThat(((TermQuery) filteredQuery.getQuery()).getTerm(), equalTo(new Term("name.first", "shay")));
|
||||
|
@ -834,7 +845,7 @@ public class SimpleIndexQueryParserTests {
|
|||
|
||||
@Test public void testTermsFilterQueryBuilder() throws Exception {
|
||||
IndexQueryParser queryParser = queryParser();
|
||||
Query parsedQuery = queryParser.parse(filtered(termQuery("name.first", "shay"), termsFilter("name.last", "banon", "kimchy"))).query();
|
||||
Query parsedQuery = queryParser.parse(filteredQuery(termQuery("name.first", "shay"), termsFilter("name.last", "banon", "kimchy"))).query();
|
||||
assertThat(parsedQuery, instanceOf(FilteredQuery.class));
|
||||
FilteredQuery filteredQuery = (FilteredQuery) parsedQuery;
|
||||
assertThat(filteredQuery.getFilter(), instanceOf(TermsFilter.class));
|
||||
|
@ -1037,7 +1048,7 @@ public class SimpleIndexQueryParserTests {
|
|||
|
||||
@Test public void testQueryFilterBuilder() throws Exception {
|
||||
IndexQueryParser queryParser = queryParser();
|
||||
Query parsedQuery = queryParser.parse(filtered(termQuery("name.first", "shay"), queryFilter(termQuery("name.last", "banon")))).query();
|
||||
Query parsedQuery = queryParser.parse(filteredQuery(termQuery("name.first", "shay"), queryFilter(termQuery("name.last", "banon")))).query();
|
||||
assertThat(parsedQuery, instanceOf(FilteredQuery.class));
|
||||
FilteredQuery filteredQuery = (FilteredQuery) parsedQuery;
|
||||
QueryWrapperFilter queryWrapperFilter = (QueryWrapperFilter) filteredQuery.getFilter();
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
query_string : {
|
||||
fields : ["name.*"],
|
||||
use_dis_max : false,
|
||||
query: "test"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue