mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-09 06:25:07 +00:00
Merge pull request #19648 from MaineC/feature/rank-eval_index_type_to_id
Add fields index and type to rated documents
This commit is contained in:
commit
bd51c315d6
@ -126,16 +126,16 @@ public class DiscountedCumulativeGainAt extends RankedListQualityMetric {
|
||||
|
||||
@Override
|
||||
public EvalQueryQuality evaluate(SearchHit[] hits, List<RatedDocument> ratedDocs) {
|
||||
Map<String, RatedDocument> ratedDocsById = new HashMap<>();
|
||||
Map<RatedDocumentKey, RatedDocument> ratedDocsByKey = new HashMap<>();
|
||||
for (RatedDocument doc : ratedDocs) {
|
||||
ratedDocsById.put(doc.getDocID(), doc);
|
||||
ratedDocsByKey.put(doc.getKey(), doc);
|
||||
}
|
||||
|
||||
Collection<String> unknownDocIds = new ArrayList<>();
|
||||
Collection<RatedDocumentKey> unknownDocIds = new ArrayList<>();
|
||||
List<Integer> ratings = new ArrayList<>();
|
||||
for (int i = 0; (i < position && i < hits.length); i++) {
|
||||
String id = hits[i].getId();
|
||||
RatedDocument ratedDoc = ratedDocsById.get(id);
|
||||
RatedDocumentKey id = new RatedDocumentKey(hits[i].getIndex(), hits[i].getType(), hits[i].getId());
|
||||
RatedDocument ratedDoc = ratedDocsByKey.get(id);
|
||||
if (ratedDoc != null) {
|
||||
ratings.add(ratedDoc.getRating());
|
||||
} else {
|
||||
|
@ -29,14 +29,14 @@ import java.util.Collection;
|
||||
public class EvalQueryQuality {
|
||||
private double qualityLevel;
|
||||
|
||||
private Collection<String> unknownDocs;
|
||||
private Collection<RatedDocumentKey> unknownDocs;
|
||||
|
||||
public EvalQueryQuality (double qualityLevel, Collection<String> unknownDocs) {
|
||||
public EvalQueryQuality (double qualityLevel, Collection<RatedDocumentKey> unknownDocs) {
|
||||
this.qualityLevel = qualityLevel;
|
||||
this.unknownDocs = unknownDocs;
|
||||
}
|
||||
|
||||
public Collection<String> getUnknownDocs() {
|
||||
public Collection<RatedDocumentKey> getUnknownDocs() {
|
||||
return unknownDocs;
|
||||
}
|
||||
|
||||
|
@ -99,27 +99,27 @@ public class PrecisionAtN extends RankedListQualityMetric {
|
||||
@Override
|
||||
public EvalQueryQuality evaluate(SearchHit[] hits, List<RatedDocument> ratedDocs) {
|
||||
|
||||
Collection<String> relevantDocIds = new ArrayList<>();
|
||||
Collection<String> irrelevantDocIds = new ArrayList<>();
|
||||
Collection<RatedDocumentKey> relevantDocIds = new ArrayList<>();
|
||||
Collection<RatedDocumentKey> irrelevantDocIds = new ArrayList<>();
|
||||
for (RatedDocument doc : ratedDocs) {
|
||||
if (Rating.RELEVANT.equals(RatingMapping.mapTo(doc.getRating()))) {
|
||||
relevantDocIds.add(doc.getDocID());
|
||||
relevantDocIds.add(doc.getKey());
|
||||
} else if (Rating.IRRELEVANT.equals(RatingMapping.mapTo(doc.getRating()))) {
|
||||
irrelevantDocIds.add(doc.getDocID());
|
||||
irrelevantDocIds.add(doc.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
int good = 0;
|
||||
int bad = 0;
|
||||
Collection<String> unknownDocIds = new ArrayList<>();
|
||||
Collection<RatedDocumentKey> unknownDocIds = new ArrayList<>();
|
||||
for (int i = 0; (i < n && i < hits.length); i++) {
|
||||
String id = hits[i].getId();
|
||||
if (relevantDocIds.contains(id)) {
|
||||
RatedDocumentKey hitKey = new RatedDocumentKey(hits[i].getIndex(), hits[i].getType(), hits[i].getId());
|
||||
if (relevantDocIds.contains(hitKey)) {
|
||||
good++;
|
||||
} else if (irrelevantDocIds.contains(id)) {
|
||||
} else if (irrelevantDocIds.contains(hitKey)) {
|
||||
bad++;
|
||||
} else {
|
||||
unknownDocIds.add(id);
|
||||
unknownDocIds.add(hitKey);
|
||||
}
|
||||
}
|
||||
double precision = (double) good / (good + bad);
|
||||
|
@ -159,7 +159,7 @@ public class QuerySpec implements Writeable {
|
||||
} , REQUEST_FIELD);
|
||||
PARSER.declareObjectArray(QuerySpec::setRatedDocs, (p, c) -> {
|
||||
try {
|
||||
return RatedDocument.fromXContent(p);
|
||||
return RatedDocument.fromXContent(p, c);
|
||||
} catch (IOException ex) {
|
||||
throw new ParsingException(p.getTokenLocation(), "error parsing ratings", ex);
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ public class RankEvalResponse extends ActionResponse implements ToXContent {
|
||||
/**Average precision observed when issuing query intents with this specification.*/
|
||||
private double qualityLevel;
|
||||
/**Mapping from intent id to all documents seen for this intent that were not annotated.*/
|
||||
private Map<String, Collection<String>> unknownDocs;
|
||||
private Map<String, Collection<RatedDocumentKey>> unknownDocs;
|
||||
|
||||
public RankEvalResponse() {
|
||||
}
|
||||
@ -56,10 +56,10 @@ public class RankEvalResponse extends ActionResponse implements ToXContent {
|
||||
super.readFrom(in);
|
||||
this.specId = in.readString();
|
||||
this.qualityLevel = in.readDouble();
|
||||
this.unknownDocs = (Map<String, Collection<String>>) in.readGenericValue();
|
||||
this.unknownDocs = (Map<String, Collection<RatedDocumentKey>>) in.readGenericValue();
|
||||
}
|
||||
|
||||
public RankEvalResponse(String specId, double qualityLevel, Map<String, Collection<String>> unknownDocs) {
|
||||
public RankEvalResponse(String specId, double qualityLevel, Map<String, Collection<RatedDocumentKey>> unknownDocs) {
|
||||
this.specId = specId;
|
||||
this.qualityLevel = qualityLevel;
|
||||
this.unknownDocs = unknownDocs;
|
||||
@ -73,7 +73,7 @@ public class RankEvalResponse extends ActionResponse implements ToXContent {
|
||||
return qualityLevel;
|
||||
}
|
||||
|
||||
public Map<String, Collection<String>> getUnknownDocs() {
|
||||
public Map<String, Collection<RatedDocumentKey>> getUnknownDocs() {
|
||||
return unknownDocs;
|
||||
}
|
||||
|
||||
|
@ -19,36 +19,68 @@
|
||||
|
||||
package org.elasticsearch.index.rankeval;
|
||||
|
||||
import org.elasticsearch.action.support.ToXContentToBytes;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentParser.Token;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A document ID and its rating for the query QA use case.
|
||||
* */
|
||||
public class RatedDocument implements Writeable {
|
||||
public class RatedDocument extends ToXContentToBytes implements Writeable {
|
||||
|
||||
// TODO augment with index name and type name
|
||||
private final String docId;
|
||||
private final int rating;
|
||||
public static final ParseField RATING_FIELD = new ParseField("rating");
|
||||
public static final ParseField KEY_FIELD = new ParseField("key");
|
||||
|
||||
public RatedDocument(String docId, int rating) {
|
||||
this.docId = docId;
|
||||
private static final ConstructingObjectParser<RatedDocument, RankEvalContext> PARSER = new ConstructingObjectParser<>("rated_document",
|
||||
a -> new RatedDocument((RatedDocumentKey) a[0], (Integer) a[1]));
|
||||
|
||||
static {
|
||||
PARSER.declareObject(ConstructingObjectParser.constructorArg(), (p, c) -> {
|
||||
try {
|
||||
return RatedDocumentKey.fromXContent(p, c);
|
||||
} catch (IOException ex) {
|
||||
throw new ParsingException(p.getTokenLocation(), "error parsing rank request", ex);
|
||||
}
|
||||
} , KEY_FIELD);
|
||||
PARSER.declareInt(ConstructingObjectParser.constructorArg(), RATING_FIELD);
|
||||
}
|
||||
|
||||
private RatedDocumentKey key;
|
||||
private int rating;
|
||||
|
||||
void setRatedDocumentKey(RatedDocumentKey key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
void setKey(RatedDocumentKey key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
void setRating(int rating) {
|
||||
this.rating = rating;
|
||||
}
|
||||
|
||||
public RatedDocument(RatedDocumentKey key, int rating) {
|
||||
this.key = key;
|
||||
this.rating = rating;
|
||||
}
|
||||
|
||||
public RatedDocument(StreamInput in) throws IOException {
|
||||
this.docId = in.readString();
|
||||
this.key = new RatedDocumentKey(in);
|
||||
this.rating = in.readVInt();
|
||||
}
|
||||
|
||||
public String getDocID() {
|
||||
return docId;
|
||||
public RatedDocumentKey getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public int getRating() {
|
||||
@ -57,31 +89,38 @@ public class RatedDocument implements Writeable {
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeString(docId);
|
||||
this.key.writeTo(out);
|
||||
out.writeVInt(rating);
|
||||
}
|
||||
|
||||
public static RatedDocument fromXContent(XContentParser parser) throws IOException {
|
||||
String id = null;
|
||||
int rating = Integer.MIN_VALUE;
|
||||
Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (parser.currentToken().equals(Token.FIELD_NAME)) {
|
||||
if (id != null) {
|
||||
throw new ParsingException(parser.getTokenLocation(), "only one document id allowed, found [{}] but already got [{}]",
|
||||
parser.currentName(), id);
|
||||
}
|
||||
id = parser.currentName();
|
||||
} else if (parser.currentToken().equals(Token.VALUE_NUMBER)) {
|
||||
rating = parser.intValue();
|
||||
} else {
|
||||
throw new ParsingException(parser.getTokenLocation(), "unexpected token [{}] while parsing rated document",
|
||||
token);
|
||||
}
|
||||
public static RatedDocument fromXContent(XContentParser parser, RankEvalContext context) throws IOException {
|
||||
return PARSER.apply(parser, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(KEY_FIELD.getPreferredName(), key);
|
||||
builder.field(RATING_FIELD.getPreferredName(), rating);
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (id == null) {
|
||||
throw new ParsingException(parser.getTokenLocation(), "didn't find document id");
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return new RatedDocument(id, rating);
|
||||
RatedDocument other = (RatedDocument) obj;
|
||||
return Objects.equals(key, other.key) &&
|
||||
Objects.equals(rating, other.rating);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return Objects.hash(getClass(), key, rating);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.index.rankeval;
|
||||
|
||||
import org.elasticsearch.action.support.ToXContentToBytes;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class RatedDocumentKey extends ToXContentToBytes implements Writeable {
|
||||
public static final ParseField DOC_ID_FIELD = new ParseField("doc_id");
|
||||
public static final ParseField TYPE_FIELD = new ParseField("type");
|
||||
public static final ParseField INDEX_FIELD = new ParseField("index");
|
||||
|
||||
private static final ConstructingObjectParser<RatedDocumentKey, RankEvalContext> PARSER = new ConstructingObjectParser<>("ratings",
|
||||
a -> new RatedDocumentKey((String) a[0], (String) a[1], (String) a[2]));
|
||||
|
||||
static {
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), INDEX_FIELD);
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), TYPE_FIELD);
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), DOC_ID_FIELD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(INDEX_FIELD.getPreferredName(), index);
|
||||
builder.field(TYPE_FIELD.getPreferredName(), type);
|
||||
builder.field(DOC_ID_FIELD.getPreferredName(), docId);
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
||||
// TODO instead of docId use path to id and id itself
|
||||
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 RatedDocumentKey(String index, String type, String docId) {
|
||||
this.index = index;
|
||||
this.type = type;
|
||||
this.docId = docId;
|
||||
}
|
||||
|
||||
public RatedDocumentKey(StreamInput in) throws IOException {
|
||||
this.index = in.readString();
|
||||
this.type = in.readString();
|
||||
this.docId = in.readString();
|
||||
}
|
||||
|
||||
public String getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getDocID() {
|
||||
return docId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeString(index);
|
||||
out.writeString(type);
|
||||
out.writeString(docId);
|
||||
}
|
||||
|
||||
public static RatedDocumentKey fromXContent(XContentParser parser, RankEvalContext context) throws IOException {
|
||||
return PARSER.apply(parser, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
RatedDocumentKey other = (RatedDocumentKey) obj;
|
||||
return Objects.equals(index, other.index) &&
|
||||
Objects.equals(type, other.type) &&
|
||||
Objects.equals(docId, other.docId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return Objects.hash(getClass(), index, type, docId);
|
||||
}
|
||||
}
|
@ -95,21 +95,21 @@ public class ReciprocalRank extends RankedListQualityMetric {
|
||||
**/
|
||||
@Override
|
||||
public EvalQueryQuality evaluate(SearchHit[] hits, List<RatedDocument> ratedDocs) {
|
||||
Set<String> relevantDocIds = new HashSet<>();
|
||||
Set<String> irrelevantDocIds = new HashSet<>();
|
||||
Set<RatedDocumentKey> relevantDocIds = new HashSet<>();
|
||||
Set<RatedDocumentKey> irrelevantDocIds = new HashSet<>();
|
||||
for (RatedDocument doc : ratedDocs) {
|
||||
if (Rating.RELEVANT.equals(RatingMapping.mapTo(doc.getRating()))) {
|
||||
relevantDocIds.add(doc.getDocID());
|
||||
relevantDocIds.add(doc.getKey());
|
||||
} else if (Rating.IRRELEVANT.equals(RatingMapping.mapTo(doc.getRating()))) {
|
||||
irrelevantDocIds.add(doc.getDocID());
|
||||
irrelevantDocIds.add(doc.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
Collection<String> unknownDocIds = new ArrayList<>();
|
||||
Collection<RatedDocumentKey> unknownDocIds = new ArrayList<>();
|
||||
int firstRelevant = -1;
|
||||
boolean found = false;
|
||||
for (int i = 0; i < hits.length; i++) {
|
||||
String id = hits[i].getId();
|
||||
RatedDocumentKey id = new RatedDocumentKey(hits[i].getIndex(), hits[i].getType(), hits[i].getId());
|
||||
if (relevantDocIds.contains(id)) {
|
||||
if (found == false && i < maxAcceptableRank) {
|
||||
firstRelevant = i + 1; // add one because rank is not
|
||||
|
@ -83,7 +83,7 @@ public class TransportRankEvalAction extends HandledTransportAction<RankEvalRequ
|
||||
RankedListQualityMetric metric = qualityTask.getEvaluator();
|
||||
|
||||
double qualitySum = 0;
|
||||
Map<String, Collection<String>> unknownDocs = new HashMap<>();
|
||||
Map<String, Collection<RatedDocumentKey>> unknownDocs = new HashMap<>();
|
||||
Collection<QuerySpec> specifications = qualityTask.getSpecifications();
|
||||
Vector<EvalQueryQuality> partialResults = new Vector<>(specifications.size());
|
||||
for (QuerySpec spec : specifications) {
|
||||
|
@ -23,7 +23,8 @@ import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.text.Text;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.search.SearchShardTarget;
|
||||
import org.elasticsearch.search.internal.InternalSearchHit;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
@ -52,10 +53,11 @@ public class DiscountedCumulativeGainAtTests extends ESTestCase {
|
||||
public void testDCGAtSix() throws IOException, InterruptedException, ExecutionException {
|
||||
List<RatedDocument> rated = new ArrayList<>();
|
||||
int[] relevanceRatings = new int[] { 3, 2, 3, 0, 1, 2 };
|
||||
SearchHit[] hits = new InternalSearchHit[6];
|
||||
InternalSearchHit[] hits = new InternalSearchHit[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
rated.add(new RatedDocument(Integer.toString(i), relevanceRatings[i]));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("index", "type", Integer.toString(i)), relevanceRatings[i]));
|
||||
hits[i] = new InternalSearchHit(i, Integer.toString(i), new Text("type"), Collections.emptyMap());
|
||||
hits[i].shard(new SearchShardTarget("testnode", new ShardId("index", "uuid", 0)));
|
||||
}
|
||||
DiscountedCumulativeGainAt dcg = new DiscountedCumulativeGainAt(6);
|
||||
assertEquals(13.84826362927298, dcg.evaluate(hits, rated).getQualityLevel(), 0.00001);
|
||||
@ -95,12 +97,13 @@ public class DiscountedCumulativeGainAtTests extends ESTestCase {
|
||||
public void testDCGAtSixMissingRatings() throws IOException, InterruptedException, ExecutionException {
|
||||
List<RatedDocument> rated = new ArrayList<>();
|
||||
int[] relevanceRatings = new int[] { 3, 2, 3};
|
||||
SearchHit[] hits = new InternalSearchHit[6];
|
||||
InternalSearchHit[] hits = new InternalSearchHit[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (i < relevanceRatings.length) {
|
||||
rated.add(new RatedDocument(Integer.toString(i), relevanceRatings[i]));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("index", "type", Integer.toString(i)), relevanceRatings[i]));
|
||||
}
|
||||
hits[i] = new InternalSearchHit(i, Integer.toString(i), new Text("type"), Collections.emptyMap());
|
||||
hits[i].shard(new SearchShardTarget("testnode", new ShardId("index", "uuid", 0)));
|
||||
}
|
||||
DiscountedCumulativeGainAt dcg = new DiscountedCumulativeGainAt(6);
|
||||
EvalQueryQuality result = dcg.evaluate(hits, rated);
|
||||
|
@ -23,8 +23,9 @@ import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.text.Text;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.rankeval.PrecisionAtN.Rating;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.SearchShardTarget;
|
||||
import org.elasticsearch.search.internal.InternalSearchHit;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
@ -41,26 +42,58 @@ public class PrecisionAtNTests extends ESTestCase {
|
||||
|
||||
public void testPrecisionAtFiveCalculation() throws IOException, InterruptedException, ExecutionException {
|
||||
List<RatedDocument> rated = new ArrayList<>();
|
||||
rated.add(new RatedDocument("0", Rating.RELEVANT.ordinal()));
|
||||
SearchHit[] hits = new InternalSearchHit[1];
|
||||
hits[0] = new InternalSearchHit(0, "0", new Text("type"), Collections.emptyMap());
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "testtype", "0"), Rating.RELEVANT.ordinal()));
|
||||
InternalSearchHit[] hits = new InternalSearchHit[1];
|
||||
hits[0] = new InternalSearchHit(0, "0", new Text("testtype"), Collections.emptyMap());
|
||||
hits[0].shard(new SearchShardTarget("testnode", new Index("test", "uuid"), 0));
|
||||
assertEquals(1, (new PrecisionAtN(5)).evaluate(hits, rated).getQualityLevel(), 0.00001);
|
||||
}
|
||||
|
||||
public void testPrecisionAtFiveIgnoreOneResult() throws IOException, InterruptedException, ExecutionException {
|
||||
List<RatedDocument> rated = new ArrayList<>();
|
||||
rated.add(new RatedDocument("0", Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument("1", Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument("2", Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument("3", Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument("4", Rating.IRRELEVANT.ordinal()));
|
||||
SearchHit[] hits = new InternalSearchHit[5];
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "testtype", "0"), Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "testtype", "1"), Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "testtype", "2"), Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "testtype", "3"), Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "testtype", "4"), Rating.IRRELEVANT.ordinal()));
|
||||
InternalSearchHit[] hits = new InternalSearchHit[5];
|
||||
for (int i = 0; i < 5; i++) {
|
||||
hits[i] = new InternalSearchHit(i, i+"", new Text("type"), Collections.emptyMap());
|
||||
hits[i] = new InternalSearchHit(i, i+"", new Text("testtype"), Collections.emptyMap());
|
||||
hits[i].shard(new SearchShardTarget("testnode", new Index("test", "uuid"), 0));
|
||||
}
|
||||
assertEquals((double) 4 / 5, (new PrecisionAtN(5)).evaluate(hits, rated).getQualityLevel(), 0.00001);
|
||||
}
|
||||
|
||||
public void testPrecisionAtFiveCorrectIndex() throws IOException, InterruptedException, ExecutionException {
|
||||
List<RatedDocument> rated = new ArrayList<>();
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test_other", "testtype", "0"), Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test_other", "testtype", "1"), Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "testtype", "2"), Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "testtype", "3"), Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "testtype", "4"), Rating.IRRELEVANT.ordinal()));
|
||||
InternalSearchHit[] hits = new InternalSearchHit[5];
|
||||
for (int i = 0; i < 5; i++) {
|
||||
hits[i] = new InternalSearchHit(i, i+"", new Text("testtype"), Collections.emptyMap());
|
||||
hits[i].shard(new SearchShardTarget("testnode", new Index("test", "uuid"), 0));
|
||||
}
|
||||
assertEquals((double) 2 / 3, (new PrecisionAtN(5)).evaluate(hits, rated).getQualityLevel(), 0.00001);
|
||||
}
|
||||
|
||||
public void testPrecisionAtFiveCorrectType() throws IOException, InterruptedException, ExecutionException {
|
||||
List<RatedDocument> rated = new ArrayList<>();
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "other_type", "0"), Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "other_type", "1"), Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "testtype", "2"), Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "testtype", "3"), Rating.RELEVANT.ordinal()));
|
||||
rated.add(new RatedDocument(new RatedDocumentKey("test", "testtype", "4"), Rating.IRRELEVANT.ordinal()));
|
||||
InternalSearchHit[] hits = new InternalSearchHit[5];
|
||||
for (int i = 0; i < 5; i++) {
|
||||
hits[i] = new InternalSearchHit(i, i+"", new Text("testtype"), Collections.emptyMap());
|
||||
hits[i].shard(new SearchShardTarget("testnode", new Index("test", "uuid"), 0));
|
||||
}
|
||||
assertEquals((double) 2 / 3, (new PrecisionAtN(5)).evaluate(hits, rated).getQualityLevel(), 0.00001);
|
||||
}
|
||||
|
||||
public void testParseFromXContent() throws IOException {
|
||||
String xContent = " {\n"
|
||||
+ " \"size\": 10\n"
|
||||
|
@ -79,7 +79,10 @@ public class QuerySpecTests extends ESTestCase {
|
||||
+ " },\n"
|
||||
+ " \"size\": 10\n"
|
||||
+ " },\n"
|
||||
+ " \"ratings\": [ {\"1\": 1 }, { \"2\": 0 }, { \"3\": 1 } ]\n"
|
||||
+ " \"ratings\": [ "
|
||||
+ " {\"key\": {\"index\": \"test\", \"type\": \"testtype\", \"doc_id\": \"1\"}, \"rating\" : 1 }, "
|
||||
+ " {\"key\": {\"index\": \"test\", \"type\": \"testtype\", \"doc_id\": \"2\"}, \"rating\" : 0 }, "
|
||||
+ " {\"key\": {\"index\": \"test\", \"type\": \"testtype\", \"doc_id\": \"3\"}, \"rating\" : 1 }]\n"
|
||||
+ "}";
|
||||
XContentParser parser = XContentFactory.xContent(querySpecString).createParser(querySpecString);
|
||||
QueryParseContext queryContext = new QueryParseContext(queriesRegistry, parser, ParseFieldMatcher.STRICT);
|
||||
@ -90,11 +93,11 @@ public class QuerySpecTests extends ESTestCase {
|
||||
assertNotNull(specification.getTestRequest());
|
||||
List<RatedDocument> ratedDocs = specification.getRatedDocs();
|
||||
assertEquals(3, ratedDocs.size());
|
||||
assertEquals("1", ratedDocs.get(0).getDocID());
|
||||
assertEquals("1", ratedDocs.get(0).getKey().getDocID());
|
||||
assertEquals(1, ratedDocs.get(0).getRating());
|
||||
assertEquals("2", ratedDocs.get(1).getDocID());
|
||||
assertEquals("2", ratedDocs.get(1).getKey().getDocID());
|
||||
assertEquals(0, ratedDocs.get(1).getRating());
|
||||
assertEquals("3", ratedDocs.get(2).getDocID());
|
||||
assertEquals("3", ratedDocs.get(2).getKey().getDocID());
|
||||
assertEquals(1, ratedDocs.get(2).getRating());
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,15 @@ package org.elasticsearch.index.rankeval;
|
||||
|
||||
import org.elasticsearch.index.query.MatchAllQueryBuilder;
|
||||
import org.elasticsearch.index.rankeval.PrecisionAtN.Rating;
|
||||
import org.elasticsearch.index.rankeval.QuerySpec;
|
||||
import org.elasticsearch.index.rankeval.RankEvalAction;
|
||||
import org.elasticsearch.index.rankeval.RankEvalPlugin;
|
||||
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.RatedDocument;
|
||||
import org.elasticsearch.index.rankeval.RatedDocumentKey;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
@ -89,9 +98,9 @@ public class RankEvalRequestTests extends ESIntegTestCase {
|
||||
RankEvalResponse response = client().execute(RankEvalAction.INSTANCE, builder.request()).actionGet();
|
||||
assertEquals(specId, response.getSpecId());
|
||||
assertEquals(1.0, response.getQualityLevel(), Double.MIN_VALUE);
|
||||
Set<Entry<String, Collection<String>>> entrySet = response.getUnknownDocs().entrySet();
|
||||
Set<Entry<String, Collection<RatedDocumentKey>>> entrySet = response.getUnknownDocs().entrySet();
|
||||
assertEquals(2, entrySet.size());
|
||||
for (Entry<String, Collection<String>> entry : entrySet) {
|
||||
for (Entry<String, Collection<RatedDocumentKey>> entry : entrySet) {
|
||||
if (entry.getKey() == "amsterdam_query") {
|
||||
assertEquals(2, entry.getValue().size());
|
||||
}
|
||||
@ -104,7 +113,7 @@ public class RankEvalRequestTests extends ESIntegTestCase {
|
||||
private static List<RatedDocument> createRelevant(String... docs) {
|
||||
List<RatedDocument> relevant = new ArrayList<>();
|
||||
for (String doc : docs) {
|
||||
relevant.add(new RatedDocument(doc, Rating.RELEVANT.ordinal()));
|
||||
relevant.add(new RatedDocument(new RatedDocumentKey("test", "testtype", doc), Rating.RELEVANT.ordinal()));
|
||||
}
|
||||
return relevant;
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.index.rankeval;
|
||||
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class RatedDocumentTests extends ESTestCase {
|
||||
|
||||
public void testXContentParsing() throws IOException {
|
||||
String index = randomAsciiOfLength(10);
|
||||
String type = randomAsciiOfLength(10);
|
||||
String docId = randomAsciiOfLength(10);
|
||||
int rating = randomInt();
|
||||
RatedDocument testItem = new RatedDocument(new RatedDocumentKey(index, type, docId), rating);
|
||||
|
||||
XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
|
||||
if (randomBoolean()) {
|
||||
builder.prettyPrint();
|
||||
}
|
||||
testItem.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
XContentBuilder shuffled = shuffleXContent(builder);
|
||||
XContentParser itemParser = XContentHelper.createParser(shuffled.bytes());
|
||||
itemParser.nextToken();
|
||||
|
||||
RankEvalContext context = new RankEvalContext(ParseFieldMatcher.STRICT, null, null, null);
|
||||
RatedDocument parsedItem = RatedDocument.fromXContent(itemParser, context);
|
||||
assertNotSame(testItem, parsedItem);
|
||||
assertEquals(testItem, parsedItem);
|
||||
assertEquals(testItem.hashCode(), parsedItem.hashCode());
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -20,8 +20,9 @@
|
||||
package org.elasticsearch.index.rankeval;
|
||||
|
||||
import org.elasticsearch.common.text.Text;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.rankeval.PrecisionAtN.Rating;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.SearchShardTarget;
|
||||
import org.elasticsearch.search.internal.InternalSearchHit;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
@ -42,17 +43,22 @@ public class ReciprocalRankTests extends ESTestCase {
|
||||
reciprocalRank.setMaxAcceptableRank(maxRank);
|
||||
assertEquals(maxRank, reciprocalRank.getMaxAcceptableRank());
|
||||
|
||||
SearchHit[] hits = new SearchHit[10];
|
||||
InternalSearchHit[] hits = new InternalSearchHit[10];
|
||||
for (int i = 0; i < 10; i++) {
|
||||
hits[i] = new InternalSearchHit(i, Integer.toString(i), new Text("type"), Collections.emptyMap());
|
||||
hits[i].shard(new SearchShardTarget("testnode", new Index("test", "uuid"), 0));
|
||||
}
|
||||
List<RatedDocument> ratedDocs = new ArrayList<>();
|
||||
int relevantAt = 5;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (i == relevantAt) {
|
||||
ratedDocs.add(new RatedDocument(Integer.toString(i), Rating.RELEVANT.ordinal()));
|
||||
ratedDocs.add(new RatedDocument(
|
||||
new RatedDocumentKey("test", "type", Integer.toString(i)),
|
||||
Rating.RELEVANT.ordinal()));
|
||||
} else {
|
||||
ratedDocs.add(new RatedDocument(Integer.toString(i), Rating.IRRELEVANT.ordinal()));
|
||||
ratedDocs.add(new RatedDocument(
|
||||
new RatedDocumentKey("test", "type", Integer.toString(i)),
|
||||
Rating.IRRELEVANT.ordinal()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,18 +79,23 @@ public class ReciprocalRankTests extends ESTestCase {
|
||||
|
||||
public void testEvaluationOneRelevantInResults() {
|
||||
ReciprocalRank reciprocalRank = new ReciprocalRank();
|
||||
SearchHit[] hits = new SearchHit[10];
|
||||
InternalSearchHit[] hits = new InternalSearchHit[10];
|
||||
for (int i = 0; i < 10; i++) {
|
||||
hits[i] = new InternalSearchHit(i, Integer.toString(i), new Text("type"), Collections.emptyMap());
|
||||
hits[i].shard(new SearchShardTarget("testnode", new Index("test", "uuid"), 0));
|
||||
}
|
||||
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(Integer.toString(i), Rating.RELEVANT.ordinal()));
|
||||
ratedDocs.add(new RatedDocument(
|
||||
new RatedDocumentKey("test", "type", Integer.toString(i)),
|
||||
Rating.RELEVANT.ordinal()));
|
||||
} else {
|
||||
ratedDocs.add(new RatedDocument(Integer.toString(i), Rating.IRRELEVANT.ordinal()));
|
||||
ratedDocs.add(new RatedDocument(
|
||||
new RatedDocumentKey("test", "type", Integer.toString(i)),
|
||||
Rating.IRRELEVANT.ordinal()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,9 +114,10 @@ public class ReciprocalRankTests extends ESTestCase {
|
||||
|
||||
public void testEvaluationNoRelevantInResults() {
|
||||
ReciprocalRank reciprocalRank = new ReciprocalRank();
|
||||
SearchHit[] hits = new SearchHit[10];
|
||||
InternalSearchHit[] hits = new InternalSearchHit[10];
|
||||
for (int i = 0; i < 10; i++) {
|
||||
hits[i] = new InternalSearchHit(i, Integer.toString(i), new Text("type"), Collections.emptyMap());
|
||||
hits[i].shard(new SearchShardTarget("testnode", new Index("test", "uuid"), 0));
|
||||
}
|
||||
List<RatedDocument> ratedDocs = new ArrayList<>();
|
||||
EvalQueryQuality evaluation = reciprocalRank.evaluate(hits, ratedDocs);
|
||||
|
@ -46,12 +46,15 @@
|
||||
{
|
||||
"id": "amsterdam_query",
|
||||
"request": { "query": { "match" : {"text" : "amsterdam" }}},
|
||||
"ratings": [{ "doc1": 0}, {"doc2": 1}, {"doc3": 1}]
|
||||
"ratings": [
|
||||
{"key": { "index": "foo", "type": "bar", "doc_id": "doc1"}, "rating": 0},
|
||||
{"key": { "index": "foo", "type": "bar", "doc_id": "doc2"}, "rating": 1},
|
||||
{"key": { "index": "foo", "type": "bar", "doc_id": "doc3"}, "rating": 1}]
|
||||
},
|
||||
{
|
||||
"id" : "berlin_query",
|
||||
"request": { "query": { "match" : { "text" : "berlin" } }, "size" : 10 },
|
||||
"ratings": [{"doc1": 1}]
|
||||
"ratings": [{"key": {"index": "foo", "type": "bar", "doc_id": "doc1"}, "rating": 1}]
|
||||
}
|
||||
],
|
||||
"metric" : { "precisionatn": { "size": 10}}
|
||||
@ -59,8 +62,8 @@
|
||||
|
||||
- match: {rank_eval.spec_id: "cities_qa_queries"}
|
||||
- match: {rank_eval.quality_level: 1}
|
||||
- match: {rank_eval.unknown_docs.0.amsterdam_query: [ "doc4"]}
|
||||
- match: {rank_eval.unknown_docs.1.berlin_query: [ "doc4"]}
|
||||
- match: {rank_eval.unknown_docs.0.amsterdam_query: [ {"index": "foo", "type": "bar", "doc_id": "doc4"}]}
|
||||
- match: {rank_eval.unknown_docs.1.berlin_query: [ {"index": "foo", "type": "bar", "doc_id": "doc4"}]}
|
||||
---
|
||||
"Reciprocal Rank":
|
||||
|
||||
@ -111,13 +114,13 @@
|
||||
"id": "amsterdam_query",
|
||||
"request": { "query": { "match" : {"text" : "amsterdam" }}},
|
||||
# doc4 should be returned in third position, so reciprocal rank is 1/3
|
||||
"ratings": [{ "doc4": 1}]
|
||||
"ratings": [{"key": {"index": "foo", "type": "bar", "doc_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": [{"doc4": 1}]
|
||||
"ratings": [{"key": {"index": "foo", "type": "bar", "doc_id": "doc4"}, "rating": 1}]
|
||||
}
|
||||
],
|
||||
"metric" : { "reciprocal_rank": {} }
|
||||
@ -136,13 +139,13 @@
|
||||
"id": "amsterdam_query",
|
||||
"request": { "query": { "match" : {"text" : "amsterdam" }}},
|
||||
# doc4 should be returned in third position, so reciprocal rank is 1/3
|
||||
"ratings": [{ "doc4": 1}]
|
||||
"ratings": [{"key": {"index": "foo", "type": "bar", "doc_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": [{"doc4": 1}]
|
||||
"ratings": [{"key": {"index": "foo", "type": "bar", "doc_id": "doc4"}, "rating": 1}]
|
||||
}
|
||||
],
|
||||
"metric" : {
|
||||
|
@ -52,7 +52,13 @@
|
||||
{
|
||||
"id": "dcg_query",
|
||||
"request": { "query": { "match_all" : {}}, "sort" : [ "bar" ] },
|
||||
"ratings": [{ "doc1": 3}, {"doc2": 2}, {"doc3": 3}, {"doc4": 0}, {"doc5": 1}, {"doc6": 2}]
|
||||
"ratings": [
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc1"}, "rating": 3},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc2"}, "rating": 2},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc3"}, "rating": 3},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc4"}, "rating": 0},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc5"}, "rating": 1},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc6"}, "rating": 2}]
|
||||
}
|
||||
],
|
||||
"metric" : { "dcg_at_n": { "size": 6}}
|
||||
@ -71,7 +77,13 @@
|
||||
{
|
||||
"id": "dcg_query_reverse",
|
||||
"request": { "query": { "match_all" : {}}, "sort" : [ {"bar" : "desc" }] },
|
||||
"ratings": [{ "doc1": 3}, {"doc2": 2}, {"doc3": 3}, {"doc4": 0}, {"doc5": 1}, {"doc6": 2}]
|
||||
"ratings": [
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc1"}, "rating": 3},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc2"}, "rating": 2},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc3"}, "rating": 3},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc4"}, "rating": 0},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc5"}, "rating": 1},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc6"}, "rating": 2}]
|
||||
},
|
||||
],
|
||||
"metric" : { "dcg_at_n": { "size": 6}}
|
||||
@ -90,12 +102,24 @@
|
||||
{
|
||||
"id": "dcg_query",
|
||||
"request": { "query": { "match_all" : {}}, "sort" : [ "bar" ] },
|
||||
"ratings": [{ "doc1": 3}, {"doc2": 2}, {"doc3": 3}, {"doc4": 0}, {"doc5": 1}, {"doc6": 2}]
|
||||
"ratings": [
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc1"}, "rating": 3},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc2"}, "rating": 2},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc3"}, "rating": 3},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc4"}, "rating": 0},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc5"}, "rating": 1},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc6"}, "rating": 2}]
|
||||
},
|
||||
{
|
||||
"id": "dcg_query_reverse",
|
||||
"request": { "query": { "match_all" : {}}, "sort" : [ {"bar" : "desc" }] },
|
||||
"ratings": [{ "doc1": 3}, {"doc2": 2}, {"doc3": 3}, {"doc4": 0}, {"doc5": 1}, {"doc6": 2}]
|
||||
"ratings": [
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc1"}, "rating": 3},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc2"}, "rating": 2},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc3"}, "rating": 3},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc4"}, "rating": 0},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc5"}, "rating": 1},
|
||||
{"key": {"index": "foo", "type": "bar", "doc_id": "doc6"}, "rating": 2}]
|
||||
},
|
||||
],
|
||||
"metric" : { "dcg_at_n": { "size": 6}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user