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");
42 * A builder which constructs Query objects.
44 public static class Builder
{
45 private String queryString
;
46 private QueryOptions options
;
52 * Constructs a {@link Query} builder with the given query.
54 * @param query the query to populate the builder
56 private Builder(Query query
) {
57 this.queryString
= query
.getQueryString();
58 this.options
= query
.getOptions();
62 * Sets the query options.
64 * @param options the {@link QueryOptions} to apply to the search results
65 * @return this builder
67 public Builder
setOptions(QueryOptions options
) {
68 this.options
= options
;
73 * Sets the query options from a builder.
75 * @param optionsBuilder the {@link QueryOptions.Builder} build a
76 * {@link QueryOptions} to apply to the search results
77 * @return this builder
79 public Builder
setOptions(QueryOptions
.Builder optionsBuilder
) {
80 return setOptions(optionsBuilder
.build());
84 * Sets the query string used to construct the query.
86 * @param query a query string used to construct the query
87 * @return this Builder
88 * @throws SearchQueryException if the query string does not parse
90 protected Builder
setQueryString(String query
) {
91 this.queryString
= QueryChecker
.checkQuery(query
);
96 * Build a {@link Query} from the query string and the parameters set on
97 * the {@link Builder}. A query string can be as simple as a single term
98 * ("foo"), or as complex as a boolean expression, including field names
99 * ("title:hello OR body:important -october").
101 * @param queryString the query string to parse and apply to an index
102 * @return the Query built from the parameters entered on this
103 * Builder including the queryString
104 * @throws SearchQueryException if the query string is invalid
106 public Query
build(String queryString
) {
107 setQueryString(queryString
);
108 return new Query(this);
112 * Construct the message.
114 * @return the Query built from the parameters entered on this
116 * @throws IllegalArgumentException if the query string is invalid
118 public Query
build() {
119 return new Query(this);
123 private final String query
;
124 private final QueryOptions options
;
127 * Creates a query from the builder.
129 * @param builder the query builder to populate with
131 protected Query(Builder builder
) {
132 query
= builder
.queryString
;
133 options
= builder
.options
;
138 * The query can be as simple as a single term ("foo"), or as complex
139 * as a boolean expression, including field names ("title:hello OR
140 * body:important -october").
144 public String
getQueryString() {
149 * @return the {@link QueryOptions} for controlling the what is returned
150 * in the result set matching the query
152 public QueryOptions
getOptions() {
157 * Creates and returns a {@link Query} builder. Set the query
158 * parameters and use the {@link Builder#build()} method to create a concrete
161 * @return a {@link Builder} which can construct a query
163 public static Builder
newBuilder() {
164 return new Builder();
168 * Creates a builder from the given query.
170 * @param query the query for the builder to use to build another query
171 * @return a new builder with values based on the given request
173 public static Builder
newBuilder(Query query
) {
174 return new Builder(query
);
178 * Checks the query is valid, specifically, has a non-null
181 * @return this checked Query
182 * @throws NullPointerException if query is null
184 private Query
checkValid() {
185 Preconditions
.checkNotNull(query
, "query cannot be null");
190 * Copies the contents of this {@link Query} object into a
191 * {@link SearchParams} protocol buffer builder.
193 * @return a search params protocol buffer builder initialized with
194 * the values from this query
195 * @throws IllegalArgumentException if the cursor type is
198 SearchParams
.Builder
copyToProtocolBuffer() {
199 SearchParams
.Builder builder
= SearchParams
.newBuilder().setQuery(query
);
200 if (options
== null) {
201 QueryOptions
.newBuilder().build().copyToProtocolBuffer(builder
, query
);
203 options
.copyToProtocolBuffer(builder
, query
);
209 public String
toString() {
210 return new Util
.ToStringHelper("Query")
211 .addField("queryString", query
)
212 .addField("options", options
)