1 // Copyright 2010 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
.QueryChecker
;
10 * A query to search an index for documents which match,
11 * restricting the document fields returned to those given, and
12 * scoring and sorting the results, whilst supporting pagination.
14 * For example, the following query will search for documents where
15 * the tokens 'good' and 'story' occur in some fields,
16 * returns up to 20 results including the fields 'author' and 'date-sent'
17 * as well as snippeted fields 'subject' and 'body'. The results
18 * are sorted by 'author' in descending order, getting the next 20 results
19 * from the responseCursor in the previously returned results, giving
20 * back a single cursor in the {@link Results} to get the next
21 * batch of results after this.
24 * QueryOptions options = QueryOptions.newBuilder()
26 * .setFieldsToSnippet("subject", "body")
27 * .setScorer(CustomScorer.newBuilder()
28 * .addSortExpression(SortExpression.newBuilder()
29 * .setExpression("author")
30 * .setDirection(SortDirection.DESCENDING)
31 * .setDefaultValue("")))
32 * .setCursor(responseCursor)
34 * Query query = Query.newBuilder()
35 * .setOptions(options)
36 * .build("good story");
43 * A builder which constructs Query objects.
45 public static class Builder
{
46 private String queryString
;
47 private QueryOptions options
;
53 * Constructs a {@link Query} builder with the given query.
55 * @param query the query to populate the builder
57 private Builder(Query query
) {
58 this.queryString
= query
.getQueryString();
59 this.options
= query
.getOptions();
63 * Sets the query options.
65 * @param options the {@link QueryOptions} to apply to the search results
66 * @return this builder
68 public Builder
setOptions(QueryOptions options
) {
69 this.options
= options
;
74 * Sets the query options from a builder.
76 * @param optionsBuilder the {@link QueryOptions.Builder} build a
77 * {@link QueryOptions{ to apply to the search results
78 * @return this builder
80 public Builder
setOptions(QueryOptions
.Builder optionsBuilder
) {
81 return setOptions(optionsBuilder
.build());
85 * Sets the query string used to construct the query.
87 * @param query a query string used to construct the query
88 * @return this Builder
89 * @throws SearchQueryException if the query string does not parse
91 protected Builder
setQueryString(String query
) {
92 this.queryString
= QueryChecker
.checkQuery(query
);
97 * Build a {@link Query} from the query string and the parameters set on
98 * the {@link Builder}. A query string can be as simple as a single term
99 * ("foo"), or as complex as a boolean expression, including field names
100 * ("title:hello OR body:important -october").
102 * @param queryString the query string to parse and apply to an index
103 * @return the Query built from the parameters entered on this
104 * Builder including the queryString
105 * @throws SearchQueryException if the query string is invalid
107 public Query
build(String queryString
) {
108 setQueryString(queryString
);
109 return new Query(this);
113 * Construct the message.
115 * @return the Query built from the parameters entered on this
117 * @throws IllegalArgumentException if the query string is invalid
119 public Query
build() {
120 return new Query(this);
124 private final String query
;
125 private final QueryOptions options
;
128 * Creates a query from the builder.
130 * @param builder the query builder to populate with
132 protected Query(Builder builder
) {
133 query
= builder
.queryString
;
134 options
= builder
.options
;
139 * The query can be as simple as a single term ("foo"), or as complex
140 * as a boolean expression, including field names ("title:hello OR
141 * body:important -october").
145 public String
getQueryString() {
150 * @return the {@link QueryOptions} for controlling the what is returned
151 * in the result set matching the query
153 public QueryOptions
getOptions() {
158 * Creates and returns a {@link Query} builder. Set the query
159 * parameters and use the {@link Builder#build()} method to create a concrete
162 * @return a {@link Builder} which can construct a query
164 public static Builder
newBuilder() {
165 return new Builder();
169 * Creates a builder from the given query.
171 * @param query the query for the builder to use to build another query
172 * @return a new builder with values based on the given request
174 public static Builder
newBuilder(Query query
) {
175 return new Builder(query
);
179 * Checks the query is valid, specifically, has a non-null
182 * @return this checked Query
183 * @throws NullPointerException if query is null
185 private Query
checkValid() {
186 Preconditions
.checkNotNull(query
, "query cannot be null");
191 * Copies the contents of this {@link Query} object into a
192 * {@link SearchParams} protocol buffer builder.
194 * @return a search params protocol buffer builder initialized with
195 * the values from this query
196 * @throws IllegalArgumentException if the cursor type is
199 SearchParams
.Builder
copyToProtocolBuffer() {
200 SearchParams
.Builder builder
= SearchParams
.newBuilder().setQuery(query
);
201 if (options
== null) {
202 QueryOptions
.newBuilder().build().copyToProtocolBuffer(builder
, query
);
204 options
.copyToProtocolBuffer(builder
, query
);
210 public String
toString() {
211 return String
.format(
212 "Query(queryString=%s%s)",
214 Util
.fieldToString("options", options
));