@Test public void testScoring() throws Exception { int numDocs = indexRandomNumbers("keyword"); String[] scoreModes = new String[] {"max", "min", "avg", "total", "multiply", ""}; float primaryWeight = 1.1f; float secondaryWeight = 1.6f; for (String scoreMode : scoreModes) { for (int i = 0; i < numDocs - 4; i++) { String[] intToEnglish = new String[] { English.intToEnglish(i), English.intToEnglish(i + 1), English.intToEnglish(i + 2), English.intToEnglish(i + 3) }; QueryRescorer rescoreQuery = RescoreBuilder.queryRescorer( QueryBuilders.boolQuery() .disableCoord(true) .should( QueryBuilders.functionScoreQuery( QueryBuilders.termQuery("field1", intToEnglish[0])) .boostMode(CombineFunction.REPLACE) .add(ScoreFunctionBuilders.scriptFunction("5.0f"))) .should( QueryBuilders.functionScoreQuery( QueryBuilders.termQuery("field1", intToEnglish[1])) .boostMode(CombineFunction.REPLACE) .add(ScoreFunctionBuilders.scriptFunction("7.0f"))) .should( QueryBuilders.functionScoreQuery( QueryBuilders.termQuery("field1", intToEnglish[3])) .boostMode(CombineFunction.REPLACE) .add(ScoreFunctionBuilders.scriptFunction("0.0f")))) .setQueryWeight(primaryWeight) .setRescoreQueryWeight(secondaryWeight); if (!"".equals(scoreMode)) { rescoreQuery.setScoreMode(scoreMode); } SearchResponse rescored = client() .prepareSearch() .setPreference("test") // ensure we hit the same shards for tie-breaking .setQuery( QueryBuilders.boolQuery() .disableCoord(true) .should( QueryBuilders.functionScoreQuery( QueryBuilders.termQuery("field1", intToEnglish[0])) .boostMode(CombineFunction.REPLACE) .add(ScoreFunctionBuilders.scriptFunction("2.0f"))) .should( QueryBuilders.functionScoreQuery( QueryBuilders.termQuery("field1", intToEnglish[1])) .boostMode(CombineFunction.REPLACE) .add(ScoreFunctionBuilders.scriptFunction("3.0f"))) .should( QueryBuilders.functionScoreQuery( QueryBuilders.termQuery("field1", intToEnglish[2])) .boostMode(CombineFunction.REPLACE) .add(ScoreFunctionBuilders.scriptFunction("5.0f"))) .should( QueryBuilders.functionScoreQuery( QueryBuilders.termQuery("field1", intToEnglish[3])) .boostMode(CombineFunction.REPLACE) .add(ScoreFunctionBuilders.scriptFunction("0.2f")))) .setFrom(0) .setSize(10) .setRescorer(rescoreQuery) .setRescoreWindow(50) .execute() .actionGet(); assertHitCount(rescored, 4); if ("total".equals(scoreMode) || "".equals(scoreMode)) { assertFirstHit(rescored, hasId(String.valueOf(i + 1))); assertSecondHit(rescored, hasId(String.valueOf(i))); assertThirdHit(rescored, hasId(String.valueOf(i + 2))); assertThat( rescored.getHits().getHits()[0].getScore(), equalTo(3.0f * primaryWeight + 7.0f * secondaryWeight)); assertThat( rescored.getHits().getHits()[1].getScore(), equalTo(2.0f * primaryWeight + 5.0f * secondaryWeight)); assertThat(rescored.getHits().getHits()[2].getScore(), equalTo(5.0f * primaryWeight)); assertThat( rescored.getHits().getHits()[3].getScore(), equalTo(0.2f * primaryWeight + 0.0f * secondaryWeight)); } else if ("max".equals(scoreMode)) { assertFirstHit(rescored, hasId(String.valueOf(i + 1))); assertSecondHit(rescored, hasId(String.valueOf(i))); assertThirdHit(rescored, hasId(String.valueOf(i + 2))); assertThat(rescored.getHits().getHits()[0].getScore(), equalTo(7.0f * secondaryWeight)); assertThat(rescored.getHits().getHits()[1].getScore(), equalTo(5.0f * secondaryWeight)); assertThat(rescored.getHits().getHits()[2].getScore(), equalTo(5.0f * primaryWeight)); assertThat(rescored.getHits().getHits()[3].getScore(), equalTo(0.2f * primaryWeight)); } else if ("min".equals(scoreMode)) { assertFirstHit(rescored, hasId(String.valueOf(i + 2))); assertSecondHit(rescored, hasId(String.valueOf(i + 1))); assertThirdHit(rescored, hasId(String.valueOf(i))); assertThat(rescored.getHits().getHits()[0].getScore(), equalTo(5.0f * primaryWeight)); assertThat(rescored.getHits().getHits()[1].getScore(), equalTo(3.0f * primaryWeight)); assertThat(rescored.getHits().getHits()[2].getScore(), equalTo(2.0f * primaryWeight)); assertThat(rescored.getHits().getHits()[3].getScore(), equalTo(0.0f * secondaryWeight)); } else if ("avg".equals(scoreMode)) { assertFirstHit(rescored, hasId(String.valueOf(i + 1))); assertSecondHit(rescored, hasId(String.valueOf(i + 2))); assertThirdHit(rescored, hasId(String.valueOf(i))); assertThat( rescored.getHits().getHits()[0].getScore(), equalTo((3.0f * primaryWeight + 7.0f * secondaryWeight) / 2.0f)); assertThat(rescored.getHits().getHits()[1].getScore(), equalTo(5.0f * primaryWeight)); assertThat( rescored.getHits().getHits()[2].getScore(), equalTo((2.0f * primaryWeight + 5.0f * secondaryWeight) / 2.0f)); assertThat( rescored.getHits().getHits()[3].getScore(), equalTo((0.2f * primaryWeight) / 2.0f)); } else if ("multiply".equals(scoreMode)) { assertFirstHit(rescored, hasId(String.valueOf(i + 1))); assertSecondHit(rescored, hasId(String.valueOf(i))); assertThirdHit(rescored, hasId(String.valueOf(i + 2))); assertThat( rescored.getHits().getHits()[0].getScore(), equalTo(3.0f * primaryWeight * 7.0f * secondaryWeight)); assertThat( rescored.getHits().getHits()[1].getScore(), equalTo(2.0f * primaryWeight * 5.0f * secondaryWeight)); assertThat(rescored.getHits().getHits()[2].getScore(), equalTo(5.0f * primaryWeight)); assertThat( rescored.getHits().getHits()[3].getScore(), equalTo(0.2f * primaryWeight * 0.0f * secondaryWeight)); } } } }
@Test public void testExplain() throws Exception { assertAcked( prepareCreate("test") .addMapping( "type1", jsonBuilder() .startObject() .startObject("type1") .startObject("properties") .startObject("field1") .field("analyzer", "whitespace") .field("type", "string") .endObject() .endObject() .endObject() .endObject())); ensureGreen(); client() .prepareIndex("test", "type1", "1") .setSource("field1", "the quick brown fox") .execute() .actionGet(); client() .prepareIndex("test", "type1", "2") .setSource("field1", "the quick lazy huge brown fox jumps over the tree") .execute() .actionGet(); client() .prepareIndex("test", "type1", "3") .setSource( "field1", "quick huge brown", "field2", "the quick lazy huge brown fox jumps over the tree") .execute() .actionGet(); refresh(); { SearchResponse searchResponse = client() .prepareSearch() .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) .setQuery( QueryBuilders.matchQuery("field1", "the quick brown") .operator(MatchQueryBuilder.Operator.OR)) .setRescorer( RescoreBuilder.queryRescorer( QueryBuilders.matchPhraseQuery("field1", "the quick brown") .slop(2) .boost(4.0f)) .setQueryWeight(0.5f) .setRescoreQueryWeight(0.4f)) .setRescoreWindow(5) .setExplain(true) .execute() .actionGet(); assertHitCount(searchResponse, 3); assertFirstHit(searchResponse, hasId("1")); assertSecondHit(searchResponse, hasId("2")); assertThirdHit(searchResponse, hasId("3")); for (int i = 0; i < 3; i++) { assertThat(searchResponse.getHits().getAt(i).explanation(), notNullValue()); assertThat(searchResponse.getHits().getAt(i).explanation().isMatch(), equalTo(true)); assertThat(searchResponse.getHits().getAt(i).explanation().getDetails().length, equalTo(2)); assertThat( searchResponse.getHits().getAt(i).explanation().getDetails()[0].isMatch(), equalTo(true)); if (i == 2) { assertThat( searchResponse.getHits().getAt(i).explanation().getDetails()[1].getValue(), equalTo(0.5f)); } else { assertThat( searchResponse.getHits().getAt(i).explanation().getDescription(), equalTo("sum of:")); assertThat( searchResponse .getHits() .getAt(i) .explanation() .getDetails()[0] .getDetails()[1] .getValue(), equalTo(0.5f)); assertThat( searchResponse .getHits() .getAt(i) .explanation() .getDetails()[1] .getDetails()[1] .getValue(), equalTo(0.4f)); } } } String[] scoreModes = new String[] {"max", "min", "avg", "total", "multiply", ""}; String[] descriptionModes = new String[] {"max of:", "min of:", "avg of:", "sum of:", "product of:", "sum of:"}; for (int innerMode = 0; innerMode < scoreModes.length; innerMode++) { QueryRescorer innerRescoreQuery = RescoreBuilder.queryRescorer( QueryBuilders.matchQuery("field1", "the quick brown").boost(4.0f)) .setQueryWeight(0.5f) .setRescoreQueryWeight(0.4f); if (!"".equals(scoreModes[innerMode])) { innerRescoreQuery.setScoreMode(scoreModes[innerMode]); } SearchResponse searchResponse = client() .prepareSearch() .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) .setQuery( QueryBuilders.matchQuery("field1", "the quick brown") .operator(MatchQueryBuilder.Operator.OR)) .setRescorer(innerRescoreQuery) .setRescoreWindow(5) .setExplain(true) .execute() .actionGet(); assertHitCount(searchResponse, 3); assertFirstHit(searchResponse, hasId("1")); assertSecondHit(searchResponse, hasId("2")); assertThirdHit(searchResponse, hasId("3")); for (int j = 0; j < 3; j++) { assertThat( searchResponse.getHits().getAt(j).explanation().getDescription(), equalTo(descriptionModes[innerMode])); } for (int outerMode = 0; outerMode < scoreModes.length; outerMode++) { QueryRescorer outerRescoreQuery = RescoreBuilder.queryRescorer( QueryBuilders.matchQuery("field1", "the quick brown").boost(4.0f)) .setQueryWeight(0.5f) .setRescoreQueryWeight(0.4f); if (!"".equals(scoreModes[outerMode])) { outerRescoreQuery.setScoreMode(scoreModes[outerMode]); } searchResponse = client() .prepareSearch() .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) .setQuery( QueryBuilders.matchQuery("field1", "the quick brown") .operator(MatchQueryBuilder.Operator.OR)) .addRescorer(innerRescoreQuery) .setRescoreWindow(5) .addRescorer(outerRescoreQuery) .setRescoreWindow(10) .setExplain(true) .get(); assertHitCount(searchResponse, 3); assertFirstHit(searchResponse, hasId("1")); assertSecondHit(searchResponse, hasId("2")); assertThirdHit(searchResponse, hasId("3")); for (int j = 0; j < 3; j++) { Explanation explanation = searchResponse.getHits().getAt(j).explanation(); assertThat(explanation.getDescription(), equalTo(descriptionModes[outerMode])); assertThat( explanation.getDetails()[0].getDetails()[0].getDescription(), equalTo(descriptionModes[innerMode])); } } } }