/** * This software is licensed to you under the Apache License, Version 2.0 (the * "Apache License"). * * LinkedIn's contributions are made under the Apache License. If you contribute * to the Software, the contributions will be deemed to have been made under the * Apache License, unless you expressly indicate otherwise. Please do not make any * contributions that would be inconsistent with the Apache License. * * You may obtain a copy of the Apache License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, this software * distributed under the Apache License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Apache * License for the specific language governing permissions and limitations for the * software governed under the Apache License. * * © 2012 LinkedIn Corp. All Rights Reserved. */ package com.senseidb.search.query; import java.util.ArrayList; import java.util.List; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.DisjunctionMaxQuery; import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.util.Version; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; public class QueryStringQueryConstructor extends QueryConstructor { public static final String QUERY_TYPE = "query_string"; private QueryParser _qparser; public QueryStringQueryConstructor(QueryParser qparser) { _qparser = qparser; } @Override public Query doConstructQuery(JSONObject jsonQuery) throws JSONException { String queryText = jsonQuery.optString(QUERY_PARAM, null); if (queryText == null || queryText.length() == 0) { return new MatchAllDocsQuery(); } try { for (String name : JSONObject.getNames(jsonQuery)) { if (QUERY_PARAM.equals(name)) continue; if (BOOST_PARAM.equals(name)) continue; List<String> fields = new ArrayList<String>(); String defaultField = jsonQuery.optString(DEFAULT_FIELD_PARAM, null); if (defaultField != null && defaultField.length() != 0) fields.add(defaultField); JSONArray fieldsArray = jsonQuery.optJSONArray(FIELDS_PARAM); if (fieldsArray != null) { for (int i=0; i<fieldsArray.length(); ++i) { String field = fieldsArray.optString(i, null); if (field != null && field.length() != 0) fields.add(field); } } if (fields.size() == 0) fields.add("contents"); String default_operator = jsonQuery.optString(DEFAULT_OPERATOR_PARAM, "or"); boolean allow_leading_wildcard = jsonQuery.optBoolean(ALLOW_LEADING_WILDCARD_PARAM, true); boolean lowercase_expanded_terms = jsonQuery.optBoolean(LOWERCASE_EXPANDED_TERMS_PARAM, true); boolean enable_position_increments = jsonQuery.optBoolean(ENABLE_POSITION_INCREMENTS_PARAM, true); int fuzzy_prefix_length = jsonQuery.optInt(FUZZY_PREFIX_LENGTH_PARAM, 0); float fuzzy_min_sim = (float)jsonQuery.optDouble(FUZZY_MIN_SIM_PARAM, 0.5); int phrase_slop = jsonQuery.optInt(PHRASE_SLOP_PARAM, 0); //boolean analyze_wildcard = jsonQuery.optBoolean(ANALYZE_WILDCARD_PARAM, false); //boolean auto_generate_phrase_queries = jsonQuery.optBoolean(AUTO_GENERATE_PHRASE_QUERIES_PARAM, false); boolean use_dis_max = jsonQuery.optBoolean(USE_DIS_MAX_PARAM, true); float tie_breaker = (float)jsonQuery.optDouble(TIE_BREAKER_PARAM, .0); List<Query> queries = new ArrayList<Query>(fields.size()); for (String field : fields) { QueryParser qparser = new QueryParser(Version.LUCENE_CURRENT, field, _qparser.getAnalyzer()); qparser.setAllowLeadingWildcard(allow_leading_wildcard); qparser.setEnablePositionIncrements(enable_position_increments); qparser.setFuzzyMinSim(fuzzy_min_sim); qparser.setFuzzyPrefixLength(fuzzy_prefix_length); qparser.setLowercaseExpandedTerms(lowercase_expanded_terms); qparser.setPhraseSlop(phrase_slop); queries.add(qparser.parse(queryText)); } if (fields.size() == 1) { Query query = queries.get(0); query.setBoost((float)jsonQuery.optDouble(BOOST_PARAM, 1.0)); return query; } if (use_dis_max) { Query query = new DisjunctionMaxQuery(queries, tie_breaker); query.setBoost((float)jsonQuery.optDouble(BOOST_PARAM, 1.0)); return query; } else { BooleanQuery query = new BooleanQuery(); if (AND_PARAM.equals(default_operator)) { for (Query q : queries) { query.add(q, BooleanClause.Occur.MUST); } } else { for (Query q : queries) { query.add(q, BooleanClause.Occur.SHOULD); } } query.setBoost((float)jsonQuery.optDouble(BOOST_PARAM, 1.0)); return query; } } synchronized(_qparser) { Query query = _qparser.parse(queryText); query.setBoost((float)jsonQuery.optDouble(BOOST_PARAM, 1.0)); return query; } } catch (ParseException e) { throw new JSONException(e); } } }