/* * Copyright 2014, Stratio. * Modification and adapations - Copyright 2014, Tuplejump Inc. * * 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 * * http://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.tuplejump.stargate.lucene.query; import com.tuplejump.stargate.lucene.Options; import com.tuplejump.stargate.lucene.query.function.Function; import com.tuplejump.stargate.lucene.query.function.NoOp; import org.apache.lucene.search.*; import org.codehaus.jackson.annotate.JsonCreator; import org.codehaus.jackson.annotate.JsonProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Class representing an Lucene's index search. It is formed by an optional querying {@link Condition} and an optional * filtering {@link Condition}. It can be translated to a Lucene's {@link Query} using a {@link com.tuplejump.stargate.lucene.Options}. */ public class Search { private static final Logger logger = LoggerFactory.getLogger(Search.class); /** * The querying condition */ private final Condition queryCondition; /** * The filtering condition */ private final Condition filterCondition; /** * The sort to apply */ private final Sort sort; private final Function function; private final boolean showScore; /** * Returns a new {@link Search} composed by the specified querying and filtering conditions. * * @param queryCondition The {@link Condition} for querying, maybe {@code null} meaning no querying. * @param filterCondition The {@link Condition} for filtering, maybe {@code null} meaning no filtering. * @param sort The {@link Sort} for sorting, may be {@code null} meaning no sorting * @param function The {@link Function} for aggregation, may be {@code null} meaning no aggregation * @param showScore To show score in results. */ @JsonCreator public Search(@JsonProperty("query") Condition queryCondition, @JsonProperty("filter") Condition filterCondition, @JsonProperty("sort") Sort sort, @JsonProperty("function") Function function, @JsonProperty("score") boolean showScore) { this.queryCondition = queryCondition; this.filterCondition = filterCondition; this.sort = sort; if (function == null) this.function = new NoOp(); else this.function = function; this.showScore = showScore; } /** * Returns {@code true} if the results must be ordered by relevance. If {@code false}, then the results are sorted * by the natural Cassandra's order. Results must be ordered by relevance if the querying condition is not {code * null}. * Relevance is used when the query condition is set, and it is not used when only the filter condition is set. * * @return {@code true} if the results must be ordered by relevance. If {@code false}, then the results must be * sorted by the natural Cassandra's order. */ public boolean usesSorting() { return queryCondition != null || sort != null; } public Function function() { return this.function; } public boolean isShowScore() { return showScore; } /** * Returns the Lucene's {@link Query} representation of this search. This {@link Query} include both the querying * and filtering {@link Condition}s. If none of them is set, then a {@link MatchAllDocsQuery} is returned. * * @param schema the schema * @return The Lucene's {@link Query} representation of this search. * @throws Exception when the query cannot be constructed */ public Query query(Options schema) throws Exception { Query query = queryCondition == null ? null : queryCondition.query(schema); Query filter = filterCondition == null ? null : filterCondition.filter(schema); if (query == null && filter == null) { return new MatchAllDocsQuery(); } else if (query != null) { if (queryCondition.getBoost() != Condition.DEFAULT_BOOST) { return new BoostQuery(query, queryCondition.getBoost()); } if (filter == null) { return query; } else { BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); booleanQuery.add(query, BooleanClause.Occur.MUST); booleanQuery.add(filter, BooleanClause.Occur.FILTER); return booleanQuery.build(); } } else { return new ConstantScoreQuery(filter); } } public org.apache.lucene.search.SortField[] sort(Options schema) { return sort == null ? null : sort.sort(schema); } /** * Returns a new {@link Search} from the specified JSON {@code String}. * * @param json A JSON {@code String} representing a {@link Search}. * @return The {@link Search} represented by the specified JSON {@code String}. */ public static Search fromJson(String json) { try { return Options.inputMapper.readValue(json, Search.class); } catch (Exception e) { String message = "Cannot parse JSON index expression: " + json; logger.error(message, e); throw new IllegalArgumentException(message, e); } } /** * {@inheritDoc} */ @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Search [query="); builder.append(queryCondition); builder.append(", filter="); builder.append(filterCondition); builder.append("]"); return builder.toString(); } }