Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / api / search / SortOptions.java
blob0536717704b5b33007195fb245d154f9cf7b50e1
1 // Copyright 2012 Google Inc. All Rights Reserved.
3 package com.google.appengine.api.search;
5 import com.google.appengine.api.search.SearchServicePb.SearchParams;
6 import com.google.appengine.api.search.checkers.Preconditions;
7 import com.google.appengine.api.search.checkers.SortOptionsChecker;
9 import java.util.ArrayList;
10 import java.util.Collections;
11 import java.util.List;
13 /**
14 * Definition of how to sort documents. You may specify zero or more sort
15 * expressions and set a match scorer. If you have a large index, it is
16 * advisable to set a limit.
19 public final class SortOptions {
21 /**
22 * A builder that constructs {@link SortOptions SortOptionss}.
23 * A SortOptions will evaluate each of the
24 * {@link SortExpression SortExpressions} on each search result and apply a
25 * sort order with priority given to the sort expressions from left to right.
26 * The following code illustrates creating a SortOptions specification
27 * to score documents based on decreasing product rating and then within
28 * rating scores showing cheapest products based on price plus tax,
29 * scoring at most 2000 documents.
30 * <p>
31 * <pre>
32 * SortOptions sortOptions = SortOptions.newBuilder()
33 * .addSortExpression(SortExpression.newBuilder()
34 * .setExpression("rating")
35 * .setDirection(SortExpression.SortDirection.DESCENDING)
36 * .setDefaultValueNumeric(0))
37 * .addSortExpression(SortExpression.newBuilder()
38 * .setExpression("price + tax")
39 * .setDirection(SortExpression.SortDirection.ASCENDING)
40 * .setDefaultValueNumeric(99999999.00))
41 * .setLimit(1000)
42 * .build();
43 * </pre>
45 * The following code fragment shows how the score from a {@link MatchScorer}
46 * can be used in an expression that combines the score with one thousandth of
47 * an "importance" field. At most 1000 documents are scored.
48 * <pre>
49 * SortOptions sortOptions = SortOptions.newBuilder()
50 * .setMatchScorer(MatchScorer.newBuilder())
51 * .addSortExpression(SortExpression.newBuilder()
52 * .setExpression(String.format(
53 * "%s + (importance * .001)", SortExpression.SCORE_FIELD_NAME))
54 * .setDirection(SortExpression.SortDirection.DESCENDING)
55 * .setDefaultValueNumeric(0))
56 * .setLimit(1000)
57 * .build();
58 * </pre>
60 public static final class Builder { private MatchScorer matchScorer; private Integer limit;
62 private final List<SortExpression> sortExpressions = new ArrayList<SortExpression>();
64 private Builder() {
67 /**
68 * Sets the limit on the number of documents to score.
70 * @param limit the maximum number of documents to score
71 * @return this builder
72 * @throws IllegalArgumentException if the limit is out of range
74 public Builder setLimit(int limit) {
75 this.limit = SortOptionsChecker.checkLimit(limit);
76 return this;
79 /**
80 * Sets a {@link MatchScorer} or {@link RescoringMatchScorer} to base some
81 * {@link SortExpression SortExpressions} on. The value of the matchScorer can
82 * be accessed by using the field name "_score".
84 * @param matchScorer the rescoring/match matchScorer to use in an expression built
85 * on "_score"
86 * @return this builder
88 public Builder setMatchScorer(MatchScorer matchScorer) {
89 this.matchScorer = matchScorer;
90 return this;
93 /**
94 * Sets the matchScorer to the {@link MatchScorer} built from the builder.
96 * @see {@link #setMatchScorer(MatchScorer)}
97 * @param builder a builder of a MatchScorer
98 * @return this builder
100 public Builder setMatchScorer(MatchScorer.Builder builder) {
101 this.matchScorer = builder.build();
102 return this;
106 * Sets the matchScorer to the {@link RescoringMatchScorer} built from the
107 * builder.
109 * @see {@link #setMatchScorer(MatchScorer)}
110 * @param builder a builder of a RescoringMatchScorer
111 * @return this builder
113 public Builder setMatchScorer(RescoringMatchScorer.Builder builder) {
114 this.matchScorer = builder.build();
115 return this;
119 * Adds a {@link SortExpression} to the list of sort expressions.
121 * @param sortExpression an expression to sort documents by
122 * @return this Builder
124 public Builder addSortExpression(SortExpression sortExpression) {
125 this.sortExpressions.add(Preconditions.checkNotNull(sortExpression,
126 "sort expression cannot be null"));
127 return this;
131 * Adds a {@link SortExpression} built from the builder to the list of sort
132 * expressions.
134 * @param builder a builder of SortExpression to sort documents by
135 * @return this Builder
137 public Builder addSortExpression(SortExpression.Builder builder) {
138 Preconditions.checkNotNull(builder, "sort expression builder cannot be null");
139 this.sortExpressions.add(builder.build());
140 return this;
144 * Builds a {@link SortOptions} from the set values.
146 * @return a {@link SortOptions} built from the set values
148 public SortOptions build() {
149 return new SortOptions(this);
153 private final List<SortExpression> sortExpressions;
154 private final MatchScorer matchScorer; private final int limit;
157 * Constructs a text sort specification using the values from the
158 * {@link Builder}.
160 private SortOptions(Builder builder) {
161 matchScorer = builder.matchScorer;
162 limit = Util.defaultIfNull(builder.limit, SortOptionsChecker.DEFAULT_LIMIT);
163 sortExpressions = new ArrayList<SortExpression>(builder.sortExpressions);
167 * @return a list of sort expressions representing a multi-dimensional sort
169 public List<SortExpression> getSortExpressions() {
170 return Collections.unmodifiableList(sortExpressions);
174 * @return a {@link MatchScorer} used to score the documents
176 public MatchScorer getMatchScorer() {
177 return matchScorer;
181 * @return the limit on the number of documents to sort
183 public int getLimit() {
184 return limit;
188 * Creates and returns a SortOptions Builder.
190 * @return a new {@link SortOptions.Builder}. Set the parameters for
191 * SortOptions on the Builder, and use the {@link Builder#build()} method
192 * to create a concrete instance of SortOptions
194 public static Builder newBuilder() {
195 return new Builder();
198 public SearchParams.Builder copyToProtocolBuffer(SearchParams.Builder builder) {
199 SearchServicePb.ScorerSpec.Builder scorerSpecBuilder = null;
200 if (matchScorer != null) {
201 scorerSpecBuilder = matchScorer.copyToScorerSpecProtocolBuffer();
202 } else {
203 scorerSpecBuilder = SearchServicePb.ScorerSpec.newBuilder();
205 scorerSpecBuilder.setLimit(limit);
206 builder.setScorerSpec(scorerSpecBuilder);
207 for (SortExpression expression : sortExpressions) {
208 builder.addSortSpec(expression.copyToProtocolBuffer());
210 return builder;
213 @Override
214 public String toString() {
215 return String.format("SortOptions(limit=%d, matchScorer=%s, sortExpressions=%s)",
216 limit,
217 matchScorer,
218 sortExpressions);