2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017-2018 Amdocs
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
21 package org.onap.aai.sa.searchdbabstraction.searchapi;
23 import com.fasterxml.jackson.annotation.JsonProperty;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.concurrent.atomic.AtomicBoolean;
27 import org.radeox.util.logging.Logger;
30 * This class represents the structure of a search statement.
33 * The expected JSON structure to represent a search statement is as follows:
39 * "results-start": int, - Optional: index of starting point in result set.
40 * "results-size": int, - Optional: maximum number of documents to include in result set.
43 * { filter structure - see {@link Filter} }
47 * { query structure - see {@link QueryStatement} },
48 * { query structure - see {@link QueryStatement} },
51 * { query structure - see {@link QueryStatement} },
55 * { aggregation structure - see {@link AggregationStatement} },
56 * { aggregation structure - see {@link AggregationStatement} },
59 * { aggregation structure - see {@link AggregationStatement} },
64 public class SearchStatement {
67 * Defines the filters that should be applied before running the actual queries. This is optional.
69 private Filter filter;
72 * The list of queries to be applied to the document store.
74 private Query[] queries;
77 * The list of aggregations to be applied to the search
79 private Aggregation[] aggregations;
82 * Defines the sort criteria to apply to the query result set. This is optional.
86 @JsonProperty("results-start")
87 private Integer resultsStart;
89 @JsonProperty("results-size")
92 public Filter getFilter() {
96 public void setFilter(Filter filter) {
100 public Query[] getQueries() {
104 public void setQueries(Query[] queries) {
105 this.queries = queries;
108 public Sort getSort() {
112 public void setSort(Sort sort) {
116 public boolean isFiltered() {
117 return filter != null;
120 public Aggregation[] getAggregations() {
124 public void setAggregations(Aggregation[] aggregations) {
125 this.aggregations = aggregations;
128 public boolean hasAggregations() {
129 return aggregations != null && aggregations.length > 0;
132 public Integer getFrom() {
136 public void setFrom(Integer from) {
137 this.resultsStart = from;
140 public Integer getSize() {
144 public void setSize(Integer size) {
149 * This method returns a string which represents this statement in syntax that is understandable by ElasticSearch
150 * and is suitable for inclusion in an ElasticSearch query string.
152 * @return - ElasticSearch syntax string.
154 public String toElasticSearch() {
156 StringBuilder sb = new StringBuilder();
157 List<QueryStatement> notMatchQueries = new ArrayList<QueryStatement>();
158 List<QueryStatement> mustQueries = new ArrayList<QueryStatement>();
159 List<QueryStatement> shouldQueries = new ArrayList<QueryStatement>();
161 createQueryLists(queries, mustQueries, shouldQueries, notMatchQueries);
165 sb.append("\"version\": true,");
167 // If the client has specified an index into the results for the first
168 // document in the result set then include that in the ElasticSearch
170 if (resultsStart != null) {
171 sb.append("\"from\": ").append(resultsStart).append(", ");
174 // If the client has specified a maximum number of documents to be returned
175 // in the result set then include that in the ElasticSearch query.
177 sb.append("\"size\": ").append(size).append(", ");
180 sb.append("\"query\": {");
181 sb.append("\"bool\": {");
183 sb.append("\"must\": [");
184 AtomicBoolean firstQuery = new AtomicBoolean(true);
185 for (QueryStatement query : mustQueries) {
187 if (!firstQuery.compareAndSet(true, false)) {
191 sb.append(query.toElasticSearch());
195 sb.append("\"should\": [");
197 firstQuery = new AtomicBoolean(true);
198 for (QueryStatement query : shouldQueries) {
200 if (!firstQuery.compareAndSet(true, false)) {
204 sb.append(query.toElasticSearch());
207 sb.append("],"); // close should list
209 sb.append("\"must_not\": [");
210 firstQuery.set(true);
211 for (QueryStatement query : notMatchQueries) {
212 sb.append(query.toElasticSearch());
216 // Add the filter stanza, if one is required.
218 sb.append(", \"filter\": ").append(filter.toElasticSearch());
221 sb.append("}"); // close bool clause
222 sb.append("}"); // close query clause
224 // Add the sort directive, if one is required.
226 sb.append(", \"sort\": ").append(sort.toElasticSearch());
230 if (hasAggregations()) {
231 sb.append(", \"aggs\": {");
233 for (int i = 0; i < aggregations.length; i++) {
237 sb.append(aggregations[i].toElasticSearch());
245 Logger.debug("Generated raw ElasticSearch query statement: " + sb.toString());
246 return sb.toString();
249 private void createQueryLists(Query[] queries, List<QueryStatement> mustList, List<QueryStatement> mayList,
250 List<QueryStatement> mustNotList) {
252 for (Query query : queries) {
254 if (query.isMust()) {
256 if (query.getQueryStatement().isNotMatch()) {
257 mustNotList.add(query.getQueryStatement());
259 mustList.add(query.getQueryStatement());
263 if (query.getQueryStatement().isNotMatch()) {
264 mustNotList.add(query.getQueryStatement());
266 mayList.add(query.getQueryStatement());
274 public String toString() {
276 StringBuilder sb = new StringBuilder();
278 sb.append("SEARCH STATEMENT: {");
281 sb.append("from: ").append(resultsStart).append(", size: ").append(size).append(", ");
284 if (filter != null) {
285 sb.append("filter: ").append(filter.toString()).append(", ");
288 sb.append("queries: [");
289 AtomicBoolean firstQuery = new AtomicBoolean(true);
290 if (queries != null) {
291 for (Query query : queries) {
293 if (!firstQuery.compareAndSet(true, false)) {
296 sb.append(query.toString());
301 sb.append("aggregations: [");
302 firstQuery = new AtomicBoolean(true);
304 if (aggregations != null) {
305 for (Aggregation agg : aggregations) {
307 if (!firstQuery.compareAndSet(true, false)) {
310 sb.append(agg.toString());
317 return sb.toString();