All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.appengine.api.search.SortOptions Maven / Gradle / Ivy

/*
 * Copyright 2021 Google LLC
 *
 * Licensed 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
 *
 *     https://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 com.google.appengine.api.search;

import com.google.appengine.api.search.checkers.SearchApiLimits;
import com.google.appengine.api.search.checkers.SortOptionsChecker;
import com.google.appengine.api.search.proto.SearchServicePb;
import com.google.appengine.api.search.proto.SearchServicePb.SearchParams;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * Definition of how to sort documents. You may specify zero or more sort
 * expressions and set a match scorer. If you have a large index, it is
 * advisable to set a limit.
 *
 */
public final class SortOptions {

  /**
   * A builder that constructs {@link SortOptions SortOptionss}.
   * A SortOptions will evaluate each of the
   * {@link SortExpression SortExpressions} on each search result and apply a
   * sort order with priority given to the sort expressions from left to right.
   * The following code illustrates creating a SortOptions specification
   * to sort documents based on decreasing product rating and then within
   * rating showing cheapest products based on price plus tax,
   * sorting at most 2000 documents.
   * 

*

{@code
   *   SortOptions sortOptions = SortOptions.newBuilder()
   *       .addSortExpression(SortExpression.newBuilder()
   *           .setExpression("rating")
   *           .setDirection(SortExpression.SortDirection.DESCENDING)
   *           .setDefaultValueNumeric(0))
   *       .addSortExpression(SortExpression.newBuilder()
   *           .setExpression("price + tax")
   *           .setDirection(SortExpression.SortDirection.ASCENDING)
   *           .setDefaultValueNumeric(99999999.00))
   *       .setLimit(1000)
   *       .build();
   * }
* * The following code fragment shows how the score from a {@link MatchScorer} * can be used in an expression that combines the score with one thousandth of * an "importance" field. At most 1000 documents are scored and sorted. *
{@code
   *   SortOptions sortOptions = SortOptions.newBuilder()
   *       .setMatchScorer(MatchScorer.newBuilder())
   *       .addSortExpression(SortExpression.newBuilder()
   *           .setExpression(String.format(
   *               "%s + (importance * .001)", SortExpression.SCORE_FIELD_NAME))
   *           .setDirection(SortExpression.SortDirection.DESCENDING)
   *           .setDefaultValueNumeric(0))
   *       .setLimit(1000)
   *       .build();
   * }
*/ public static final class Builder { // Optional @Nullable private MatchScorer matchScorer; @Nullable private Integer limit; private final List sortExpressions = new ArrayList(); private Builder() { } /** * Sets the limit on the number of documents to score or sort. * * @param limit the maximum number of documents to score or sort * @return this builder * @throws IllegalArgumentException if the limit is out of range */ public Builder setLimit(int limit) { this.limit = SortOptionsChecker.checkLimit(limit); return this; } /** * Sets a {@link MatchScorer} or {@link RescoringMatchScorer} to base some * {@link SortExpression SortExpressions} on. The value of the matchScorer can * be accessed by using the field name "_score". * * @param matchScorer the rescoring/match matchScorer to use in an expression built * on "_score" * @return this builder */ public Builder setMatchScorer(MatchScorer matchScorer) { this.matchScorer = matchScorer; return this; } /** * Sets the matchScorer to the {@link MatchScorer} built from the builder. * * @see #setMatchScorer(MatchScorer) * @param builder a builder of a MatchScorer * @return this builder */ public Builder setMatchScorer(MatchScorer.Builder builder) { this.matchScorer = builder.build(); return this; } /** * Sets the matchScorer to the {@link RescoringMatchScorer} built from the * builder. * * @see #setMatchScorer(MatchScorer) * @param builder a builder of a RescoringMatchScorer * @return this builder */ public Builder setMatchScorer(RescoringMatchScorer.Builder builder) { this.matchScorer = builder.build(); return this; } /** * Adds a {@link SortExpression} to the list of sort expressions. * * @param sortExpression an expression to sort documents by * @return this Builder */ public Builder addSortExpression(SortExpression sortExpression) { this.sortExpressions.add(Preconditions.checkNotNull(sortExpression, "sort expression cannot be null")); return this; } /** * Adds a {@link SortExpression} built from the builder to the list of sort * expressions. * * @param builder a builder of SortExpression to sort documents by * @return this Builder */ public Builder addSortExpression(SortExpression.Builder builder) { Preconditions.checkNotNull(builder, "sort expression builder cannot be null"); this.sortExpressions.add(builder.build()); return this; } /** * Builds a {@link SortOptions} from the set values. * * @return a {@link SortOptions} built from the set values */ public SortOptions build() { return new SortOptions(this); } } private final List sortExpressions; // Optional @Nullable private final MatchScorer matchScorer; private final int limit; /** * Constructs a text sort specification using the values from the * {@link Builder}. */ private SortOptions(Builder builder) { matchScorer = builder.matchScorer; limit = Util.defaultIfNull(builder.limit, SearchApiLimits.SEARCH_DEFAULT_SORTED_LIMIT); sortExpressions = new ArrayList(builder.sortExpressions); } /** * @return a list of sort expressions representing a multi-dimensional sort */ public List getSortExpressions() { return Collections.unmodifiableList(sortExpressions); } /** * @return a {@link MatchScorer} used to score the documents */ public MatchScorer getMatchScorer() { return matchScorer; } /** * @return the limit on the number of documents to score or sort */ public int getLimit() { return limit; } /** * Creates and returns a SortOptions Builder. * * @return a new {@link SortOptions.Builder}. Set the parameters for * SortOptions on the Builder, and use the {@link Builder#build()} method * to create a concrete instance of SortOptions */ public static Builder newBuilder() { return new Builder(); } SearchParams.Builder copyToProtocolBuffer(SearchParams.Builder builder) { SearchServicePb.ScorerSpec.Builder scorerSpecBuilder = null; if (matchScorer != null) { scorerSpecBuilder = matchScorer.copyToScorerSpecProtocolBuffer(); } else { scorerSpecBuilder = SearchServicePb.ScorerSpec.newBuilder(); } scorerSpecBuilder.setLimit(limit); builder.setScorerSpec(scorerSpecBuilder); for (SortExpression expression : sortExpressions) { builder.addSortSpec(expression.copyToProtocolBuffer()); } return builder; } @Override public String toString() { return String.format("SortOptions(limit=%d, matchScorer=%s, sortExpressions=%s)", limit, matchScorer, sortExpressions); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy