فهرست منبع

allow no query is defined in function score, default is match all

Britta Weber 12 سال پیش
والد
کامیت
f12fa0c1c4

+ 18 - 0
src/main/java/org/elasticsearch/index/query/QueryBuilders.java

@@ -550,6 +550,24 @@ public abstract class QueryBuilders {
     public static FunctionScoreQueryBuilder functionScoreQuery(QueryBuilder queryBuilder) {
         return new FunctionScoreQueryBuilder(queryBuilder);
     }
+    
+    /**
+     * A query that allows to define a custom scoring function.
+     * 
+     */
+    public static FunctionScoreQueryBuilder functionScoreQuery() {
+        return new FunctionScoreQueryBuilder();
+    }
+    
+    /**
+     * A query that allows to define a custom scoring function.
+     *
+     * @param filterBuilder The filterBuilder to custom score
+     */
+    public static FunctionScoreQueryBuilder functionScoreQuery(ScoreFunctionBuilder function) {
+        return new FunctionScoreQueryBuilder(function);
+    }
+    
     /**
      * A query that allows to define a custom scoring function.
      *

+ 13 - 5
src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilder.java

@@ -19,7 +19,6 @@
 
 package org.elasticsearch.index.query.functionscore;
 
-import org.elasticsearch.ElasticSearchException;
 import org.elasticsearch.common.lucene.search.function.CombineFunction;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.index.query.BaseQueryBuilder;
@@ -61,6 +60,18 @@ public class FunctionScoreQueryBuilder extends BaseQueryBuilder implements Boost
         this.queryBuilder = null;
     }
 
+    public FunctionScoreQueryBuilder() {
+        this.filterBuilder = null;
+        this.queryBuilder = null;
+    }
+
+    public FunctionScoreQueryBuilder(ScoreFunctionBuilder scoreFunctionBuilder) {
+        queryBuilder = null;
+        filterBuilder = null;
+        this.filters.add(null);
+        this.scoreFunctions.add(scoreFunctionBuilder);
+    }
+
     public FunctionScoreQueryBuilder add(FilterBuilder filter, ScoreFunctionBuilder scoreFunctionBuilder) {
         this.filters.add(filter);
         this.scoreFunctions.add(scoreFunctionBuilder);
@@ -112,10 +123,7 @@ public class FunctionScoreQueryBuilder extends BaseQueryBuilder implements Boost
         } else if (filterBuilder != null) {
             builder.field("filter");
             filterBuilder.toXContent(builder, params);
-        } else {
-            throw new ElasticSearchException(FunctionScoreQueryParser.NAME
-                    + " builder requires that either a filter or a query is defined!");
-        }
+        } 
         // If there is only one function without a filter, we later want to
         // create a FunctionScoreQuery.
         // For this, we only build the scoreFunction.Tthis will be translated to

+ 3 - 3
src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryParser.java

@@ -23,7 +23,7 @@ import org.apache.lucene.search.Filter;
 import org.apache.lucene.search.Query;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.inject.Inject;
-import org.elasticsearch.common.lucene.search.MatchAllDocsFilter;
+import org.elasticsearch.common.lucene.search.Queries;
 import org.elasticsearch.common.lucene.search.XConstantScoreQuery;
 import org.elasticsearch.common.lucene.search.function.CombineFunction;
 import org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery;
@@ -95,7 +95,7 @@ public class FunctionScoreQueryParser implements QueryParser {
             }
         }
         if (query == null) {
-            throw new QueryParsingException(parseContext.index(), NAME + " requires 'query' field");
+            query = Queries.newMatchAllQuery();
         }
         // if all filter elements returned null, just use the query
         if (filterFunctions.isEmpty()) {
@@ -150,7 +150,7 @@ public class FunctionScoreQueryParser implements QueryParser {
                 }
             }
             if (filter == null) {
-                filter = new MatchAllDocsFilter();
+                filter = Queries.MATCH_ALL_FILTER;
             }
             filterFunctions.add(new FiltersFunctionScoreQuery.FilterFunction(filter, scoreFunction));
 

+ 12 - 1
src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java

@@ -32,6 +32,7 @@ import org.apache.lucene.search.spans.*;
 import org.apache.lucene.spatial.prefix.IntersectsPrefixTreeFilter;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.NumericUtils;
+import org.elasticsearch.ElasticsearchTestCase;
 import org.elasticsearch.cache.recycler.CacheRecyclerModule;
 import org.elasticsearch.cluster.ClusterService;
 import org.elasticsearch.common.bytes.BytesArray;
@@ -63,7 +64,6 @@ import org.elasticsearch.index.settings.IndexSettingsModule;
 import org.elasticsearch.index.similarity.SimilarityModule;
 import org.elasticsearch.indices.query.IndicesQueriesModule;
 import org.elasticsearch.script.ScriptModule;
-import org.elasticsearch.ElasticsearchTestCase;
 import org.elasticsearch.threadpool.ThreadPool;
 import org.elasticsearch.threadpool.ThreadPoolModule;
 import org.hamcrest.Matchers;
@@ -1478,6 +1478,17 @@ public class SimpleIndexQueryParserTests extends ElasticsearchTestCase {
         assertThat(((TermQuery) functionScoreQuery.getSubQuery()).getTerm(), equalTo(new Term("name.last", "banon")));
         assertThat((double) ((BoostScoreFunction) functionScoreQuery.getFunction()).getBoost(), closeTo(1.3, 0.001));
     }
+    
+    @Test
+    public void testCustomBoostFactorQueryBuilder_withFunctionScoreWithoutQueryGiven() throws IOException {
+        IndexQueryParserService queryParser = queryParser();
+        Query parsedQuery = queryParser.parse(functionScoreQuery(factorFunction(1.3f))).query();
+        assertThat(parsedQuery, instanceOf(FunctionScoreQuery.class));
+        FunctionScoreQuery functionScoreQuery = (FunctionScoreQuery) parsedQuery;
+        assertThat(functionScoreQuery.getSubQuery() instanceof XConstantScoreQuery, equalTo(true));
+        assertThat(((XConstantScoreQuery)functionScoreQuery.getSubQuery()).getFilter() instanceof MatchAllDocsFilter, equalTo(true));
+        assertThat((double) ((BoostScoreFunction) functionScoreQuery.getFunction()).getBoost(), closeTo(1.3, 0.001));
+    }
 
 
     @Test

+ 23 - 2
src/test/java/org/elasticsearch/search/functionscore/DecayFunctionScoreTests.java

@@ -560,7 +560,7 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
                                         .add(new MatchAllFilterBuilder(), linearDecayFunction("date", "2013-05-30", "+15d"))
                                         .add(new MatchAllFilterBuilder(), linearDecayFunction("geo", lonlat, "1000km"))
                                         .add(new MatchAllFilterBuilder(),
-                                                linearDecayFunction("num", Integer.toString(numDocs), Integer.toString(numDocs / 2)))
+                                                linearDecayFunction("num", numDocs, numDocs / 2.0))
                                         .scoreMode("multiply").boostMode(CombineFunction.REPLACE.getName()))));
 
         SearchResponse sr = response.actionGet();
@@ -623,8 +623,29 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
                 searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
                         searchSource().explain(true).query(
                                 functionScoreQuery(termQuery("test", "value")).add(new MatchAllFilterBuilder(),
-                                        linearDecayFunction("num", Integer.toString(1), Integer.toString(1 / 2))).scoreMode("multiply"))));
+                                        linearDecayFunction("num", 1.0, 0.5)).scoreMode("multiply"))));
         response.actionGet();
     }
+    @Test
+    public void testNoQueryGiven() throws Exception {
+        assertAcked(prepareCreate("test").addMapping("type", 
+                jsonBuilder().startObject().startObject("type").startObject("properties")
+                    .startObject("test").field("type", "string").endObject()
+                    .startObject("num").field("type", "double").endObject()
+                    .endObject().endObject().endObject()));
+        ensureYellow();
+        client().index(
+                indexRequest("test").type("type").source(
+                        jsonBuilder().startObject().field("test", "value").field("num", 1.0).endObject())).actionGet();
+        refresh();
+        // so, we indexed a string field, but now we try to score a num field
+        ActionFuture<SearchResponse> response = client().search(
+                searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
+                        searchSource().explain(true).query(
+                                functionScoreQuery().add(new MatchAllFilterBuilder(),
+                                        linearDecayFunction("num", 1, 0.5)).scoreMode("multiply"))));
+        response.actionGet();
+    }
+
 
 }