瀏覽代碼

FunctionScore: Fixed RandomScoreFunction to guard against _uid field not existing.

Also added a test case to check the random score works with queries on
an empty index.
Ryan Ernst 11 年之前
父節點
當前提交
eb22d9ec24

+ 8 - 0
src/main/java/org/elasticsearch/common/lucene/search/function/RandomScoreFunction.java

@@ -35,6 +35,14 @@ public class RandomScoreFunction extends ScoreFunction {
     private final IndexFieldData<?> uidFieldData;
     private SortedBinaryDocValues uidByteData;
 
+    /**
+     * Default constructor. Only useful for constructing as a placeholder, but should not be used for actual scoring.
+     */
+    public RandomScoreFunction() {
+        super(CombineFunction.MULT);
+        uidFieldData = null;
+    }
+
     /**
      * Creates a RandomScoreFunction.
      *

+ 9 - 6
src/main/java/org/elasticsearch/index/query/functionscore/random/RandomScoreFunctionParser.java

@@ -66,15 +66,18 @@ public class RandomScoreFunctionParser implements ScoreFunctionParser {
             }
         }
 
+        final FieldMapper<?> mapper = SearchContext.current().mapperService().smartNameFieldMapper("_uid");
+        if (mapper == null) {
+            // mapper could be null if we are on a shard with no docs yet, so this won't actually be used
+            return new RandomScoreFunction();
+        }
+
         if (seed == -1) {
             seed = (int)parseContext.nowInMillis();
         }
-
-        ShardId shardId = SearchContext.current().indexShard().shardId();
-        int salt = (shardId.index().name().hashCode() << 10) | shardId.id();
-
-        final FieldMapper<?> mapper = SearchContext.current().mapperService().smartNameFieldMapper("_uid");
-        IndexFieldData<?> uidFieldData = SearchContext.current().fieldData().getForField(mapper);
+        final ShardId shardId = SearchContext.current().indexShard().shardId();
+        final int salt = (shardId.index().name().hashCode() << 10) | shardId.id();
+        final IndexFieldData<?> uidFieldData = SearchContext.current().fieldData().getForField(mapper);
 
         return new RandomScoreFunction(seed, salt, uidFieldData);
     }

+ 12 - 2
src/test/java/org/elasticsearch/search/functionscore/RandomScoreFunctionTests.java

@@ -18,7 +18,6 @@
  */
 package org.elasticsearch.search.functionscore;
 
-import org.apache.lucene.search.Explanation;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.index.query.functionscore.random.RandomScoreFunctionBuilder;
 import org.elasticsearch.search.SearchHit;
@@ -37,7 +36,7 @@ import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.
 import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
 import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
 import static org.hamcrest.Matchers.*;
-import static org.hamcrest.Matchers.arrayContaining;
+
 
 public class RandomScoreFunctionTests extends ElasticsearchIntegrationTest {
 
@@ -179,6 +178,17 @@ public class RandomScoreFunctionTests extends ElasticsearchIntegrationTest {
         assertThat(firstHit.explanation().toString(), containsString("" + seed));
     }
 
+    public void testNoDocs() throws Exception {
+        createIndex("test");
+        ensureGreen();
+
+        SearchResponse resp = client().prepareSearch("test")
+            .setQuery(functionScoreQuery(matchAllQuery(), randomFunction(1234)))
+            .get();
+        assertNoFailures(resp);
+        assertEquals(0, resp.getHits().totalHits());
+    }
+
     @Test
     public void testScoreRange() throws Exception {
         // all random scores should be in range [0.0, 1.0]