Remove usage of types in rank_eval endpoint

This commit is contained in:
Christoph Büscher 2017-11-06 22:46:59 +01:00 committed by Christoph Büscher
parent c83ec1f133
commit 0a6c6ac360
20 changed files with 284 additions and 525 deletions

View File

@ -32,40 +32,30 @@ import java.util.Objects;
public class DocumentKey implements Writeable, ToXContentObject {
private String docId;
private String type;
private String index;
void setIndex(String index) {
this.index = index;
}
void setType(String type) {
this.type = type;
}
void setDocId(String docId) {
this.docId = docId;
}
public DocumentKey(String index, String type, String docId) {
public DocumentKey(String index, String docId) {
if (Strings.isNullOrEmpty(index)) {
throw new IllegalArgumentException("Index must be set for each rated document");
}
if(Strings.isNullOrEmpty(type)) {
throw new IllegalArgumentException("Type must be set for each rated document");
}
if (Strings.isNullOrEmpty(docId)) {
throw new IllegalArgumentException("DocId must be set for each rated document");
}
this.index = index;
this.type = type;
this.docId = docId;
}
public DocumentKey(StreamInput in) throws IOException {
this.index = in.readString();
this.type = in.readString();
this.docId = in.readString();
}
@ -73,10 +63,6 @@ public class DocumentKey implements Writeable, ToXContentObject {
return index;
}
public String getType() {
return type;
}
public String getDocID() {
return docId;
}
@ -84,7 +70,6 @@ public class DocumentKey implements Writeable, ToXContentObject {
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeString(index);
out.writeString(type);
out.writeString(docId);
}
@ -97,21 +82,18 @@ public class DocumentKey implements Writeable, ToXContentObject {
return false;
}
DocumentKey other = (DocumentKey) obj;
return Objects.equals(index, other.index) &&
Objects.equals(type, other.type) &&
Objects.equals(docId, other.docId);
return Objects.equals(index, other.index) && Objects.equals(docId, other.docId);
}
@Override
public final int hashCode() {
return Objects.hash(index, type, docId);
return Objects.hash(index, docId);
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(RatedDocument.INDEX_FIELD.getPreferredName(), index);
builder.field(RatedDocument.TYPE_FIELD.getPreferredName(), type);
builder.field(RatedDocument.DOC_ID_FIELD.getPreferredName(), docId);
builder.endObject();
return builder;

View File

@ -35,29 +35,23 @@ import java.util.Optional;
import java.util.stream.Collectors;
/**
* Classes implementing this interface provide a means to compute the quality of
* a result list returned by some search.
*
* RelevancyLevel specifies the type of object determining the relevancy level
* of some known docid.
* Classes implementing this interface provide a means to compute the quality of a result list returned by some search.
*/
public interface RankedListQualityMetric extends ToXContent, NamedWriteable {
/**
* Returns a single metric representing the ranking quality of a set of
* returned documents wrt. to a set of document Ids labeled as relevant for
* this search.
* Returns a single metric representing the ranking quality of a set of returned
* documents wrt. to a set of document Ids labeled as relevant for this search.
*
* @param taskId
* the id of the query for which the ranking is currently
* evaluated
* the id of the query for which the ranking is currently evaluated
* @param hits
* the result hits as returned by a search request
* @param ratedDocs
* the documents that were ranked by human annotators for this
* query case
* @return some metric representing the quality of the result hit list wrt.
* to relevant doc ids.
* the documents that were ranked by human annotators for this query
* case
* @return some metric representing the quality of the result hit list wrt. to
* relevant doc ids.
*/
EvalQueryQuality evaluate(String taskId, SearchHit[] hits, List<RatedDocument> ratedDocs);
@ -65,8 +59,7 @@ public interface RankedListQualityMetric extends ToXContent, NamedWriteable {
RankedListQualityMetric rc;
Token token = parser.nextToken();
if (token != XContentParser.Token.FIELD_NAME) {
throw new ParsingException(parser.getTokenLocation(),
"[_na] missing required metric name");
throw new ParsingException(parser.getTokenLocation(), "[_na] missing required metric name");
}
String metricName = parser.currentName();
@ -82,8 +75,7 @@ public interface RankedListQualityMetric extends ToXContent, NamedWriteable {
rc = DiscountedCumulativeGain.fromXContent(parser);
break;
default:
throw new ParsingException(parser.getTokenLocation(),
"[_na] unknown query metric name [{}]", metricName);
throw new ParsingException(parser.getTokenLocation(), "[_na] unknown query metric name [{}]", metricName);
}
if (parser.currentToken() == XContentParser.Token.END_OBJECT) {
// if we are at END_OBJECT, move to the next one...
@ -92,14 +84,13 @@ public interface RankedListQualityMetric extends ToXContent, NamedWriteable {
return rc;
}
static List<RatedSearchHit> joinHitsWithRatings(SearchHit[] hits,
List<RatedDocument> ratedDocs) {
static List<RatedSearchHit> joinHitsWithRatings(SearchHit[] hits, List<RatedDocument> ratedDocs) {
// join hits with rated documents
Map<DocumentKey, RatedDocument> ratedDocumentMap = ratedDocs.stream()
.collect(Collectors.toMap(RatedDocument::getKey, item -> item));
List<RatedSearchHit> ratedSearchHits = new ArrayList<>(hits.length);
for (SearchHit hit : hits) {
DocumentKey key = new DocumentKey(hit.getIndex(), hit.getType(), hit.getId());
DocumentKey key = new DocumentKey(hit.getIndex(), hit.getId());
RatedDocument ratedDoc = ratedDocumentMap.get(key);
if (ratedDoc != null) {
ratedSearchHits.add(new RatedSearchHit(hit, Optional.of(ratedDoc.getRating())));
@ -112,16 +103,12 @@ public interface RankedListQualityMetric extends ToXContent, NamedWriteable {
static List<DocumentKey> filterUnknownDocuments(List<RatedSearchHit> ratedHits) {
// join hits with rated documents
List<DocumentKey> unknownDocs = ratedHits.stream()
.filter(hit -> hit.getRating().isPresent() == false)
.map(hit -> new DocumentKey(hit.getSearchHit().getIndex(),
hit.getSearchHit().getType(), hit.getSearchHit().getId()))
.collect(Collectors.toList());
List<DocumentKey> unknownDocs = ratedHits.stream().filter(hit -> hit.getRating().isPresent() == false)
.map(hit -> new DocumentKey(hit.getSearchHit().getIndex(), hit.getSearchHit().getId())).collect(Collectors.toList());
return unknownDocs;
}
default double combine(Collection<EvalQueryQuality> partialResults) {
return partialResults.stream().mapToDouble(EvalQueryQuality::getQualityLevel).sum()
/ partialResults.size();
return partialResults.stream().mapToDouble(EvalQueryQuality::getQualityLevel).sum() / partialResults.size();
}
}

View File

@ -34,21 +34,18 @@ import java.util.Objects;
/**
* A document ID and its rating for the query QA use case.
* */
*/
public class RatedDocument implements Writeable, ToXContentObject {
public static final ParseField RATING_FIELD = new ParseField("rating");
public static final ParseField DOC_ID_FIELD = new ParseField("_id");
public static final ParseField TYPE_FIELD = new ParseField("_type");
public static final ParseField INDEX_FIELD = new ParseField("_index");
private static final ConstructingObjectParser<RatedDocument, Void> PARSER =
new ConstructingObjectParser<>("rated_document",
a -> new RatedDocument((String) a[0], (String) a[1], (String) a[2], (Integer) a[3]));
private static final ConstructingObjectParser<RatedDocument, Void> PARSER = new ConstructingObjectParser<>("rated_document",
a -> new RatedDocument((String) a[0], (String) a[1], (Integer) a[2]));
static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), INDEX_FIELD);
PARSER.declareString(ConstructingObjectParser.constructorArg(), TYPE_FIELD);
PARSER.declareString(ConstructingObjectParser.constructorArg(), DOC_ID_FIELD);
PARSER.declareInt(ConstructingObjectParser.constructorArg(), RATING_FIELD);
}
@ -56,8 +53,8 @@ public class RatedDocument implements Writeable, ToXContentObject {
private int rating;
private DocumentKey key;
public RatedDocument(String index, String type, String docId, int rating) {
this(new DocumentKey(index, type, docId), rating);
public RatedDocument(String index, String docId, int rating) {
this(new DocumentKey(index, docId), rating);
}
public RatedDocument(StreamInput in) throws IOException {
@ -78,10 +75,6 @@ public class RatedDocument implements Writeable, ToXContentObject {
return key.getIndex();
}
public String getType() {
return key.getType();
}
public String getDocID() {
return key.getDocID();
}
@ -104,7 +97,6 @@ public class RatedDocument implements Writeable, ToXContentObject {
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(INDEX_FIELD.getPreferredName(), key.getIndex());
builder.field(TYPE_FIELD.getPreferredName(), key.getType());
builder.field(DOC_ID_FIELD.getPreferredName(), key.getDocID());
builder.field(RATING_FIELD.getPreferredName(), rating);
builder.endObject();
@ -125,8 +117,7 @@ public class RatedDocument implements Writeable, ToXContentObject {
return false;
}
RatedDocument other = (RatedDocument) obj;
return Objects.equals(key, other.key) &&
Objects.equals(rating, other.rating);
return Objects.equals(key, other.key) && Objects.equals(rating, other.rating);
}
@Override

View File

@ -54,7 +54,6 @@ import java.util.Set;
public class RatedRequest implements Writeable, ToXContentObject {
private String id;
private List<String> indices = new ArrayList<>();
private List<String> types = new ArrayList<>();
private List<String> summaryFields = new ArrayList<>();
/** Collection of rated queries for this query QA specification. */
private List<RatedDocument> ratedDocs = new ArrayList<>();
@ -93,7 +92,7 @@ public class RatedRequest implements Writeable, ToXContentObject {
"If template parameters are supplied need to set id of template to apply "
+ "them to too.");
}
// No documents with same _index/_type/id allowed.
// No documents with same _index/id allowed.
Set<DocumentKey> docKeys = new HashSet<>();
for (RatedDocument doc : ratedDocs) {
if (docKeys.add(doc.getKey()) == false) {
@ -131,11 +130,6 @@ public class RatedRequest implements Writeable, ToXContentObject {
for (int i = 0; i < indicesSize; i++) {
this.indices.add(in.readString());
}
int typesSize = in.readInt();
types = new ArrayList<>(typesSize);
for (int i = 0; i < typesSize; i++) {
this.types.add(in.readString());
}
int intentSize = in.readInt();
ratedDocs = new ArrayList<>(intentSize);
for (int i = 0; i < intentSize; i++) {
@ -159,10 +153,6 @@ public class RatedRequest implements Writeable, ToXContentObject {
for (String index : indices) {
out.writeString(index);
}
out.writeInt(types.size());
for (String type : types) {
out.writeString(type);
}
out.writeInt(ratedDocs.size());
for (RatedDocument ratedDoc : ratedDocs) {
ratedDoc.writeTo(out);
@ -187,14 +177,6 @@ public class RatedRequest implements Writeable, ToXContentObject {
return indices;
}
public void setTypes(List<String> types) {
this.types = types;
}
public List<String> getTypes() {
return types;
}
/** Returns a user supplied spec id for easier referencing. */
public String getId() {
return id;
@ -314,7 +296,7 @@ public class RatedRequest implements Writeable, ToXContentObject {
RatedRequest other = (RatedRequest) obj;
return Objects.equals(id, other.id) && Objects.equals(testRequest, other.testRequest)
&& Objects.equals(indices, other.indices) && Objects.equals(types, other.types)
&& Objects.equals(indices, other.indices)
&& Objects.equals(summaryFields, other.summaryFields)
&& Objects.equals(ratedDocs, other.ratedDocs)
&& Objects.equals(params, other.params)
@ -323,7 +305,7 @@ public class RatedRequest implements Writeable, ToXContentObject {
@Override
public final int hashCode() {
return Objects.hash(id, testRequest, indices, types, summaryFields, ratedDocs, params,
return Objects.hash(id, testRequest, indices, summaryFields, ratedDocs, params,
templateId);
}
}

View File

@ -135,13 +135,13 @@ import static org.elasticsearch.rest.RestRequest.Method.POST;
"quality_level": 0.4,
"unknown_docs": {
"amsterdam_query": [
{ "index" : "test", "type" : "my_type", "doc_id" : "21"},
{ "index" : "test", "type" : "my_type", "doc_id" : "5"},
{ "index" : "test", "type" : "my_type", "doc_id" : "9"}
{ "index" : "test", "doc_id" : "21"},
{ "index" : "test", "doc_id" : "5"},
{ "index" : "test", "doc_id" : "9"}
]
}, {
"berlin_query": [
{ "index" : "test", "type" : "my_type", "doc_id" : "42"}
{ "index" : "test", "doc_id" : "42"}
]
}
}]
@ -157,8 +157,6 @@ public class RestRankEvalAction extends BaseRestHandler {
controller.registerHandler(POST, "/_rank_eval", this);
controller.registerHandler(GET, "/{index}/_rank_eval", this);
controller.registerHandler(POST, "/{index}/_rank_eval", this);
controller.registerHandler(GET, "/{index}/{type}/_rank_eval", this);
controller.registerHandler(POST, "/{index}/{type}/_rank_eval", this);
}
@Override
@ -176,13 +174,10 @@ public class RestRankEvalAction extends BaseRestHandler {
XContentParser parser) {
List<String> indices = Arrays
.asList(Strings.splitStringByCommaToArray(request.param("index")));
List<String> types = Arrays
.asList(Strings.splitStringByCommaToArray(request.param("type")));
RankEvalSpec spec = null;
spec = RankEvalSpec.parse(parser);
for (RatedRequest specification : spec.getRatedRequests()) {
specification.setIndices(indices);
specification.setTypes(types);
}
;

View File

@ -128,10 +128,6 @@ public class TransportRankEvalAction
indices = ratedRequest.getIndices().toArray(indices);
SearchRequest templatedRequest = new SearchRequest(indices, ratedSearchSource);
String[] types = new String[ratedRequest.getTypes().size()];
types = ratedRequest.getTypes().toArray(types);
templatedRequest.types(types);
RequestTask task = new RequestTask(templatedRequest, searchListener);
taskQueue.add(task);
}

View File

@ -43,13 +43,12 @@ public class DiscountedCumulativeGainTests extends ESTestCase {
/**
* Assuming the docs are ranked in the following order:
*
* rank | rel_rank | 2^(rel_rank) - 1 | log_2(rank + 1) | (2^(rel_rank) - 1)
* / log_2(rank + 1)
* rank | rel_rank | 2^(rel_rank) - 1 | log_2(rank + 1) | (2^(rel_rank) - 1) /
* log_2(rank + 1)
* -------------------------------------------------------------------------------------------
* 1 | 3 | 7.0 | 1.0 | 7.0 2 | 2 | 3.0 | 1.5849625007211563
* | 1.8927892607143721 3 | 3 | 7.0 | 2.0 | 3.5 4 | 0 | 0.0
* | 2.321928094887362 | 0.0 5 | 1 | 1.0 | 2.584962500721156
* | 0.38685280723454163 6 | 2 | 3.0 | 2.807354922057604
* 1 | 3 | 7.0 | 1.0 | 7.0 2 | 2 | 3.0 | 1.5849625007211563 | 1.8927892607143721
* 3 | 3 | 7.0 | 2.0 | 3.5 4 | 0 | 0.0 | 2.321928094887362 | 0.0 5 | 1 | 1.0
* | 2.584962500721156 | 0.38685280723454163 6 | 2 | 3.0 | 2.807354922057604
* | 1.0686215613240666
*
* dcg = 13.84826362927298 (sum of last column)
@ -59,45 +58,41 @@ public class DiscountedCumulativeGainTests extends ESTestCase {
int[] relevanceRatings = new int[] { 3, 2, 3, 0, 1, 2 };
SearchHit[] hits = new SearchHit[6];
for (int i = 0; i < 6; i++) {
rated.add(new RatedDocument("index", "type", Integer.toString(i), relevanceRatings[i]));
hits[i] = new SearchHit(i, Integer.toString(i), new Text("type"),
Collections.emptyMap());
rated.add(new RatedDocument("index", Integer.toString(i), relevanceRatings[i]));
hits[i] = new SearchHit(i, Integer.toString(i), new Text("type"), Collections.emptyMap());
hits[i].shard(new SearchShardTarget("testnode", new Index("index", "uuid"), 0, null));
}
DiscountedCumulativeGain dcg = new DiscountedCumulativeGain();
assertEquals(13.84826362927298, dcg.evaluate("id", hits, rated).getQualityLevel(), 0.00001);
/**
* Check with normalization: to get the maximal possible dcg, sort
* documents by relevance in descending order
* Check with normalization: to get the maximal possible dcg, sort documents by
* relevance in descending order
*
* rank | rel_rank | 2^(rel_rank) - 1 | log_2(rank + 1) | (2^(rel_rank)
* - 1) / log_2(rank + 1)
* rank | rel_rank | 2^(rel_rank) - 1 | log_2(rank + 1) | (2^(rel_rank) - 1) /
* log_2(rank + 1)
* ---------------------------------------------------------------------------------------
* 1 | 3 | 7.0 | 1.0  | 7.0 2 | 3 | 7.0 |
* 1.5849625007211563 | 4.416508275000202 3 | 2 | 3.0 | 2.0  | 1.5 4 | 2
* | 3.0 | 2.321928094887362  | 1.2920296742201793 5 | 1 | 1.0 |
* 2.584962500721156  | 0.38685280723454163 6 | 0 | 0.0 |
* 2.807354922057604  | 0.0
* 1 | 3 | 7.0 | 1.0  | 7.0 2 | 3 | 7.0 | 1.5849625007211563 | 4.416508275000202
* 3 | 2 | 3.0 | 2.0  | 1.5 4 | 2 | 3.0 | 2.321928094887362 
* | 1.2920296742201793 5 | 1 | 1.0 | 2.584962500721156  | 0.38685280723454163 6
* | 0 | 0.0 | 2.807354922057604  | 0.0
*
* idcg = 14.595390756454922 (sum of last column)
*/
dcg.setNormalize(true);
assertEquals(13.84826362927298 / 14.595390756454922,
dcg.evaluate("id", hits, rated).getQualityLevel(), 0.00001);
assertEquals(13.84826362927298 / 14.595390756454922, dcg.evaluate("id", hits, rated).getQualityLevel(), 0.00001);
}
/**
* This tests metric when some documents in the search result don't have a
* rating provided by the user.
*
* rank | rel_rank | 2^(rel_rank) - 1 | log_2(rank + 1) | (2^(rel_rank) - 1)
* / log_2(rank + 1)
* rank | rel_rank | 2^(rel_rank) - 1 | log_2(rank + 1) | (2^(rel_rank) - 1) /
* log_2(rank + 1)
* -------------------------------------------------------------------------------------------
* 1 | 3 | 7.0 | 1.0 | 7.0 2 | 2 | 3.0 | 1.5849625007211563
* | 1.8927892607143721 3 | 3 | 7.0 | 2.0 | 3.5 4 | n/a | n/a | n/a | n/a 5
* | 1 | 1.0 | 2.584962500721156 | 0.38685280723454163 6 | n/a | n/a | n/a |
* n/a
* 1 | 3 | 7.0 | 1.0 | 7.0 2 | 2 | 3.0 | 1.5849625007211563 | 1.8927892607143721
* 3 | 3 | 7.0 | 2.0 | 3.5 4 | n/a | n/a | n/a | n/a 5 | 1 | 1.0
* | 2.584962500721156 | 0.38685280723454163 6 | n/a | n/a | n/a | n/a
*
* dcg = 12.779642067948913 (sum of last column)
*/
@ -108,12 +103,10 @@ public class DiscountedCumulativeGainTests extends ESTestCase {
for (int i = 0; i < 6; i++) {
if (i < relevanceRatings.length) {
if (relevanceRatings[i] != null) {
rated.add(new RatedDocument("index", "type", Integer.toString(i),
relevanceRatings[i]));
rated.add(new RatedDocument("index", Integer.toString(i), relevanceRatings[i]));
}
}
hits[i] = new SearchHit(i, Integer.toString(i), new Text("type"),
Collections.emptyMap());
hits[i] = new SearchHit(i, Integer.toString(i), new Text("type"), Collections.emptyMap());
hits[i].shard(new SearchShardTarget("testnode", new Index("index", "uuid"), 0, null));
}
DiscountedCumulativeGain dcg = new DiscountedCumulativeGain();
@ -122,36 +115,34 @@ public class DiscountedCumulativeGainTests extends ESTestCase {
assertEquals(2, filterUnknownDocuments(result.getHitsAndRatings()).size());
/**
* Check with normalization: to get the maximal possible dcg, sort
* documents by relevance in descending order
* Check with normalization: to get the maximal possible dcg, sort documents by
* relevance in descending order
*
* rank | rel_rank | 2^(rel_rank) - 1 | log_2(rank + 1) | (2^(rel_rank)
* - 1) / log_2(rank + 1)
* rank | rel_rank | 2^(rel_rank) - 1 | log_2(rank + 1) | (2^(rel_rank) - 1) /
* log_2(rank + 1)
* ----------------------------------------------------------------------------------------
* 1 | 3 | 7.0 | 1.0  | 7.0 2 | 3 | 7.0 |
* 1.5849625007211563 | 4.416508275000202 3 | 2 | 3.0 | 2.0  | 1.5 4 | 1
* | 1.0 | 2.321928094887362   | 0.43067655807339 5 | n.a | n.a | n.a. 
* | n.a. 6 | n.a | n.a | n.a  | n.a
* 1 | 3 | 7.0 | 1.0  | 7.0 2 | 3 | 7.0 | 1.5849625007211563 | 4.416508275000202
* 3 | 2 | 3.0 | 2.0  | 1.5 4 | 1 | 1.0 | 2.321928094887362   | 0.43067655807339
* 5 | n.a | n.a | n.a.  | n.a. 6 | n.a | n.a | n.a  | n.a
*
* idcg = 13.347184833073591 (sum of last column)
*/
dcg.setNormalize(true);
assertEquals(12.779642067948913 / 13.347184833073591,
dcg.evaluate("id", hits, rated).getQualityLevel(), 0.00001);
assertEquals(12.779642067948913 / 13.347184833073591, dcg.evaluate("id", hits, rated).getQualityLevel(), 0.00001);
}
/**
* This tests that normalization works as expected when there are more rated
* documents than search hits because we restrict DCG to be calculated at
* the fourth position
* documents than search hits because we restrict DCG to be calculated at the
* fourth position
*
* rank | rel_rank | 2^(rel_rank) - 1 | log_2(rank + 1) | (2^(rel_rank) - 1)
* / log_2(rank + 1)
* rank | rel_rank | 2^(rel_rank) - 1 | log_2(rank + 1) | (2^(rel_rank) - 1) /
* log_2(rank + 1)
* -------------------------------------------------------------------------------------------
* 1 | 3 | 7.0 | 1.0 | 7.0 2 | 2 | 3.0 | 1.5849625007211563
* | 1.8927892607143721 3 | 3 | 7.0 | 2.0 | 3.5 4 | n/a | n/a | n/a | n/a
* ----------------------------------------------------------------- 5 | 1
* | 1.0 | 2.584962500721156 | 0.38685280723454163 6 | n/a | n/a | n/a | n/a
* 1 | 3 | 7.0 | 1.0 | 7.0 2 | 2 | 3.0 | 1.5849625007211563 | 1.8927892607143721
* 3 | 3 | 7.0 | 2.0 | 3.5 4 | n/a | n/a | n/a | n/a
* ----------------------------------------------------------------- 5 | 1 | 1.0
* | 2.584962500721156 | 0.38685280723454163 6 | n/a | n/a | n/a | n/a
*
* dcg = 12.392789260714371 (sum of last column until position 4)
*/
@ -161,16 +152,14 @@ public class DiscountedCumulativeGainTests extends ESTestCase {
for (int i = 0; i < 6; i++) {
if (i < relevanceRatings.length) {
if (relevanceRatings[i] != null) {
ratedDocs.add(new RatedDocument("index", "type", Integer.toString(i),
relevanceRatings[i]));
ratedDocs.add(new RatedDocument("index", Integer.toString(i), relevanceRatings[i]));
}
}
}
// only create four hits
SearchHit[] hits = new SearchHit[4];
for (int i = 0; i < 4; i++) {
hits[i] = new SearchHit(i, Integer.toString(i), new Text("type"),
Collections.emptyMap());
hits[i] = new SearchHit(i, Integer.toString(i), new Text("type"), Collections.emptyMap());
hits[i].shard(new SearchShardTarget("testnode", new Index("index", "uuid"), 0, null));
}
DiscountedCumulativeGain dcg = new DiscountedCumulativeGain();
@ -179,28 +168,25 @@ public class DiscountedCumulativeGainTests extends ESTestCase {
assertEquals(1, filterUnknownDocuments(result.getHitsAndRatings()).size());
/**
* Check with normalization: to get the maximal possible dcg, sort
* documents by relevance in descending order
* Check with normalization: to get the maximal possible dcg, sort documents by
* relevance in descending order
*
* rank | rel_rank | 2^(rel_rank) - 1 | log_2(rank + 1) | (2^(rel_rank)
* - 1) / log_2(rank + 1)
* rank | rel_rank | 2^(rel_rank) - 1 | log_2(rank + 1) | (2^(rel_rank) - 1) /
* log_2(rank + 1)
* ---------------------------------------------------------------------------------------
* 1 | 3 | 7.0 | 1.0  | 7.0 2 | 3 | 7.0 |
* 1.5849625007211563 | 4.416508275000202 3 | 2 | 3.0 | 2.0  | 1.5 4 | 1
* | 1.0 | 2.321928094887362   | 0.43067655807339
* 1 | 3 | 7.0 | 1.0  | 7.0 2 | 3 | 7.0 | 1.5849625007211563 | 4.416508275000202
* 3 | 2 | 3.0 | 2.0  | 1.5 4 | 1 | 1.0 | 2.321928094887362   | 0.43067655807339
* ---------------------------------------------------------------------------------------
* 5 | n.a | n.a | n.a.  | n.a. 6 | n.a | n.a | n.a  | n.a
*
* idcg = 13.347184833073591 (sum of last column)
*/
dcg.setNormalize(true);
assertEquals(12.392789260714371 / 13.347184833073591,
dcg.evaluate("id", hits, ratedDocs).getQualityLevel(), 0.00001);
assertEquals(12.392789260714371 / 13.347184833073591, dcg.evaluate("id", hits, ratedDocs).getQualityLevel(), 0.00001);
}
public void testParseFromXContent() throws IOException {
String xContent = " {\n" + " \"unknown_doc_rating\": 2,\n" + " \"normalize\": true\n"
+ "}";
String xContent = " {\n" + " \"unknown_doc_rating\": 2,\n" + " \"normalize\": true\n" + "}";
try (XContentParser parser = createParser(JsonXContent.jsonXContent, xContent)) {
DiscountedCumulativeGain dcgAt = DiscountedCumulativeGain.fromXContent(parser);
assertEquals(2, dcgAt.getUnknownDocRating().intValue());
@ -218,8 +204,7 @@ public class DiscountedCumulativeGainTests extends ESTestCase {
public void testXContentRoundtrip() throws IOException {
DiscountedCumulativeGain testItem = createTestItem();
XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
XContentBuilder shuffled = shuffleXContent(
testItem.toXContent(builder, ToXContent.EMPTY_PARAMS));
XContentBuilder shuffled = shuffleXContent(testItem.toXContent(builder, ToXContent.EMPTY_PARAMS));
try (XContentParser itemParser = createParser(shuffled)) {
itemParser.nextToken();
itemParser.nextToken();
@ -232,8 +217,7 @@ public class DiscountedCumulativeGainTests extends ESTestCase {
public void testSerialization() throws IOException {
DiscountedCumulativeGain original = createTestItem();
DiscountedCumulativeGain deserialized = RankEvalTestHelper.copy(original,
DiscountedCumulativeGain::new);
DiscountedCumulativeGain deserialized = RankEvalTestHelper.copy(original, DiscountedCumulativeGain::new);
assertEquals(deserialized, original);
assertEquals(deserialized.hashCode(), original.hashCode());
assertNotSame(deserialized, original);
@ -254,8 +238,7 @@ public class DiscountedCumulativeGainTests extends ESTestCase {
List<Runnable> mutators = new ArrayList<>();
mutators.add(() -> gain.setNormalize(!original.getNormalize()));
mutators.add(() -> gain.setUnknownDocRating(
randomValueOtherThan(unknownDocRating, () -> randomIntBetween(0, 10))));
mutators.add(() -> gain.setUnknownDocRating(randomValueOtherThan(unknownDocRating, () -> randomIntBetween(0, 10))));
randomFrom(mutators).run();
return gain;
}

View File

@ -23,14 +23,12 @@ import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
public class DocumentKeyTests extends ESTestCase {
static DocumentKey createRandomRatedDocumentKey() {
String index = randomAlphaOfLengthBetween(1, 10);
String type = randomAlphaOfLengthBetween(1, 10);
String docId = randomAlphaOfLengthBetween(1, 10);
return new DocumentKey(index, type, docId);
return new DocumentKey(index, docId);
}
public DocumentKey createTestItem() {
@ -39,28 +37,24 @@ public class DocumentKeyTests extends ESTestCase {
public DocumentKey mutateTestItem(DocumentKey original) {
String index = original.getIndex();
String type = original.getType();
String docId = original.getDocID();
switch (randomIntBetween(0, 2)) {
switch (randomIntBetween(0, 1)) {
case 0:
index = index + "_";
break;
case 1:
type = type + "_";
break;
case 2:
docId = docId + "_";
break;
default:
throw new IllegalStateException("The test should only allow three parameters mutated");
throw new IllegalStateException("The test should only allow two parameters mutated");
}
return new DocumentKey(index, type, docId);
return new DocumentKey(index, docId);
}
public void testEqualsAndHash() throws IOException {
DocumentKey testItem = createRandomRatedDocumentKey();
RankEvalTestHelper.testHashCodeAndEquals(testItem, mutateTestItem(testItem),
new DocumentKey(testItem.getIndex(), testItem.getType(), testItem.getDocID()));
new DocumentKey(testItem.getIndex(), testItem.getDocID()));
}
public void testSerialization() throws IOException {
@ -70,6 +64,4 @@ public class DocumentKeyTests extends ESTestCase {
assertEquals(deserialized.hashCode(), original.hashCode());
assertNotSame(deserialized, original);
}
}

View File

@ -42,96 +42,72 @@ public class PrecisionTests extends ESTestCase {
public void testPrecisionAtFiveCalculation() {
List<RatedDocument> rated = new ArrayList<>();
rated.add(new RatedDocument("test", "testtype", "0", Rating.RELEVANT.ordinal()));
EvalQueryQuality evaluated = (new Precision()).evaluate("id",
toSearchHits(rated, "test", "testtype"), rated);
rated.add(new RatedDocument("test", "0", Rating.RELEVANT.ordinal()));
EvalQueryQuality evaluated = (new Precision()).evaluate("id", toSearchHits(rated, "test"), rated);
assertEquals(1, evaluated.getQualityLevel(), 0.00001);
assertEquals(1,
((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(1, ((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(1, ((Precision.Breakdown) evaluated.getMetricDetails()).getRetrieved());
}
public void testPrecisionAtFiveIgnoreOneResult() {
List<RatedDocument> rated = new ArrayList<>();
rated.add(new RatedDocument("test", "testtype", "0", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "testtype", "1", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "testtype", "2", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "testtype", "3", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "testtype", "4", Rating.IRRELEVANT.ordinal()));
EvalQueryQuality evaluated = (new Precision()).evaluate("id",
toSearchHits(rated, "test", "testtype"), rated);
rated.add(new RatedDocument("test", "0", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "1", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "2", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "3", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "4", Rating.IRRELEVANT.ordinal()));
EvalQueryQuality evaluated = (new Precision()).evaluate("id", toSearchHits(rated, "test"), rated);
assertEquals((double) 4 / 5, evaluated.getQualityLevel(), 0.00001);
assertEquals(4,
((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(4, ((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(5, ((Precision.Breakdown) evaluated.getMetricDetails()).getRetrieved());
}
/**
* test that the relevant rating threshold can be set to something larger
* than 1. e.g. we set it to 2 here and expect dics 0-2 to be not relevant,
* doc 3 and 4 to be relevant
* test that the relevant rating threshold can be set to something larger than
* 1. e.g. we set it to 2 here and expect dics 0-2 to be not relevant, doc 3 and
* 4 to be relevant
*/
public void testPrecisionAtFiveRelevanceThreshold() {
List<RatedDocument> rated = new ArrayList<>();
rated.add(new RatedDocument("test", "testtype", "0", 0));
rated.add(new RatedDocument("test", "testtype", "1", 1));
rated.add(new RatedDocument("test", "testtype", "2", 2));
rated.add(new RatedDocument("test", "testtype", "3", 3));
rated.add(new RatedDocument("test", "testtype", "4", 4));
rated.add(new RatedDocument("test", "0", 0));
rated.add(new RatedDocument("test", "1", 1));
rated.add(new RatedDocument("test", "2", 2));
rated.add(new RatedDocument("test", "3", 3));
rated.add(new RatedDocument("test", "4", 4));
Precision precisionAtN = new Precision();
precisionAtN.setRelevantRatingThreshhold(2);
EvalQueryQuality evaluated = precisionAtN.evaluate("id",
toSearchHits(rated, "test", "testtype"), rated);
EvalQueryQuality evaluated = precisionAtN.evaluate("id", toSearchHits(rated, "test"), rated);
assertEquals((double) 3 / 5, evaluated.getQualityLevel(), 0.00001);
assertEquals(3,
((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(3, ((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(5, ((Precision.Breakdown) evaluated.getMetricDetails()).getRetrieved());
}
public void testPrecisionAtFiveCorrectIndex() {
List<RatedDocument> rated = new ArrayList<>();
rated.add(new RatedDocument("test_other", "testtype", "0", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test_other", "testtype", "1", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "testtype", "0", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "testtype", "1", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "testtype", "2", Rating.IRRELEVANT.ordinal()));
rated.add(new RatedDocument("test_other", "0", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test_other", "1", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "0", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "1", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "2", Rating.IRRELEVANT.ordinal()));
// the following search hits contain only the last three documents
EvalQueryQuality evaluated = (new Precision()).evaluate("id",
toSearchHits(rated.subList(2, 5), "test", "testtype"), rated);
EvalQueryQuality evaluated = (new Precision()).evaluate("id", toSearchHits(rated.subList(2, 5), "test"), rated);
assertEquals((double) 2 / 3, evaluated.getQualityLevel(), 0.00001);
assertEquals(2,
((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(3, ((Precision.Breakdown) evaluated.getMetricDetails()).getRetrieved());
}
public void testPrecisionAtFiveCorrectType() {
List<RatedDocument> rated = new ArrayList<>();
rated.add(new RatedDocument("test", "other_type", "0", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "other_type", "1", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "testtype", "0", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "testtype", "1", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "testtype", "2", Rating.IRRELEVANT.ordinal()));
EvalQueryQuality evaluated = (new Precision()).evaluate("id",
toSearchHits(rated.subList(2, 5), "test", "testtype"), rated);
assertEquals((double) 2 / 3, evaluated.getQualityLevel(), 0.00001);
assertEquals(2,
((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(2, ((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(3, ((Precision.Breakdown) evaluated.getMetricDetails()).getRetrieved());
}
public void testIgnoreUnlabeled() {
List<RatedDocument> rated = new ArrayList<>();
rated.add(new RatedDocument("test", "testtype", "0", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "testtype", "1", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "0", Rating.RELEVANT.ordinal()));
rated.add(new RatedDocument("test", "1", Rating.RELEVANT.ordinal()));
// add an unlabeled search hit
SearchHit[] searchHits = Arrays.copyOf(toSearchHits(rated, "test", "testtype"), 3);
SearchHit[] searchHits = Arrays.copyOf(toSearchHits(rated, "test"), 3);
searchHits[2] = new SearchHit(2, "2", new Text("testtype"), Collections.emptyMap());
searchHits[2].shard(new SearchShardTarget("testnode", new Index("index", "uuid"), 0, null));
EvalQueryQuality evaluated = (new Precision()).evaluate("id", searchHits, rated);
assertEquals((double) 2 / 3, evaluated.getQualityLevel(), 0.00001);
assertEquals(2,
((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(2, ((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(3, ((Precision.Breakdown) evaluated.getMetricDetails()).getRetrieved());
// also try with setting `ignore_unlabeled`
@ -139,8 +115,7 @@ public class PrecisionTests extends ESTestCase {
prec.setIgnoreUnlabeled(true);
evaluated = prec.evaluate("id", searchHits, rated);
assertEquals((double) 2 / 2, evaluated.getQualityLevel(), 0.00001);
assertEquals(2,
((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(2, ((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(2, ((Precision.Breakdown) evaluated.getMetricDetails()).getRetrieved());
}
@ -150,11 +125,9 @@ public class PrecisionTests extends ESTestCase {
hits[i] = new SearchHit(i, i + "", new Text("type"), Collections.emptyMap());
hits[i].shard(new SearchShardTarget("testnode", new Index("index", "uuid"), 0, null));
}
EvalQueryQuality evaluated = (new Precision()).evaluate("id", hits,
Collections.emptyList());
EvalQueryQuality evaluated = (new Precision()).evaluate("id", hits, Collections.emptyList());
assertEquals(0.0d, evaluated.getQualityLevel(), 0.00001);
assertEquals(0,
((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(0, ((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(5, ((Precision.Breakdown) evaluated.getMetricDetails()).getRetrieved());
// also try with setting `ignore_unlabeled`
@ -162,8 +135,7 @@ public class PrecisionTests extends ESTestCase {
prec.setIgnoreUnlabeled(true);
evaluated = prec.evaluate("id", hits, Collections.emptyList());
assertEquals(0.0d, evaluated.getQualityLevel(), 0.00001);
assertEquals(0,
((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(0, ((Precision.Breakdown) evaluated.getMetricDetails()).getRelevantRetrieved());
assertEquals(0, ((Precision.Breakdown) evaluated.getMetricDetails()).getRetrieved());
}
@ -201,8 +173,7 @@ public class PrecisionTests extends ESTestCase {
public void testXContentRoundtrip() throws IOException {
Precision testItem = createTestItem();
XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
XContentBuilder shuffled = shuffleXContent(
testItem.toXContent(builder, ToXContent.EMPTY_PARAMS));
XContentBuilder shuffled = shuffleXContent(testItem.toXContent(builder, ToXContent.EMPTY_PARAMS));
try (XContentParser itemParser = createParser(shuffled)) {
itemParser.nextToken();
itemParser.nextToken();
@ -223,8 +194,7 @@ public class PrecisionTests extends ESTestCase {
public void testEqualsAndHash() throws IOException {
Precision testItem = createTestItem();
RankEvalTestHelper.testHashCodeAndEquals(testItem, mutateTestItem(testItem),
RankEvalTestHelper.copy(testItem, Precision::new));
RankEvalTestHelper.testHashCodeAndEquals(testItem, mutateTestItem(testItem), RankEvalTestHelper.copy(testItem, Precision::new));
}
private static Precision mutateTestItem(Precision original) {
@ -236,16 +206,15 @@ public class PrecisionTests extends ESTestCase {
List<Runnable> mutators = new ArrayList<>();
mutators.add(() -> precision.setIgnoreUnlabeled(!ignoreUnlabeled));
mutators.add(() -> precision.setRelevantRatingThreshhold(
randomValueOtherThan(relevantThreshold, () -> randomIntBetween(0, 10))));
mutators.add(() -> precision.setRelevantRatingThreshhold(randomValueOtherThan(relevantThreshold, () -> randomIntBetween(0, 10))));
randomFrom(mutators).run();
return precision;
}
private static SearchHit[] toSearchHits(List<RatedDocument> rated, String index, String type) {
private static SearchHit[] toSearchHits(List<RatedDocument> rated, String index) {
SearchHit[] hits = new SearchHit[rated.size()];
for (int i = 0; i < rated.size(); i++) {
hits[i] = new SearchHit(i, i + "", new Text(type), Collections.emptyMap());
hits[i] = new SearchHit(i, i + "", new Text(""), Collections.emptyMap());
hits[i].shard(new SearchShardTarget("testnode", new Index(index, "uuid"), 0, null));
}
return hits;

View File

@ -65,7 +65,6 @@ public class RankEvalRequestIT extends ESIntegTestCase {
public void testPrecisionAtRequest() {
List<String> indices = Arrays.asList(new String[] { "test" });
List<String> types = Arrays.asList(new String[] { "testtype" });
List<RatedRequest> specifications = new ArrayList<>();
SearchSourceBuilder testQuery = new SearchSourceBuilder();
@ -73,14 +72,12 @@ public class RankEvalRequestIT extends ESIntegTestCase {
RatedRequest amsterdamRequest = new RatedRequest("amsterdam_query",
createRelevant("2", "3", "4", "5"), testQuery);
amsterdamRequest.setIndices(indices);
amsterdamRequest.setTypes(types);
amsterdamRequest.setSummaryFields(Arrays.asList(new String[] { "text", "title" }));
specifications.add(amsterdamRequest);
RatedRequest berlinRequest = new RatedRequest("berlin_query", createRelevant("1"),
testQuery);
berlinRequest.setIndices(indices);
berlinRequest.setTypes(types);
berlinRequest.setSummaryFields(Arrays.asList(new String[] { "text", "title" }));
specifications.add(berlinRequest);
@ -135,7 +132,6 @@ public class RankEvalRequestIT extends ESIntegTestCase {
*/
public void testBadQuery() {
List<String> indices = Arrays.asList(new String[] { "test" });
List<String> types = Arrays.asList(new String[] { "testtype" });
List<RatedRequest> specifications = new ArrayList<>();
SearchSourceBuilder amsterdamQuery = new SearchSourceBuilder();
@ -143,7 +139,6 @@ public class RankEvalRequestIT extends ESIntegTestCase {
RatedRequest amsterdamRequest = new RatedRequest("amsterdam_query",
createRelevant("2", "3", "4", "5"), amsterdamQuery);
amsterdamRequest.setIndices(indices);
amsterdamRequest.setTypes(types);
specifications.add(amsterdamRequest);
SearchSourceBuilder brokenQuery = new SearchSourceBuilder();
@ -151,7 +146,6 @@ public class RankEvalRequestIT extends ESIntegTestCase {
RatedRequest brokenRequest = new RatedRequest("broken_query", createRelevant("1"),
brokenQuery);
brokenRequest.setIndices(indices);
brokenRequest.setTypes(types);
specifications.add(brokenRequest);
RankEvalSpec task = new RankEvalSpec(specifications, new Precision());
@ -173,7 +167,7 @@ public class RankEvalRequestIT extends ESIntegTestCase {
private static List<RatedDocument> createRelevant(String... docs) {
List<RatedDocument> relevant = new ArrayList<>();
for (String doc : docs) {
relevant.add(new RatedDocument("test", "testtype", doc, Rating.RELEVANT.ordinal()));
relevant.add(new RatedDocument("test", doc, Rating.RELEVANT.ordinal()));
}
return relevant;
}

View File

@ -78,18 +78,15 @@ public class RankEvalSpecTests extends ESTestCase {
}
templates = new HashSet<>();
templates.add(new ScriptWithId("templateId",
new Script(ScriptType.INLINE, Script.DEFAULT_TEMPLATE_LANG, script, params)));
templates.add(new ScriptWithId("templateId", new Script(ScriptType.INLINE, Script.DEFAULT_TEMPLATE_LANG, script, params)));
Map<String, Object> templateParams = new HashMap<>();
templateParams.put("key", "value");
RatedRequest ratedRequest = new RatedRequest("id",
Arrays.asList(RatedDocumentTests.createRatedDocument()), templateParams,
RatedRequest ratedRequest = new RatedRequest("id", Arrays.asList(RatedDocumentTests.createRatedDocument()), templateParams,
"templateId");
ratedRequests = Arrays.asList(ratedRequest);
} else {
RatedRequest ratedRequest = new RatedRequest("id",
Arrays.asList(RatedDocumentTests.createRatedDocument()),
RatedRequest ratedRequest = new RatedRequest("id", Arrays.asList(RatedDocumentTests.createRatedDocument()),
new SearchSourceBuilder());
ratedRequests = Arrays.asList(ratedRequest);
}
@ -101,15 +98,11 @@ public class RankEvalSpecTests extends ESTestCase {
public void testXContentRoundtrip() throws IOException {
RankEvalSpec testItem = createTestItem();
XContentBuilder shuffled = shuffleXContent(
testItem.toXContent(XContentFactory.jsonBuilder(), ToXContent.EMPTY_PARAMS));
XContentBuilder shuffled = shuffleXContent(testItem.toXContent(XContentFactory.jsonBuilder(), ToXContent.EMPTY_PARAMS));
try (XContentParser parser = createParser(JsonXContent.jsonXContent, shuffled.bytes())) {
RankEvalSpec parsedItem = RankEvalSpec.parse(parser);
// IRL these come from URL parameters - see RestRankEvalAction
// TODO Do we still need this?
// parsedItem.getRatedRequests().stream().forEach(e ->
// {e.setIndices(indices); e.setTypes(types);});
assertNotSame(testItem, parsedItem);
assertEquals(testItem, parsedItem);
assertEquals(testItem.hashCode(), parsedItem.hashCode());
@ -120,17 +113,13 @@ public class RankEvalSpecTests extends ESTestCase {
RankEvalSpec original = createTestItem();
List<NamedWriteableRegistry.Entry> namedWriteables = new ArrayList<>();
namedWriteables.add(new NamedWriteableRegistry.Entry(QueryBuilder.class,
MatchAllQueryBuilder.NAME, MatchAllQueryBuilder::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(RankedListQualityMetric.class,
Precision.NAME, Precision::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(RankedListQualityMetric.class,
DiscountedCumulativeGain.NAME, DiscountedCumulativeGain::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(RankedListQualityMetric.class,
ReciprocalRank.NAME, ReciprocalRank::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(QueryBuilder.class, MatchAllQueryBuilder.NAME, MatchAllQueryBuilder::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(RankedListQualityMetric.class, Precision.NAME, Precision::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(RankedListQualityMetric.class, DiscountedCumulativeGain.NAME,
DiscountedCumulativeGain::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(RankedListQualityMetric.class, ReciprocalRank.NAME, ReciprocalRank::new));
RankEvalSpec deserialized = RankEvalTestHelper.copy(original, RankEvalSpec::new,
new NamedWriteableRegistry(namedWriteables));
RankEvalSpec deserialized = RankEvalTestHelper.copy(original, RankEvalSpec::new, new NamedWriteableRegistry(namedWriteables));
assertEquals(deserialized, original);
assertEquals(deserialized.hashCode(), original.hashCode());
assertNotSame(deserialized, original);
@ -140,20 +129,15 @@ public class RankEvalSpecTests extends ESTestCase {
RankEvalSpec testItem = createTestItem();
List<NamedWriteableRegistry.Entry> namedWriteables = new ArrayList<>();
namedWriteables.add(new NamedWriteableRegistry.Entry(QueryBuilder.class,
MatchAllQueryBuilder.NAME, MatchAllQueryBuilder::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(RankedListQualityMetric.class,
Precision.NAME, Precision::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(RankedListQualityMetric.class,
DiscountedCumulativeGain.NAME, DiscountedCumulativeGain::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(RankedListQualityMetric.class,
ReciprocalRank.NAME, ReciprocalRank::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(QueryBuilder.class, MatchAllQueryBuilder.NAME, MatchAllQueryBuilder::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(RankedListQualityMetric.class, Precision.NAME, Precision::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(RankedListQualityMetric.class, DiscountedCumulativeGain.NAME,
DiscountedCumulativeGain::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(RankedListQualityMetric.class, ReciprocalRank.NAME, ReciprocalRank::new));
RankEvalSpec mutant = RankEvalTestHelper.copy(testItem, RankEvalSpec::new,
new NamedWriteableRegistry(namedWriteables));
RankEvalSpec mutant = RankEvalTestHelper.copy(testItem, RankEvalSpec::new, new NamedWriteableRegistry(namedWriteables));
RankEvalTestHelper.testHashCodeAndEquals(testItem, mutateTestItem(mutant),
RankEvalTestHelper.copy(testItem, RankEvalSpec::new,
new NamedWriteableRegistry(namedWriteables)));
RankEvalTestHelper.copy(testItem, RankEvalSpec::new, new NamedWriteableRegistry(namedWriteables)));
}
private static RankEvalSpec mutateTestItem(RankEvalSpec mutant) {
@ -164,8 +148,7 @@ public class RankEvalSpecTests extends ESTestCase {
int mutate = randomIntBetween(0, 2);
switch (mutate) {
case 0:
RatedRequest request = RatedRequestsTests.createTestItem(new ArrayList<>(),
new ArrayList<>(), true);
RatedRequest request = RatedRequestsTests.createTestItem(new ArrayList<>(), true);
ratedRequests.add(request);
break;
case 1:
@ -176,16 +159,7 @@ public class RankEvalSpecTests extends ESTestCase {
}
break;
case 2:
if (templates.size() > 0) {
String mutatedTemplate = randomAlphaOfLength(10);
templates.put("mutation", new Script(ScriptType.INLINE, "mustache", mutatedTemplate,
new HashMap<>()));
} else {
String mutatedTemplate = randomValueOtherThanMany(templates::containsValue,
() -> randomAlphaOfLength(10));
templates.put("mutation", new Script(ScriptType.INLINE, "mustache", mutatedTemplate,
new HashMap<>()));
}
templates.put("mutation", new Script(ScriptType.INLINE, "mustache", randomAlphaOfLength(10), new HashMap<>()));
break;
default:
throw new IllegalStateException("Requested to modify more than available parameters.");
@ -202,28 +176,24 @@ public class RankEvalSpecTests extends ESTestCase {
public void testMissingRatedRequestsFailsParsing() {
RankedListQualityMetric metric = new Precision();
expectThrows(IllegalStateException.class,
() -> new RankEvalSpec(new ArrayList<>(), metric));
expectThrows(IllegalStateException.class, () -> new RankEvalSpec(new ArrayList<>(), metric));
expectThrows(IllegalStateException.class, () -> new RankEvalSpec(null, metric));
}
public void testMissingMetricFailsParsing() {
List<String> strings = Arrays.asList("value");
List<RatedRequest> ratedRequests = randomList(
() -> RatedRequestsTests.createTestItem(strings, strings, randomBoolean()));
List<RatedRequest> ratedRequests = randomList(() -> RatedRequestsTests.createTestItem(strings, randomBoolean()));
expectThrows(IllegalStateException.class, () -> new RankEvalSpec(ratedRequests, null));
}
public void testMissingTemplateAndSearchRequestFailsParsing() {
List<RatedDocument> ratedDocs = Arrays
.asList(new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1));
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "id1"), 1));
Map<String, Object> params = new HashMap<>();
params.put("key", "value");
RatedRequest request = new RatedRequest("id", ratedDocs, params, "templateId");
List<RatedRequest> ratedRequests = Arrays.asList(request);
expectThrows(IllegalStateException.class,
() -> new RankEvalSpec(ratedRequests, new Precision()));
expectThrows(IllegalStateException.class, () -> new RankEvalSpec(ratedRequests, new Precision()));
}
}

View File

@ -36,6 +36,7 @@ import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
// TODO replace by infra from ESTestCase
public class RankEvalTestHelper {
public static <T> void testHashCodeAndEquals(T testItem, T mutation, T secondCopy) {

View File

@ -32,18 +32,16 @@ public class RatedDocumentTests extends ESTestCase {
public static RatedDocument createRatedDocument() {
String index = randomAlphaOfLength(10);
String type = randomAlphaOfLength(10);
String docId = randomAlphaOfLength(10);
int rating = randomInt();
return new RatedDocument(index, type, docId, rating);
return new RatedDocument(index, docId, rating);
}
public void testXContentParsing() throws IOException {
RatedDocument testItem = createRatedDocument();
XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
XContentBuilder shuffled = shuffleXContent(
testItem.toXContent(builder, ToXContent.EMPTY_PARAMS));
XContentBuilder shuffled = shuffleXContent(testItem.toXContent(builder, ToXContent.EMPTY_PARAMS));
try (XContentParser itemParser = createParser(shuffled)) {
RatedDocument parsedItem = RatedDocument.fromXContent(itemParser);
assertNotSame(testItem, parsedItem);
@ -62,29 +60,22 @@ public class RatedDocumentTests extends ESTestCase {
public void testEqualsAndHash() throws IOException {
RatedDocument testItem = createRatedDocument();
RankEvalTestHelper.testHashCodeAndEquals(testItem, mutateTestItem(testItem),
RankEvalTestHelper.copy(testItem, RatedDocument::new));
RankEvalTestHelper.testHashCodeAndEquals(testItem, mutateTestItem(testItem), RankEvalTestHelper.copy(testItem, RatedDocument::new));
}
public void testInvalidParsing() {
expectThrows(IllegalArgumentException.class,
() -> new RatedDocument(null, "abc", "abc", 10));
expectThrows(IllegalArgumentException.class, () -> new RatedDocument("", "abc", "abc", 10));
expectThrows(IllegalArgumentException.class,
() -> new RatedDocument("abc", null, "abc", 10));
expectThrows(IllegalArgumentException.class, () -> new RatedDocument("abc", "", "abc", 10));
expectThrows(IllegalArgumentException.class,
() -> new RatedDocument("abc", "abc", null, 10));
expectThrows(IllegalArgumentException.class, () -> new RatedDocument("abc", "abc", "", 10));
expectThrows(IllegalArgumentException.class, () -> new RatedDocument(null, "abc", 10));
expectThrows(IllegalArgumentException.class, () -> new RatedDocument("", "abc", 10));
expectThrows(IllegalArgumentException.class, () -> new RatedDocument("abc", "", 10));
expectThrows(IllegalArgumentException.class, () -> new RatedDocument("abc", null, 10));
}
private static RatedDocument mutateTestItem(RatedDocument original) {
int rating = original.getRating();
String index = original.getIndex();
String type = original.getType();
String docId = original.getDocID();
switch (randomIntBetween(0, 3)) {
switch (randomIntBetween(0, 2)) {
case 0:
rating = randomValueOtherThan(rating, () -> randomInt());
break;
@ -92,14 +83,11 @@ public class RatedDocumentTests extends ESTestCase {
index = randomValueOtherThan(index, () -> randomAlphaOfLength(10));
break;
case 2:
type = randomValueOtherThan(type, () -> randomAlphaOfLength(10));
break;
case 3:
docId = randomValueOtherThan(docId, () -> randomAlphaOfLength(10));
break;
default:
throw new IllegalStateException("The test should only allow two parameters mutated");
}
return new RatedDocument(index, type, docId, rating);
return new RatedDocument(index, docId, rating);
}
}

View File

@ -57,9 +57,9 @@ public class RatedRequestsTests extends ESTestCase {
*/
@BeforeClass
public static void init() {
xContentRegistry = new NamedXContentRegistry(Stream.of(
new SearchModule(Settings.EMPTY, false, emptyList()).getNamedXContents().stream())
.flatMap(Function.identity()).collect(toList()));
xContentRegistry = new NamedXContentRegistry(
Stream.of(new SearchModule(Settings.EMPTY, false, emptyList()).getNamedXContents().stream()).flatMap(Function.identity())
.collect(toList()));
}
@AfterClass
@ -72,8 +72,7 @@ public class RatedRequestsTests extends ESTestCase {
return xContentRegistry;
}
public static RatedRequest createTestItem(List<String> indices, List<String> types,
boolean forceRequest) {
public static RatedRequest createTestItem(List<String> indices, boolean forceRequest) {
String requestId = randomAlphaOfLength(50);
List<RatedDocument> ratedDocs = new ArrayList<>();
@ -105,12 +104,10 @@ public class RatedRequestsTests extends ESTestCase {
if (params.size() == 0) {
ratedRequest = new RatedRequest(requestId, ratedDocs, testRequest);
ratedRequest.setIndices(indices);
ratedRequest.setTypes(types);
ratedRequest.setSummaryFields(summaryFields);
} else {
ratedRequest = new RatedRequest(requestId, ratedDocs, params, randomAlphaOfLength(5));
ratedRequest.setIndices(indices);
ratedRequest.setTypes(types);
ratedRequest.setSummaryFields(summaryFields);
}
return ratedRequest;
@ -123,25 +120,14 @@ public class RatedRequestsTests extends ESTestCase {
indices.add(randomAlphaOfLengthBetween(0, 50));
}
List<String> types = new ArrayList<>();
size = randomIntBetween(0, 20);
for (int i = 0; i < size; i++) {
types.add(randomAlphaOfLengthBetween(0, 50));
}
RatedRequest testItem = createTestItem(indices, types, randomBoolean());
RatedRequest testItem = createTestItem(indices, randomBoolean());
XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
XContentBuilder shuffled = shuffleXContent(
testItem.toXContent(builder, ToXContent.EMPTY_PARAMS));
XContentBuilder shuffled = shuffleXContent(testItem.toXContent(builder, ToXContent.EMPTY_PARAMS));
try (XContentParser itemParser = createParser(shuffled)) {
itemParser.nextToken();
RatedRequest parsedItem = RatedRequest.fromXContent(itemParser);
parsedItem.setIndices(indices); // IRL these come from URL
// parameters - see
// RestRankEvalAction
parsedItem.setTypes(types); // IRL these come from URL parameters -
// see RestRankEvalAction
parsedItem.setIndices(indices); // IRL these come from URL parameters - see RestRankEvalAction
assertNotSame(testItem, parsedItem);
assertEquals(testItem, parsedItem);
assertEquals(testItem.hashCode(), parsedItem.hashCode());
@ -155,20 +141,12 @@ public class RatedRequestsTests extends ESTestCase {
indices.add(randomAlphaOfLengthBetween(0, 50));
}
List<String> types = new ArrayList<>();
size = randomIntBetween(0, 20);
for (int i = 0; i < size; i++) {
types.add(randomAlphaOfLengthBetween(0, 50));
}
RatedRequest original = createTestItem(indices, types, randomBoolean());
RatedRequest original = createTestItem(indices, randomBoolean());
List<NamedWriteableRegistry.Entry> namedWriteables = new ArrayList<>();
namedWriteables.add(new NamedWriteableRegistry.Entry(QueryBuilder.class,
MatchAllQueryBuilder.NAME, MatchAllQueryBuilder::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(QueryBuilder.class, MatchAllQueryBuilder.NAME, MatchAllQueryBuilder::new));
RatedRequest deserialized = RankEvalTestHelper.copy(original, RatedRequest::new,
new NamedWriteableRegistry(namedWriteables));
RatedRequest deserialized = RankEvalTestHelper.copy(original, RatedRequest::new, new NamedWriteableRegistry(namedWriteables));
assertEquals(deserialized, original);
assertEquals(deserialized.hashCode(), original.hashCode());
assertNotSame(deserialized, original);
@ -181,21 +159,13 @@ public class RatedRequestsTests extends ESTestCase {
indices.add(randomAlphaOfLengthBetween(0, 50));
}
List<String> types = new ArrayList<>();
size = randomIntBetween(0, 20);
for (int i = 0; i < size; i++) {
types.add(randomAlphaOfLengthBetween(0, 50));
}
RatedRequest testItem = createTestItem(indices, types, randomBoolean());
RatedRequest testItem = createTestItem(indices, randomBoolean());
List<NamedWriteableRegistry.Entry> namedWriteables = new ArrayList<>();
namedWriteables.add(new NamedWriteableRegistry.Entry(QueryBuilder.class,
MatchAllQueryBuilder.NAME, MatchAllQueryBuilder::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(QueryBuilder.class, MatchAllQueryBuilder.NAME, MatchAllQueryBuilder::new));
RankEvalTestHelper.testHashCodeAndEquals(testItem, mutateTestItem(testItem),
RankEvalTestHelper.copy(testItem, RatedRequest::new,
new NamedWriteableRegistry(namedWriteables)));
RankEvalTestHelper.copy(testItem, RatedRequest::new, new NamedWriteableRegistry(namedWriteables)));
}
private static RatedRequest mutateTestItem(RatedRequest original) {
@ -203,12 +173,11 @@ public class RatedRequestsTests extends ESTestCase {
SearchSourceBuilder testRequest = original.getTestRequest();
List<RatedDocument> ratedDocs = original.getRatedDocs();
List<String> indices = original.getIndices();
List<String> types = original.getTypes();
Map<String, Object> params = original.getParams();
List<String> summaryFields = original.getSummaryFields();
String templateId = original.getTemplateId();
int mutate = randomIntBetween(0, 5);
int mutate = randomIntBetween(0, 4);
switch (mutate) {
case 0:
id = randomValueOtherThan(id, () -> randomAlphaOfLength(10));
@ -231,120 +200,95 @@ public class RatedRequestsTests extends ESTestCase {
}
break;
case 2:
ratedDocs = Arrays.asList(randomValueOtherThanMany(ratedDocs::contains,
() -> RatedDocumentTests.createRatedDocument()));
ratedDocs = Arrays.asList(randomValueOtherThanMany(ratedDocs::contains, () -> RatedDocumentTests.createRatedDocument()));
break;
case 3:
indices = Arrays.asList(
randomValueOtherThanMany(indices::contains, () -> randomAlphaOfLength(10)));
indices = Arrays.asList(randomValueOtherThanMany(indices::contains, () -> randomAlphaOfLength(10)));
break;
case 4:
types = Arrays.asList(
randomValueOtherThanMany(types::contains, () -> randomAlphaOfLength(10)));
break;
case 5:
summaryFields = Arrays.asList(randomValueOtherThanMany(summaryFields::contains,
() -> randomAlphaOfLength(10)));
summaryFields = Arrays.asList(randomValueOtherThanMany(summaryFields::contains, () -> randomAlphaOfLength(10)));
break;
default:
throw new IllegalStateException("Requested to modify more than available parameters.");
}
RatedRequest ratedRequest = new RatedRequest(id, ratedDocs, testRequest, params,
templateId);
RatedRequest ratedRequest = new RatedRequest(id, ratedDocs, testRequest, params, templateId);
ratedRequest.setIndices(indices);
ratedRequest.setTypes(types);
ratedRequest.setSummaryFields(summaryFields);
return ratedRequest;
}
public void testDuplicateRatedDocThrowsException() {
List<RatedDocument> ratedDocs = Arrays.asList(
new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1),
new RatedDocument(new DocumentKey("index1", "type1", "id1"), 5));
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "id1"), 1),
new RatedDocument(new DocumentKey("index1", "id1"), 5));
// search request set, no summary fields
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> new RatedRequest("id", ratedDocs, new SearchSourceBuilder()));
assertEquals(
"Found duplicate rated document key [{\"_index\":\"index1\","
+ "\"_type\":\"type1\",\"_id\":\"id1\"}]",
assertEquals("Found duplicate rated document key [{\"_index\":\"index1\",\"_id\":\"id1\"}]",
ex.getMessage());
// templated path, no summary fields
Map<String, Object> params = new HashMap<>();
params.put("key", "value");
ex = expectThrows(IllegalArgumentException.class,
() -> new RatedRequest("id", ratedDocs, params, "templateId"));
assertEquals(
"Found duplicate rated document key [{\"_index\":\"index1\","
+ "\"_type\":\"type1\",\"_id\":\"id1\"}]",
ex = expectThrows(IllegalArgumentException.class, () -> new RatedRequest("id", ratedDocs, params, "templateId"));
assertEquals("Found duplicate rated document key [{\"_index\":\"index1\",\"_id\":\"id1\"}]",
ex.getMessage());
}
public void testNullSummaryFieldsTreatment() {
List<RatedDocument> ratedDocs = Arrays
.asList(new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1));
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "id1"), 1));
RatedRequest request = new RatedRequest("id", ratedDocs, new SearchSourceBuilder());
expectThrows(IllegalArgumentException.class, () -> request.setSummaryFields(null));
}
public void testNullParamsTreatment() {
List<RatedDocument> ratedDocs = Arrays
.asList(new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1));
RatedRequest request = new RatedRequest("id", ratedDocs, new SearchSourceBuilder(), null,
null);
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "id1"), 1));
RatedRequest request = new RatedRequest("id", ratedDocs, new SearchSourceBuilder(), null, null);
assertNotNull(request.getParams());
}
public void testSettingParamsAndRequestThrows() {
List<RatedDocument> ratedDocs = Arrays
.asList(new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1));
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "id1"), 1));
Map<String, Object> params = new HashMap<>();
params.put("key", "value");
expectThrows(IllegalArgumentException.class,
() -> new RatedRequest("id", ratedDocs, new SearchSourceBuilder(), params, null));
expectThrows(IllegalArgumentException.class, () -> new RatedRequest("id", ratedDocs, new SearchSourceBuilder(), params, null));
}
public void testSettingNeitherParamsNorRequestThrows() {
List<RatedDocument> ratedDocs = Arrays
.asList(new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1));
expectThrows(IllegalArgumentException.class,
() -> new RatedRequest("id", ratedDocs, null, null));
expectThrows(IllegalArgumentException.class,
() -> new RatedRequest("id", ratedDocs, null, new HashMap<>(), "templateId"));
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "id1"), 1));
expectThrows(IllegalArgumentException.class, () -> new RatedRequest("id", ratedDocs, null, null));
expectThrows(IllegalArgumentException.class, () -> new RatedRequest("id", ratedDocs, null, new HashMap<>(), "templateId"));
}
public void testSettingParamsWithoutTemplateIdThrows() {
List<RatedDocument> ratedDocs = Arrays
.asList(new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1));
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "id1"), 1));
Map<String, Object> params = new HashMap<>();
params.put("key", "value");
expectThrows(IllegalArgumentException.class,
() -> new RatedRequest("id", ratedDocs, null, params, null));
expectThrows(IllegalArgumentException.class, () -> new RatedRequest("id", ratedDocs, null, params, null));
}
public void testSettingTemplateIdAndRequestThrows() {
List<RatedDocument> ratedDocs = Arrays
.asList(new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1));
expectThrows(IllegalArgumentException.class, () -> new RatedRequest("id", ratedDocs,
new SearchSourceBuilder(), null, "templateId"));
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "id1"), 1));
expectThrows(IllegalArgumentException.class,
() -> new RatedRequest("id", ratedDocs, new SearchSourceBuilder(), null, "templateId"));
}
public void testSettingTemplateIdNoParamsThrows() {
List<RatedDocument> ratedDocs = Arrays
.asList(new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1));
expectThrows(IllegalArgumentException.class,
() -> new RatedRequest("id", ratedDocs, null, null, "templateId"));
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "id1"), 1));
expectThrows(IllegalArgumentException.class, () -> new RatedRequest("id", ratedDocs, null, null, "templateId"));
}
/**
* test that modifying the order of index/type/docId to make sure it doesn't
* test that modifying the order of index/docId to make sure it doesn't
* matter for parsing xContent
*/
public void testParseFromXContent() throws IOException {
String querySpecString = " {\n" + " \"id\": \"my_qa_query\",\n" + " \"request\": {\n"
+ " \"query\": {\n" + " \"bool\": {\n"
String querySpecString = " {\n"
+ " \"id\": \"my_qa_query\",\n"
+ " \"request\": {\n"
+ " \"query\": {\n"
+ " \"bool\": {\n"
+ " \"must\": [\n"
+ " {\"match\": {\"beverage\": \"coffee\"}},\n"
+ " {\"term\": {\"browser\": {\"value\": \"safari\"}}},\n"
@ -352,16 +296,15 @@ public class RatedRequestsTests extends ESTestCase {
+ " {\"value\": \"morning\",\"boost\": 2}}},\n"
+ " {\"term\": {\"ip_location\": "
+ " {\"value\": \"ams\",\"boost\": 10}}}]}\n"
+ " },\n" + " \"size\": 10\n" + " },\n"
+ " },\n"
+ " \"size\": 10\n"
+ " },\n"
+ " \"summary_fields\" : [\"title\"],\n"
+ " \"ratings\": [\n"
+ " {\"_index\": \"test\", \"_type\": \"testtype\", "
+ " \"_id\": \"1\", \"rating\" : 1 }, "
+ " {\"_type\": \"testtype\", \"_index\": \"test\", "
+ " \"_id\": \"2\", \"rating\" : 0 }, "
+ " {\"_id\": \"3\", \"_index\": \"test\", "
+ " \"_type\": \"testtype\", \"rating\" : 1 }]\n"
+ "}";
+ " {\"_index\": \"test\" , \"_id\": \"1\", \"rating\" : 1 },\n"
+ " {\"_index\": \"test\", \"rating\" : 0, \"_id\": \"2\"},\n"
+ " {\"_id\": \"3\", \"_index\": \"test\", \"rating\" : 1} ]"
+ "}\n";
try (XContentParser parser = createParser(JsonXContent.jsonXContent, querySpecString)) {
RatedRequest specification = RatedRequest.fromXContent(parser);
assertEquals("my_qa_query", specification.getId());
@ -371,7 +314,6 @@ public class RatedRequestsTests extends ESTestCase {
for (int i = 0; i < 3; i++) {
assertEquals("" + (i + 1), ratedDocs.get(i).getDocID());
assertEquals("test", ratedDocs.get(i).getIndex());
assertEquals("testtype", ratedDocs.get(i).getType());
if (i == 1) {
assertEquals(0, ratedDocs.get(i).getRating());
} else {

View File

@ -45,75 +45,67 @@ public class ReciprocalRankTests extends ESTestCase {
int searchHits = randomIntBetween(1, 50);
SearchHit[] hits = createSearchHits(0, searchHits, "test", "type");
SearchHit[] hits = createSearchHits(0, searchHits, "test");
List<RatedDocument> ratedDocs = new ArrayList<>();
int relevantAt = randomIntBetween(0, searchHits);
for (int i = 0; i <= searchHits; i++) {
if (i == relevantAt) {
ratedDocs.add(new RatedDocument("test", "type", Integer.toString(i),
Rating.RELEVANT.ordinal()));
ratedDocs.add(new RatedDocument("test", Integer.toString(i), Rating.RELEVANT.ordinal()));
} else {
ratedDocs.add(new RatedDocument("test", "type", Integer.toString(i),
Rating.IRRELEVANT.ordinal()));
ratedDocs.add(new RatedDocument("test", Integer.toString(i), Rating.IRRELEVANT.ordinal()));
}
}
int rankAtFirstRelevant = relevantAt + 1;
EvalQueryQuality evaluation = reciprocalRank.evaluate("id", hits, ratedDocs);
assertEquals(1.0 / rankAtFirstRelevant, evaluation.getQualityLevel(), Double.MIN_VALUE);
assertEquals(rankAtFirstRelevant,
((ReciprocalRank.Breakdown) evaluation.getMetricDetails()).getFirstRelevantRank());
assertEquals(rankAtFirstRelevant, ((ReciprocalRank.Breakdown) evaluation.getMetricDetails()).getFirstRelevantRank());
// check that if we have fewer search hits than relevant doc position,
// we don't find any result and get 0.0 quality level
reciprocalRank = new ReciprocalRank();
evaluation = reciprocalRank.evaluate("id", Arrays.copyOfRange(hits, 0, relevantAt),
ratedDocs);
evaluation = reciprocalRank.evaluate("id", Arrays.copyOfRange(hits, 0, relevantAt), ratedDocs);
assertEquals(0.0, evaluation.getQualityLevel(), Double.MIN_VALUE);
}
public void testEvaluationOneRelevantInResults() {
ReciprocalRank reciprocalRank = new ReciprocalRank();
SearchHit[] hits = createSearchHits(0, 9, "test", "type");
SearchHit[] hits = createSearchHits(0, 9, "test");
List<RatedDocument> ratedDocs = new ArrayList<>();
// mark one of the ten docs relevant
int relevantAt = randomIntBetween(0, 9);
for (int i = 0; i <= 20; i++) {
if (i == relevantAt) {
ratedDocs.add(new RatedDocument("test", "type", Integer.toString(i),
Rating.RELEVANT.ordinal()));
ratedDocs.add(new RatedDocument("test", Integer.toString(i), Rating.RELEVANT.ordinal()));
} else {
ratedDocs.add(new RatedDocument("test", "type", Integer.toString(i),
Rating.IRRELEVANT.ordinal()));
ratedDocs.add(new RatedDocument("test", Integer.toString(i), Rating.IRRELEVANT.ordinal()));
}
}
EvalQueryQuality evaluation = reciprocalRank.evaluate("id", hits, ratedDocs);
assertEquals(1.0 / (relevantAt + 1), evaluation.getQualityLevel(), Double.MIN_VALUE);
assertEquals(relevantAt + 1,
((ReciprocalRank.Breakdown) evaluation.getMetricDetails()).getFirstRelevantRank());
assertEquals(relevantAt + 1, ((ReciprocalRank.Breakdown) evaluation.getMetricDetails()).getFirstRelevantRank());
}
/**
* test that the relevant rating threshold can be set to something larger
* than 1. e.g. we set it to 2 here and expect dics 0-2 to be not relevant,
* so first relevant doc has third ranking position, so RR should be 1/3
* test that the relevant rating threshold can be set to something larger than
* 1. e.g. we set it to 2 here and expect dics 0-2 to be not relevant, so first
* relevant doc has third ranking position, so RR should be 1/3
*/
public void testPrecisionAtFiveRelevanceThreshold() {
List<RatedDocument> rated = new ArrayList<>();
rated.add(new RatedDocument("test", "testtype", "0", 0));
rated.add(new RatedDocument("test", "testtype", "1", 1));
rated.add(new RatedDocument("test", "testtype", "2", 2));
rated.add(new RatedDocument("test", "testtype", "3", 3));
rated.add(new RatedDocument("test", "testtype", "4", 4));
SearchHit[] hits = createSearchHits(0, 5, "test", "testtype");
rated.add(new RatedDocument("test", "0", 0));
rated.add(new RatedDocument("test", "1", 1));
rated.add(new RatedDocument("test", "2", 2));
rated.add(new RatedDocument("test", "3", 3));
rated.add(new RatedDocument("test", "4", 4));
SearchHit[] hits = createSearchHits(0, 5, "test");
ReciprocalRank reciprocalRank = new ReciprocalRank();
reciprocalRank.setRelevantRatingThreshhold(2);
EvalQueryQuality evaluation = reciprocalRank.evaluate("id", hits, rated);
assertEquals((double) 1 / 3, evaluation.getQualityLevel(), 0.00001);
assertEquals(3,
((ReciprocalRank.Breakdown) evaluation.getMetricDetails()).getFirstRelevantRank());
assertEquals(3, ((ReciprocalRank.Breakdown) evaluation.getMetricDetails()).getFirstRelevantRank());
}
public void testCombine() {
@ -127,7 +119,7 @@ public class ReciprocalRankTests extends ESTestCase {
public void testEvaluationNoRelevantInResults() {
ReciprocalRank reciprocalRank = new ReciprocalRank();
SearchHit[] hits = createSearchHits(0, 9, "test", "type");
SearchHit[] hits = createSearchHits(0, 9, "test");
List<RatedDocument> ratedDocs = new ArrayList<>();
EvalQueryQuality evaluation = reciprocalRank.evaluate("id", hits, ratedDocs);
assertEquals(0.0, evaluation.getQualityLevel(), Double.MIN_VALUE);
@ -136,8 +128,7 @@ public class ReciprocalRankTests extends ESTestCase {
public void testXContentRoundtrip() throws IOException {
ReciprocalRank testItem = createTestItem();
XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
XContentBuilder shuffled = shuffleXContent(
testItem.toXContent(builder, ToXContent.EMPTY_PARAMS));
XContentBuilder shuffled = shuffleXContent(testItem.toXContent(builder, ToXContent.EMPTY_PARAMS));
try (XContentParser itemParser = createParser(shuffled)) {
itemParser.nextToken();
itemParser.nextToken();
@ -149,13 +140,13 @@ public class ReciprocalRankTests extends ESTestCase {
}
/**
* Create SearchHits for testing, starting from dociId 'from' up to docId
* 'to'. The search hits index and type also need to be provided
* Create SearchHits for testing, starting from dociId 'from' up to docId 'to'.
* The search hits index also need to be provided
*/
private static SearchHit[] createSearchHits(int from, int to, String index, String type) {
private static SearchHit[] createSearchHits(int from, int to, String index) {
SearchHit[] hits = new SearchHit[to + 1 - from];
for (int i = from; i <= to; i++) {
hits[i] = new SearchHit(i, i + "", new Text(type), Collections.emptyMap());
hits[i] = new SearchHit(i, i + "", new Text(""), Collections.emptyMap());
hits[i].shard(new SearchShardTarget("testnode", new Index(index, "uuid"), 0, null));
}
return hits;
@ -185,8 +176,7 @@ public class ReciprocalRankTests extends ESTestCase {
private static ReciprocalRank mutateTestItem(ReciprocalRank testItem) {
int relevantThreshold = testItem.getRelevantRatingThreshold();
ReciprocalRank rank = new ReciprocalRank();
rank.setRelevantRatingThreshhold(
randomValueOtherThan(relevantThreshold, () -> randomIntBetween(0, 10)));
rank.setRelevantRatingThreshhold(randomValueOtherThan(relevantThreshold, () -> randomIntBetween(0, 10)));
return rank;
}

View File

@ -46,14 +46,14 @@
"id": "amsterdam_query",
"request": { "query": { "match" : {"text" : "amsterdam" }}},
"ratings": [
{"_index": "foo", "_type": "bar", "_id": "doc1", "rating": 0},
{"_index": "foo", "_type": "bar", "_id": "doc2", "rating": 1},
{"_index": "foo", "_type": "bar", "_id": "doc3", "rating": 1}]
{"_index": "foo", "_id": "doc1", "rating": 0},
{"_index": "foo", "_id": "doc2", "rating": 1},
{"_index": "foo", "_id": "doc3", "rating": 1}]
},
{
"id" : "berlin_query",
"request": { "query": { "match" : { "text" : "berlin" } }, "size" : 10 },
"ratings": [{"_index": "foo", "_type": "bar", "_id": "doc1", "rating": 1}]
"ratings": [{"_index": "foo", "_id": "doc1", "rating": 1}]
}
],
"metric" : { "precision": { "ignore_unlabeled" : true }}
@ -61,7 +61,7 @@
- match: { rank_eval.quality_level: 1}
- match: { rank_eval.details.amsterdam_query.quality_level: 1.0}
- match: { rank_eval.details.amsterdam_query.unknown_docs: [ {"_index": "foo", "_type": "bar", "_id": "doc4"}]}
- match: { rank_eval.details.amsterdam_query.unknown_docs: [ {"_index": "foo", "_id": "doc4"}]}
- match: { rank_eval.details.amsterdam_query.metric_details: {"relevant_docs_retrieved": 2, "docs_retrieved": 2}}
- length: { rank_eval.details.amsterdam_query.hits: 3}
@ -73,7 +73,7 @@
- is_false: rank_eval.details.amsterdam_query.hits.2.rating
- match: { rank_eval.details.berlin_query.quality_level: 1.0}
- match: { rank_eval.details.berlin_query.unknown_docs: [ {"_index": "foo", "_type": "bar", "_id": "doc4"}]}
- match: { rank_eval.details.berlin_query.unknown_docs: [ {"_index": "foo", "_id": "doc4"}]}
- match: { rank_eval.details.berlin_query.metric_details: {"relevant_docs_retrieved": 1, "docs_retrieved": 1}}
- length: { rank_eval.details.berlin_query.hits: 2}
- match: { rank_eval.details.berlin_query.hits.0.hit._id: "doc1" }
@ -130,13 +130,13 @@
"id": "amsterdam_query",
"request": { "query": { "match" : {"text" : "amsterdam" }}},
# doc4 should be returned in third position, so reciprocal rank is 1/3
"ratings": [{"_index": "foo", "_type": "bar", "_id": "doc4", "rating": 1}]
"ratings": [{"_index": "foo", "_id": "doc4", "rating": 1}]
},
{
"id" : "berlin_query",
"request": { "query": { "match" : { "text" : "berlin" } }, "size" : 10 },
# doc1 should be returned in first position, doc3 in second, so reciprocal rank is 1/2
"ratings": [{"_index": "foo", "_type": "bar", "_id": "doc4", "rating": 1}]
"ratings": [{"_index": "foo", "_id": "doc4", "rating": 1}]
}
],
"metric" : { "reciprocal_rank": {} }
@ -146,9 +146,9 @@
- match: {rank_eval.quality_level: 0.41666666666666663}
- match: {rank_eval.details.amsterdam_query.quality_level: 0.3333333333333333}
- match: {rank_eval.details.amsterdam_query.metric_details: {"first_relevant": 3}}
- match: {rank_eval.details.amsterdam_query.unknown_docs: [ {"_index": "foo", "_type": "bar", "_id": "doc2"},
{"_index": "foo", "_type": "bar", "_id": "doc3"} ]}
- match: {rank_eval.details.amsterdam_query.unknown_docs: [ {"_index": "foo", "_id": "doc2"},
{"_index": "foo", "_id": "doc3"} ]}
- match: {rank_eval.details.berlin_query.quality_level: 0.5}
- match: {rank_eval.details.berlin_query.metric_details: {"first_relevant": 2}}
- match: {rank_eval.details.berlin_query.unknown_docs: [ {"_index": "foo", "_type": "bar", "_id": "doc1"}]}
- match: {rank_eval.details.berlin_query.unknown_docs: [ {"_index": "foo", "_id": "doc1"}]}

View File

@ -54,12 +54,12 @@
"id": "dcg_query",
"request": { "query": { "match_all" : {}}, "sort" : [ "bar" ] },
"ratings": [
{"_index" : "foo", "_type" : "bar", "_id" : "doc1", "rating": 3},
{"_index" : "foo", "_type" : "bar", "_id" : "doc2", "rating": 2},
{"_index" : "foo", "_type" : "bar", "_id" : "doc3", "rating": 3},
{"_index" : "foo", "_type" : "bar", "_id" : "doc4", "rating": 0},
{"_index" : "foo", "_type" : "bar", "_id" : "doc5", "rating": 1},
{"_index" : "foo", "_type" : "bar", "_id" : "doc6", "rating": 2}]
{"_index" : "foo", "_id" : "doc1", "rating": 3},
{"_index" : "foo", "_id" : "doc2", "rating": 2},
{"_index" : "foo", "_id" : "doc3", "rating": 3},
{"_index" : "foo", "_id" : "doc4", "rating": 0},
{"_index" : "foo", "_id" : "doc5", "rating": 1},
{"_index" : "foo", "_id" : "doc6", "rating": 2}]
}
],
"metric" : { "dcg": {}}
@ -79,12 +79,12 @@
"id": "dcg_query_reverse",
"request": { "query": { "match_all" : {}}, "sort" : [ {"bar" : "desc" }] },
"ratings": [
{"_index" : "foo", "_type" : "bar", "_id" : "doc1", "rating": 3},
{"_index" : "foo", "_type" : "bar", "_id" : "doc2", "rating": 2},
{"_index" : "foo", "_type" : "bar", "_id" : "doc3", "rating": 3},
{"_index" : "foo", "_type" : "bar", "_id" : "doc4", "rating": 0},
{"_index" : "foo", "_type" : "bar", "_id" : "doc5", "rating": 1},
{"_index" : "foo", "_type" : "bar", "_id" : "doc6", "rating": 2}]
{"_index" : "foo", "_id" : "doc1", "rating": 3},
{"_index" : "foo", "_id" : "doc2", "rating": 2},
{"_index" : "foo", "_id" : "doc3", "rating": 3},
{"_index" : "foo", "_id" : "doc4", "rating": 0},
{"_index" : "foo", "_id" : "doc5", "rating": 1},
{"_index" : "foo", "_id" : "doc6", "rating": 2}]
},
],
"metric" : { "dcg": { }}
@ -104,23 +104,23 @@
"id": "dcg_query",
"request": { "query": { "match_all" : {}}, "sort" : [ "bar" ] },
"ratings": [
{"_index" : "foo", "_type" : "bar", "_id" : "doc1", "rating": 3},
{"_index" : "foo", "_type" : "bar", "_id" : "doc2", "rating": 2},
{"_index" : "foo", "_type" : "bar", "_id" : "doc3", "rating": 3},
{"_index" : "foo", "_type" : "bar", "_id" : "doc4", "rating": 0},
{"_index" : "foo", "_type" : "bar", "_id" : "doc5", "rating": 1},
{"_index" : "foo", "_type" : "bar", "_id" : "doc6", "rating": 2}]
{"_index" : "foo", "_id" : "doc1", "rating": 3},
{"_index" : "foo", "_id" : "doc2", "rating": 2},
{"_index" : "foo", "_id" : "doc3", "rating": 3},
{"_index" : "foo", "_id" : "doc4", "rating": 0},
{"_index" : "foo", "_id" : "doc5", "rating": 1},
{"_index" : "foo", "_id" : "doc6", "rating": 2}]
},
{
"id": "dcg_query_reverse",
"request": { "query": { "match_all" : {}}, "sort" : [ {"bar" : "desc" }] },
"ratings": [
{"_index" : "foo", "_type" : "bar", "_id" : "doc1", "rating": 3},
{"_index" : "foo", "_type" : "bar", "_id" : "doc2", "rating": 2},
{"_index" : "foo", "_type" : "bar", "_id" : "doc3", "rating": 3},
{"_index" : "foo", "_type" : "bar", "_id" : "doc4", "rating": 0},
{"_index" : "foo", "_type" : "bar", "_id" : "doc5", "rating": 1},
{"_index" : "foo", "_type" : "bar", "_id" : "doc6", "rating": 2}]
{"_index" : "foo", "_id" : "doc1", "rating": 3},
{"_index" : "foo", "_id" : "doc2", "rating": 2},
{"_index" : "foo", "_id" : "doc3", "rating": 3},
{"_index" : "foo", "_id" : "doc4", "rating": 0},
{"_index" : "foo", "_id" : "doc5", "rating": 1},
{"_index" : "foo", "_id" : "doc6", "rating": 2}]
},
],
"metric" : { "dcg": { }}

View File

@ -19,12 +19,12 @@
"id": "amsterdam_query",
"request": { "query": { "match_all" : { }}},
"ratings": [
{"_index": "foo", "_type": "bar", "_id": "doc1", "rating": 1}]
{"_index": "foo", "_id": "doc1", "rating": 1}]
},
{
"id" : "invalid_query",
"request": { "query": { "range" : { "bar" : { "from" : "Basel", "time_zone": "+01:00" }}}},
"ratings": [{"_index": "foo", "_type": "bar", "_id": "doc1", "rating": 1}]
"ratings": [{"_index": "foo", "_id": "doc1", "rating": 1}]
}
],
"metric" : { "precision": { "ignore_unlabeled" : true }}

View File

@ -26,9 +26,9 @@ import org.elasticsearch.index.rankeval.RankEvalRequest;
import org.elasticsearch.index.rankeval.RankEvalRequestBuilder;
import org.elasticsearch.index.rankeval.RankEvalResponse;
import org.elasticsearch.index.rankeval.RankEvalSpec;
import org.elasticsearch.index.rankeval.RankEvalSpec.ScriptWithId;
import org.elasticsearch.index.rankeval.RatedDocument;
import org.elasticsearch.index.rankeval.RatedRequest;
import org.elasticsearch.index.rankeval.RankEvalSpec.ScriptWithId;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
@ -82,7 +82,6 @@ public class SmokeMultipleTemplatesIT extends ESIntegTestCase {
public void testPrecisionAtRequest() throws IOException {
List<String> indices = Arrays.asList(new String[] { "test" });
List<String> types = Arrays.asList(new String[] { "testtype" });
List<RatedRequest> specifications = new ArrayList<>();
Map<String, Object> ams_params = new HashMap<>();
@ -90,7 +89,6 @@ public class SmokeMultipleTemplatesIT extends ESIntegTestCase {
RatedRequest amsterdamRequest = new RatedRequest(
"amsterdam_query", createRelevant("2", "3", "4", "5"), ams_params, MATCH_TEMPLATE);
amsterdamRequest.setIndices(indices);
amsterdamRequest.setTypes(types);
specifications.add(amsterdamRequest);
@ -99,12 +97,11 @@ public class SmokeMultipleTemplatesIT extends ESIntegTestCase {
RatedRequest berlinRequest = new RatedRequest(
"berlin_query", createRelevant("1"), berlin_params, MATCH_TEMPLATE);
berlinRequest.setIndices(indices);
berlinRequest.setTypes(types);
specifications.add(berlinRequest);
Precision metric = new Precision();
ScriptWithId template =
ScriptWithId template =
new ScriptWithId(
MATCH_TEMPLATE,
new Script(
@ -124,7 +121,7 @@ public class SmokeMultipleTemplatesIT extends ESIntegTestCase {
private static List<RatedDocument> createRelevant(String... docs) {
List<RatedDocument> relevant = new ArrayList<>();
for (String doc : docs) {
relevant.add(new RatedDocument("test", "testtype", doc, Rating.RELEVANT.ordinal()));
relevant.add(new RatedDocument("test", doc, Rating.RELEVANT.ordinal()));
}
return relevant;
}

View File

@ -41,22 +41,22 @@
- do:
rank_eval:
body: {
"templates": [ { "id": "match", "template": {"inline": "{\"query\": { \"match\" : {\"text\" : \"{{query_string}}\" }}}" }} ],
"templates": [ { "id": "match", "template": {"source": "{\"query\": { \"match\" : {\"text\" : \"{{query_string}}\" }}}" }} ],
"requests" : [
{
"id": "amsterdam_query",
"params": { "query_string": "amsterdam" },
"template_id": "match",
"ratings": [
{"_index": "foo", "_type": "bar", "_id": "doc1", "rating": 0},
{"_index": "foo", "_type": "bar", "_id": "doc2", "rating": 1},
{"_index": "foo", "_type": "bar", "_id": "doc3", "rating": 1}]
{"_index": "foo", "_id": "doc1", "rating": 0},
{"_index": "foo", "_id": "doc2", "rating": 1},
{"_index": "foo", "_id": "doc3", "rating": 1}]
},
{
"id" : "berlin_query",
"params": { "query_string": "berlin" },
"template_id": "match",
"ratings": [{"_index": "foo", "_type": "bar", "_id": "doc1", "rating": 1}]
"ratings": [{"_index": "foo", "_id": "doc1", "rating": 1}]
}
],
"metric" : { "precision": { }}