/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.solr.client.solrj; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.regex.Pattern; import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.FacetParams; import org.apache.solr.common.params.HighlightParams; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.MoreLikeThisParams; import org.apache.solr.common.params.StatsParams; import org.apache.solr.common.params.TermsParams; /** * This is an augmented SolrParams with get/set/add fields for common fields used * in the Standard and Dismax request handlers * * * @since solr 1.3 */ public class SolrQuery extends ModifiableSolrParams { public static final String DOCID = "_docid_"; // duplicate of org.apache.solr.search.SortSpecParsing.DOCID which is not accessible from here public enum ORDER { desc, asc; public ORDER reverse() { return (this == asc) ? desc : asc; } } /** Maintains a map of current sorts */ private List<SortClause> sortClauses; public SolrQuery() { super(); } /** Create a new SolrQuery * * @param q query string */ public SolrQuery(String q) { this(); this.set(CommonParams.Q, q); } public SolrQuery(String k, String v, String... params) { assert params.length % 2 == 0; this.set(k, v); for (int i = 0; i < params.length; i += 2) { this.set(params[i], params[i + 1]); } } /** enable/disable terms. * * @param b flag to indicate terms should be enabled. <br> if b==false, removes all other terms parameters * @return Current reference (<i>this</i>) */ public SolrQuery setTerms(boolean b) { if (b) { this.set(TermsParams.TERMS, true); } else { this.remove(TermsParams.TERMS); this.remove(TermsParams.TERMS_FIELD); this.remove(TermsParams.TERMS_LOWER); this.remove(TermsParams.TERMS_UPPER); this.remove(TermsParams.TERMS_UPPER_INCLUSIVE); this.remove(TermsParams.TERMS_LOWER_INCLUSIVE); this.remove(TermsParams.TERMS_LIMIT); this.remove(TermsParams.TERMS_PREFIX_STR); this.remove(TermsParams.TERMS_MINCOUNT); this.remove(TermsParams.TERMS_MAXCOUNT); this.remove(TermsParams.TERMS_RAW); this.remove(TermsParams.TERMS_SORT); this.remove(TermsParams.TERMS_REGEXP_STR); this.remove(TermsParams.TERMS_REGEXP_FLAG); } return this; } public boolean getTerms() { return this.getBool(TermsParams.TERMS, false); } public SolrQuery addTermsField(String field) { this.add(TermsParams.TERMS_FIELD, field); return this; } public String[] getTermsFields() { return this.getParams(TermsParams.TERMS_FIELD); } public SolrQuery setTermsLower(String lower) { this.set(TermsParams.TERMS_LOWER, lower); return this; } public String getTermsLower() { return this.get(TermsParams.TERMS_LOWER, ""); } public SolrQuery setTermsUpper(String upper) { this.set(TermsParams.TERMS_UPPER, upper); return this; } public String getTermsUpper() { return this.get(TermsParams.TERMS_UPPER, ""); } public SolrQuery setTermsUpperInclusive(boolean b) { this.set(TermsParams.TERMS_UPPER_INCLUSIVE, b); return this; } public boolean getTermsUpperInclusive() { return this.getBool(TermsParams.TERMS_UPPER_INCLUSIVE, false); } public SolrQuery setTermsLowerInclusive(boolean b) { this.set(TermsParams.TERMS_LOWER_INCLUSIVE, b); return this; } public boolean getTermsLowerInclusive() { return this.getBool(TermsParams.TERMS_LOWER_INCLUSIVE, true); } public SolrQuery setTermsLimit(int limit) { this.set(TermsParams.TERMS_LIMIT, limit); return this; } public int getTermsLimit() { return this.getInt(TermsParams.TERMS_LIMIT, 10); } public SolrQuery setTermsMinCount(int cnt) { this.set(TermsParams.TERMS_MINCOUNT, cnt); return this; } public int getTermsMinCount() { return this.getInt(TermsParams.TERMS_MINCOUNT, 1); } public SolrQuery setTermsMaxCount(int cnt) { this.set(TermsParams.TERMS_MAXCOUNT, cnt); return this; } public int getTermsMaxCount() { return this.getInt(TermsParams.TERMS_MAXCOUNT, -1); } public SolrQuery setTermsPrefix(String prefix) { this.set(TermsParams.TERMS_PREFIX_STR, prefix); return this; } public String getTermsPrefix() { return this.get(TermsParams.TERMS_PREFIX_STR, ""); } public SolrQuery setTermsRaw(boolean b) { this.set(TermsParams.TERMS_RAW, b); return this; } public boolean getTermsRaw() { return this.getBool(TermsParams.TERMS_RAW, false); } public SolrQuery setTermsSortString(String type) { this.set(TermsParams.TERMS_SORT, type); return this; } public String getTermsSortString() { return this.get(TermsParams.TERMS_SORT, TermsParams.TERMS_SORT_COUNT); } public SolrQuery setTermsRegex(String regex) { this.set(TermsParams.TERMS_REGEXP_STR, regex); return this; } public String getTermsRegex() { return this.get(TermsParams.TERMS_REGEXP_STR); } public SolrQuery setTermsRegexFlag(String flag) { this.add(TermsParams.TERMS_REGEXP_FLAG, flag); return this; } public String[] getTermsRegexFlags() { return this.getParams(TermsParams.TERMS_REGEXP_FLAG); } /** Add field(s) for facet computation. * * @param fields Array of field names from the IndexSchema * @return this */ public SolrQuery addFacetField(String ... fields) { add(FacetParams.FACET_FIELD, fields); this.set(FacetParams.FACET, true); return this; } /** Add field(s) for pivot computation. * * pivot fields are comma separated * * @param fields Array of field names from the IndexSchema * @return this */ public SolrQuery addFacetPivotField(String ... fields) { add(FacetParams.FACET_PIVOT, fields); this.set(FacetParams.FACET, true); return this; } /** * Add a numeric range facet. * * @param field The field * @param start The start of range * @param end The end of the range * @param gap The gap between each count * @return this */ public SolrQuery addNumericRangeFacet(String field, Number start, Number end, Number gap) { add(FacetParams.FACET_RANGE, field); add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_START), start.toString()); add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_END), end.toString()); add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_GAP), gap.toString()); this.set(FacetParams.FACET, true); return this; } /** * Add a numeric range facet. * * @param field The field * @param start The start of range * @param end The end of the range * @param gap The gap between each count * @return this */ public SolrQuery addDateRangeFacet(String field, Date start, Date end, String gap) { add(FacetParams.FACET_RANGE, field); add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_START), start.toInstant().toString()); add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_END), end.toInstant().toString()); add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_GAP), gap); this.set(FacetParams.FACET, true); return this; } /** * Add Interval Faceting on a field. All intervals for the same field should be included * in the same call to this method. * For syntax documentation see <a href="https://wiki.apache.org/solr/SimpleFacetParameters#Interval_Faceting">Solr wiki</a>. * <br> * Key substitution, filter exclusions or other local params on the field are not supported when using this method, * if this is needed, use the lower level {@link #add} method.<br> * Key substitution IS supported on intervals when using this method. * * * @param field the field to add facet intervals. Must be an existing field and can't be null * @param intervals Intervals to be used for faceting. It can be an empty array, but it can't * be <code>null</code> * @return this */ public SolrQuery addIntervalFacets(String field, String[] intervals) { if (intervals == null) { throw new IllegalArgumentException("Can't add null intervals"); } if (field == null) { throw new IllegalArgumentException("Field can't be null"); } set(FacetParams.FACET, true); add(FacetParams.FACET_INTERVAL, field); for (String interval:intervals) { add(String.format(Locale.ROOT, "f.%s.facet.interval.set", field), interval); } return this; } /** * Remove all Interval Facets on a field * * @param field the field to remove from facet intervals * @return Array of current intervals for <code>field</code> */ public String[] removeIntervalFacets(String field) { while(remove(FacetParams.FACET_INTERVAL, field)){}; return remove(String.format(Locale.ROOT, "f.%s.facet.interval.set", field)); } /** get the facet fields * * @return string array of facet fields or null if not set/empty */ public String[] getFacetFields() { return this.getParams(FacetParams.FACET_FIELD); } /** remove a facet field * * @param name Name of the facet field to be removed. * * @return true, if the item was removed. <br> * false, if the facet field was null or did not exist. */ public boolean removeFacetField(String name) { boolean b = this.remove(FacetParams.FACET_FIELD, name); if (this.get(FacetParams.FACET_FIELD) == null && this.get(FacetParams.FACET_QUERY) == null) { this.setFacet(false); } return b; } /** enable/disable faceting. * * @param b flag to indicate faceting should be enabled. <br> if b==false, removes all other faceting parameters * @return Current reference (<i>this</i>) */ public SolrQuery setFacet(boolean b) { if (b) { this.set(FacetParams.FACET, true); } else { this.remove(FacetParams.FACET); this.remove(FacetParams.FACET_MINCOUNT); this.remove(FacetParams.FACET_FIELD); this.remove(FacetParams.FACET_LIMIT); this.remove(FacetParams.FACET_MISSING); this.remove(FacetParams.FACET_OFFSET); this.remove(FacetParams.FACET_PREFIX); this.remove(FacetParams.FACET_QUERY); this.remove(FacetParams.FACET_SORT); this.remove(FacetParams.FACET_ZEROS); this.remove(FacetParams.FACET_PREFIX); // does not include the individual fields... this.remove(FacetParams.FACET_INTERVAL); // does not remove interval parameters } return this; } public SolrQuery setFacetPrefix( String prefix ) { this.set( FacetParams.FACET_PREFIX, prefix ); return this; } public SolrQuery setFacetPrefix( String field, String prefix ) { this.set( "f."+field+"."+FacetParams.FACET_PREFIX, prefix ); return this; } /** add a faceting query * * @param f facet query */ public SolrQuery addFacetQuery(String f) { this.add(FacetParams.FACET_QUERY, f); this.set(FacetParams.FACET, true); return this; } /** get facet queries * * @return all facet queries or null if not set/empty */ public String[] getFacetQuery() { return this.getParams(FacetParams.FACET_QUERY); } /** remove a facet query * * @param q the facet query to remove * @return true if the facet query was removed false otherwise */ public boolean removeFacetQuery(String q) { boolean b = this.remove(FacetParams.FACET_QUERY, q); if (this.get(FacetParams.FACET_FIELD) == null && this.get(FacetParams.FACET_QUERY) == null) { this.setFacet(false); } return b; } /** set the facet limit * * @param lim number facet items to return */ public SolrQuery setFacetLimit(int lim) { this.set(FacetParams.FACET_LIMIT, lim); return this; } /** get current facet limit * * @return facet limit or default of 25 */ public int getFacetLimit() { return this.getInt(FacetParams.FACET_LIMIT, 25); } /** set facet minimum count * * @param cnt facets having less that cnt hits will be excluded from teh facet list */ public SolrQuery setFacetMinCount(int cnt) { this.set(FacetParams.FACET_MINCOUNT, cnt); return this; } /** get facet minimum count * * @return facet minimum count or default of 1 */ public int getFacetMinCount() { return this.getInt(FacetParams.FACET_MINCOUNT, 1); } /** * Sets facet missing boolean flag * * @param v flag to indicate the field of {@link FacetParams#FACET_MISSING} . * @return this */ public SolrQuery setFacetMissing(Boolean v) { this.set(FacetParams.FACET_MISSING, v); return this; } /** get facet sort * * @return facet sort or default of {@link FacetParams#FACET_SORT_COUNT} */ public String getFacetSortString() { return this.get(FacetParams.FACET_SORT, FacetParams.FACET_SORT_COUNT); } /** set facet sort * * @param sort sort facets * @return this */ public SolrQuery setFacetSort(String sort) { this.set(FacetParams.FACET_SORT, sort); return this; } /** add highlight field * * @param f field to enable for highlighting */ public SolrQuery addHighlightField(String f) { this.add(HighlightParams.FIELDS, f); this.set(HighlightParams.HIGHLIGHT, true); return this; } /** remove a field for highlighting * * @param f field name to not highlight * @return <i>true</i>, if removed, <br> <i>false</i>, otherwise */ public boolean removeHighlightField(String f) { boolean b = this.remove(HighlightParams.FIELDS, f); if (this.get(HighlightParams.FIELDS) == null) { this.setHighlight(false); } return b; } /** get list of highlighted fields * * @return Array of highlight fields or null if not set/empty */ public String[] getHighlightFields() { return this.getParams(HighlightParams.FIELDS); } public SolrQuery setHighlightSnippets(int num) { this.set(HighlightParams.SNIPPETS, num); return this; } public int getHighlightSnippets() { return this.getInt(HighlightParams.SNIPPETS, 1); } public SolrQuery setHighlightFragsize(int num) { this.set(HighlightParams.FRAGSIZE, num); return this; } public int getHighlightFragsize() { return this.getInt(HighlightParams.FRAGSIZE, 100); } public SolrQuery setHighlightRequireFieldMatch(boolean flag) { this.set(HighlightParams.FIELD_MATCH, flag); return this; } public boolean getHighlightRequireFieldMatch() { return this.getBool(HighlightParams.FIELD_MATCH, false); } public SolrQuery setHighlightSimplePre(String f) { this.set(HighlightParams.SIMPLE_PRE, f); return this; } public String getHighlightSimplePre() { return this.get(HighlightParams.SIMPLE_PRE, ""); } public SolrQuery setHighlightSimplePost(String f) { this.set(HighlightParams.SIMPLE_POST, f); return this; } public String getHighlightSimplePost() { return this.get(HighlightParams.SIMPLE_POST, ""); } /** * Gets the raw sort field, as it will be sent to Solr. * <p> * The returned sort field will always contain a serialized version * of the sort string built using {@link #setSort(SortClause)}, * {@link #addSort(SortClause)}, {@link #addOrUpdateSort(SortClause)}, * {@link #removeSort(SortClause)}, {@link #clearSorts()} and * {@link #setSorts(List)}. */ public String getSortField() { return this.get(CommonParams.SORT); } /** * Clears current sort information. * * @return the modified SolrQuery object, for easy chaining * @since 4.2 */ public SolrQuery clearSorts() { sortClauses = null; serializeSorts(); return this; } /** * Replaces the current sort information. * * @return the modified SolrQuery object, for easy chaining * @since 4.2 */ public SolrQuery setSorts(List<SortClause> value) { sortClauses = new ArrayList<>(value); serializeSorts(); return this; } /** * Gets an a list of current sort clauses. * * @return an immutable list of current sort clauses * @since 4.2 */ public List<SortClause> getSorts() { if (sortClauses == null) return Collections.emptyList(); else return Collections.unmodifiableList(sortClauses); } /** * Replaces the current sort information with a single sort clause * * @return the modified SolrQuery object, for easy chaining * @since 4.2 */ public SolrQuery setSort(String field, ORDER order) { return setSort(new SortClause(field, order)); } /** * Replaces the current sort information with a single sort clause * * @return the modified SolrQuery object, for easy chaining * @since 4.2 */ public SolrQuery setSort(SortClause sortClause) { clearSorts(); return addSort(sortClause); } /** * Adds a single sort clause to the end of the current sort information. * * @return the modified SolrQuery object, for easy chaining * @since 4.2 */ public SolrQuery addSort(String field, ORDER order) { return addSort(new SortClause(field, order)); } /** * Adds a single sort clause to the end of the query. * * @return the modified SolrQuery object, for easy chaining * @since 4.2 */ public SolrQuery addSort(SortClause sortClause) { if (sortClauses == null) sortClauses = new ArrayList<>(); sortClauses.add(sortClause); serializeSorts(); return this; } /** * Updates or adds a single sort clause to the query. * If the field is already used for sorting, the order * of the existing field is modified; otherwise, it is * added to the end. * <p> * @return the modified SolrQuery object, for easy chaining * @since 4.2 */ public SolrQuery addOrUpdateSort(String field, ORDER order) { return addOrUpdateSort(new SortClause(field, order)); } /** * Updates or adds a single sort field specification to the current sort * information. If the sort field already exist in the sort information map, * its position is unchanged and the sort order is set; if it does not exist, * it is appended at the end with the specified order.. * * @return the modified SolrQuery object, for easy chaining * @since 4.2 */ public SolrQuery addOrUpdateSort(SortClause sortClause) { if (sortClauses != null) { for (int index=0 ; index<sortClauses.size() ; index++) { SortClause existing = sortClauses.get(index); if (existing.getItem().equals(sortClause.getItem())) { sortClauses.set(index, sortClause); serializeSorts(); return this; } } } return addSort(sortClause); } /** * Removes a single sort field from the current sort information. * * @return the modified SolrQuery object, for easy chaining * @since 4.2 */ public SolrQuery removeSort(SortClause sortClause) { return removeSort(sortClause.getItem()); } /** * Removes a single sort field from the current sort information. * * @return the modified SolrQuery object, for easy chaining * @since 4.2 */ public SolrQuery removeSort(String itemName) { if (sortClauses != null) { for (SortClause existing : sortClauses) { if (existing.getItem().equals(itemName)) { sortClauses.remove(existing); if (sortClauses.isEmpty()) sortClauses = null; serializeSorts(); break; } } } return this; } private void serializeSorts() { if (sortClauses == null || sortClauses.isEmpty()) { remove(CommonParams.SORT); } else { StringBuilder sb = new StringBuilder(); for (SortClause sortClause : sortClauses) { if (sb.length() > 0) sb.append(","); sb.append(sortClause.getItem()); sb.append(" "); sb.append(sortClause.getOrder()); } set(CommonParams.SORT, sb.toString()); } } public void setGetFieldStatistics( boolean v ) { this.set( StatsParams.STATS, v ); } public void setGetFieldStatistics( String field ) { this.set( StatsParams.STATS, true ); this.add( StatsParams.STATS_FIELD, field ); } public void addGetFieldStatistics( String ... field ) { this.set( StatsParams.STATS, true ); this.add( StatsParams.STATS_FIELD, field ); } public void addStatsFieldFacets( String field, String ... facets ) { if( field == null ) { this.add( StatsParams.STATS_FACET, facets ); } else { for( String f : facets ) { this.add( "f."+field+"."+StatsParams.STATS_FACET, f ); } } } public void addStatsFieldCalcDistinct(String field, boolean calcDistinct) { if (field == null) { this.add(StatsParams.STATS_CALC_DISTINCT, Boolean.toString(calcDistinct)); } else { this.add("f." + field + "." + StatsParams.STATS_CALC_DISTINCT, Boolean.toString(calcDistinct)); } } public SolrQuery setFilterQueries(String ... fq) { this.set(CommonParams.FQ, fq); return this; } public SolrQuery addFilterQuery(String ... fq) { this.add(CommonParams.FQ, fq); return this; } public boolean removeFilterQuery(String fq) { return this.remove(CommonParams.FQ, fq); } public String[] getFilterQueries() { return this.getParams(CommonParams.FQ); } public boolean getHighlight() { return this.getBool(HighlightParams.HIGHLIGHT, false); } public SolrQuery setHighlight(boolean b) { if (b) { this.set(HighlightParams.HIGHLIGHT, true); } else { this.remove(HighlightParams.HIGHLIGHT); this.remove(HighlightParams.FIELD_MATCH); this.remove(HighlightParams.FIELDS); this.remove(HighlightParams.FORMATTER); this.remove(HighlightParams.FRAGSIZE); this.remove(HighlightParams.SIMPLE_POST); this.remove(HighlightParams.SIMPLE_PRE); this.remove(HighlightParams.SNIPPETS); } return this; } /** * Add field for MoreLikeThis. Automatically * enables MoreLikeThis. * * @param field the names of the field to be added * @return this */ public SolrQuery addMoreLikeThisField(String field) { this.setMoreLikeThis(true); return addValueToParam(MoreLikeThisParams.SIMILARITY_FIELDS, field); } public SolrQuery setMoreLikeThisFields(String... fields) { if( fields == null || fields.length == 0 ) { this.remove( MoreLikeThisParams.SIMILARITY_FIELDS ); this.setMoreLikeThis(false); return this; } StringBuilder sb = new StringBuilder(); sb.append(fields[0]); for (int i = 1; i < fields.length; i++) { sb.append(','); sb.append(fields[i]); } this.set(MoreLikeThisParams.SIMILARITY_FIELDS, sb.toString()); this.setMoreLikeThis(true); return this; } /** * @return an array with the fields used to compute similarity. */ public String[] getMoreLikeThisFields() { String fl = this.get(MoreLikeThisParams.SIMILARITY_FIELDS); if(fl==null || fl.length()==0) { return null; } return fl.split(","); } /** * Sets the frequency below which terms will be ignored in the source doc * * @param mintf the minimum term frequency * @return this */ public SolrQuery setMoreLikeThisMinTermFreq(int mintf) { this.set(MoreLikeThisParams.MIN_TERM_FREQ, mintf); return this; } /** * Gets the frequency below which terms will be ignored in the source doc */ public int getMoreLikeThisMinTermFreq() { return this.getInt(MoreLikeThisParams.MIN_TERM_FREQ, 2); } /** * Sets the frequency at which words will be ignored which do not occur in * at least this many docs. * * @param mindf the minimum document frequency * @return this */ public SolrQuery setMoreLikeThisMinDocFreq(int mindf) { this.set(MoreLikeThisParams.MIN_DOC_FREQ, mindf); return this; } /** * Gets the frequency at which words will be ignored which do not occur in * at least this many docs. */ public int getMoreLikeThisMinDocFreq() { return this.getInt(MoreLikeThisParams.MIN_DOC_FREQ, 5); } /** * Sets the minimum word length below which words will be ignored. * * @param minwl the minimum word length * @return this */ public SolrQuery setMoreLikeThisMinWordLen(int minwl) { this.set(MoreLikeThisParams.MIN_WORD_LEN, minwl); return this; } /** * Gets the minimum word length below which words will be ignored. */ public int getMoreLikeThisMinWordLen() { return this.getInt(MoreLikeThisParams.MIN_WORD_LEN, 0); } /** * Sets the maximum word length above which words will be ignored. * * @param maxwl the maximum word length * @return this */ public SolrQuery setMoreLikeThisMaxWordLen(int maxwl) { this.set(MoreLikeThisParams.MAX_WORD_LEN, maxwl); return this; } /** * Gets the maximum word length above which words will be ignored. */ public int getMoreLikeThisMaxWordLen() { return this.getInt(MoreLikeThisParams.MAX_WORD_LEN, 0); } /** * Sets the maximum number of query terms that will be included in any * generated query. * * @param maxqt the maximum number of query terms * @return this */ public SolrQuery setMoreLikeThisMaxQueryTerms(int maxqt) { this.set(MoreLikeThisParams.MAX_QUERY_TERMS, maxqt); return this; } /** * Gets the maximum number of query terms that will be included in any * generated query. */ public int getMoreLikeThisMaxQueryTerms() { return this.getInt(MoreLikeThisParams.MAX_QUERY_TERMS, 25); } /** * Sets the maximum number of tokens to parse in each example doc field * that is not stored with TermVector support. * * @param maxntp the maximum number of tokens to parse * @return this */ public SolrQuery setMoreLikeThisMaxTokensParsed(int maxntp) { this.set(MoreLikeThisParams.MAX_NUM_TOKENS_PARSED, maxntp); return this; } /** * Gets the maximum number of tokens to parse in each example doc field * that is not stored with TermVector support. */ public int getMoreLikeThisMaxTokensParsed() { return this.getInt(MoreLikeThisParams.MAX_NUM_TOKENS_PARSED, 5000); } /** * Sets if the query will be boosted by the interesting term relevance. * * @param b set to true to boost the query with the interesting term relevance * @return this */ public SolrQuery setMoreLikeThisBoost(boolean b) { this.set(MoreLikeThisParams.BOOST, b); return this; } /** * Gets if the query will be boosted by the interesting term relevance. */ public boolean getMoreLikeThisBoost() { return this.getBool(MoreLikeThisParams.BOOST, false); } /** * Sets the query fields and their boosts using the same format as that * used in DisMaxQParserPlugin. These fields must also be added * using {@link #addMoreLikeThisField(String)}. * * @param qf the query fields * @return this */ public SolrQuery setMoreLikeThisQF(String qf) { this.set(MoreLikeThisParams.QF, qf); return this; } /** * Gets the query fields and their boosts. */ public String getMoreLikeThisQF() { return this.get(MoreLikeThisParams.QF); } /** * Sets the number of similar documents to return for each result. * * @param count the number of similar documents to return for each result * @return this */ public SolrQuery setMoreLikeThisCount(int count) { this.set(MoreLikeThisParams.DOC_COUNT, count); return this; } /** * Gets the number of similar documents to return for each result. */ public int getMoreLikeThisCount() { return this.getInt(MoreLikeThisParams.DOC_COUNT, MoreLikeThisParams.DEFAULT_DOC_COUNT); } /** * Enable/Disable MoreLikeThis. After enabling MoreLikeThis, the fields * used for computing similarity must be specified calling * {@link #addMoreLikeThisField(String)}. * * @param b flag to indicate if MoreLikeThis should be enabled. if b==false * removes all mlt.* parameters * @return this */ public SolrQuery setMoreLikeThis(boolean b) { if(b) { this.set(MoreLikeThisParams.MLT, true); } else { this.remove(MoreLikeThisParams.MLT); this.remove(MoreLikeThisParams.SIMILARITY_FIELDS); this.remove(MoreLikeThisParams.MIN_TERM_FREQ); this.remove(MoreLikeThisParams.MIN_DOC_FREQ); this.remove(MoreLikeThisParams.MIN_WORD_LEN); this.remove(MoreLikeThisParams.MAX_WORD_LEN); this.remove(MoreLikeThisParams.MAX_QUERY_TERMS); this.remove(MoreLikeThisParams.MAX_NUM_TOKENS_PARSED); this.remove(MoreLikeThisParams.BOOST); this.remove(MoreLikeThisParams.QF); this.remove(MoreLikeThisParams.DOC_COUNT); } return this; } /** * @return true if MoreLikeThis is enabled, false otherwise */ public boolean getMoreLikeThis() { return this.getBool(MoreLikeThisParams.MLT, false); } public SolrQuery setFields(String ... fields) { if( fields == null || fields.length == 0 ) { this.remove( CommonParams.FL ); return this; } StringBuilder sb = new StringBuilder(); sb.append( fields[0] ); for( int i=1; i<fields.length; i++ ) { sb.append( ',' ); sb.append( fields[i] ); } this.set(CommonParams.FL, sb.toString() ); return this; } public SolrQuery addField(String field) { return addValueToParam(CommonParams.FL, field); } public String getFields() { String fields = this.get(CommonParams.FL); if (fields!=null && fields.equals("score")) { fields = "*, score"; } return fields; } private static Pattern scorePattern = Pattern.compile("(^|[, ])score"); public SolrQuery setIncludeScore(boolean includeScore) { String fields = get(CommonParams.FL,"*"); if (includeScore) { if (!scorePattern.matcher(fields).find()) { this.set(CommonParams.FL, fields+",score"); } } else { this.set(CommonParams.FL, scorePattern.matcher(fields).replaceAll("")); } return this; } public SolrQuery setQuery(String query) { this.set(CommonParams.Q, query); return this; } public String getQuery() { return this.get(CommonParams.Q); } public SolrQuery setRows(Integer rows) { if( rows == null ) { this.remove( CommonParams.ROWS ); } else { this.set(CommonParams.ROWS, rows); } return this; } public Integer getRows() { return this.getInt(CommonParams.ROWS); } public SolrQuery setShowDebugInfo(boolean showDebugInfo) { this.set(CommonParams.DEBUG_QUERY, String.valueOf(showDebugInfo)); return this; } public void setDistrib(boolean val) { this.set(CommonParams.DISTRIB, String.valueOf(val)); } public SolrQuery setStart(Integer start) { if( start == null ) { this.remove( CommonParams.START ); } else { this.set(CommonParams.START, start); } return this; } public Integer getStart() { return this.getInt(CommonParams.START); } /** * The Request Handler to use (see the solrconfig.xml), which is stored in the "qt" parameter. * Normally it starts with a '/' and if so it will be used by * {@link org.apache.solr.client.solrj.request.QueryRequest#getPath()} in the URL instead of the "qt" parameter. * If this is left blank, then the default of "/select" is assumed. * * @param qt The Request Handler name corresponding to one in solrconfig.xml on the server. * @return this */ public SolrQuery setRequestHandler(String qt) { this.set(CommonParams.QT, qt); return this; } public String getRequestHandler() { return this.get(CommonParams.QT); } /** * @return this * @see ModifiableSolrParams#set(String,String[]) */ public SolrQuery setParam(String name, String ... values) { this.set(name, values); return this; } /** * @return this * @see org.apache.solr.common.params.ModifiableSolrParams#set(String, boolean) */ public SolrQuery setParam(String name, boolean value) { this.set(name, value); return this; } /** get a deep copy of this object **/ public SolrQuery getCopy() { SolrQuery q = new SolrQuery(); for (String name : this.getParameterNames()) { q.setParam(name, this.getParams(name)); } return q; } /** * Set the maximum time allowed for this query. If the query takes more time * than the specified milliseconds, a timeout occurs and partial (or no) * results may be returned. * * If given Integer is null, then this parameter is removed from the request * *@param milliseconds the time in milliseconds allowed for this query */ public SolrQuery setTimeAllowed(Integer milliseconds) { if (milliseconds == null) { this.remove(CommonParams.TIME_ALLOWED); } else { this.set(CommonParams.TIME_ALLOWED, milliseconds); } return this; } /** * Get the maximum time allowed for this query. */ public Integer getTimeAllowed() { return this.getInt(CommonParams.TIME_ALLOWED); } /////////////////////// // Utility functions /////////////////////// private String toSortString(String field, ORDER order) { return field.trim() + ' ' + String.valueOf(order).trim(); } private String join(String a, String b, String sep) { StringBuilder sb = new StringBuilder(); if (a!=null && a.length()>0) { sb.append(a); sb.append(sep); } if (b!=null && b.length()>0) { sb.append(b); } return sb.toString().trim(); } private SolrQuery addValueToParam(String name, String value) { String tmp = this.get(name); tmp = join(tmp, value, ","); this.set(name, tmp); return this; } private String join(String[] vals, String sep, String removeVal) { StringBuilder sb = new StringBuilder(); for (int i=0; i<vals.length; i++) { if (!vals[i].equals(removeVal)) { if (sb.length() > 0) { sb.append(sep); } sb.append(vals[i]); } } return sb.toString().trim(); } /** * A single sort clause, encapsulating what to sort and the sort order. * <p> * The item specified can be "anything sortable" by solr; some examples * include a simple field name, the constant string {@code score}, and functions * such as {@code sum(x_f, y_f)}. * <p> * A SortClause can be created through different mechanisms: * <PRE><code> * new SortClause("product", SolrQuery.ORDER.asc); * new SortClause("product", "asc"); * SortClause.asc("product"); * SortClause.desc("product"); * </code></PRE> */ public static class SortClause implements java.io.Serializable { private static final long serialVersionUID = 1L; private final String item; private final ORDER order; /** * Creates a SortClause based on item and order * @param item item to sort on * @param order direction to sort */ public SortClause(String item, ORDER order) { this.item = item; this.order = order; } /** * Creates a SortClause based on item and order * @param item item to sort on * @param order string value for direction to sort */ public SortClause(String item, String order) { this(item, ORDER.valueOf(order)); } /** * Creates an ascending SortClause for an item * @param item item to sort on */ public static SortClause create (String item, ORDER order) { return new SortClause(item, order); } /** * Creates a SortClause based on item and order * @param item item to sort on * @param order string value for direction to sort */ public static SortClause create(String item, String order) { return new SortClause(item, ORDER.valueOf(order)); } /** * Creates an ascending SortClause for an item * @param item item to sort on */ public static SortClause asc (String item) { return new SortClause(item, ORDER.asc); } /** * Creates a decending SortClause for an item * @param item item to sort on */ public static SortClause desc (String item) { return new SortClause(item, ORDER.desc); } /** * Gets the item to sort, typically a function or a fieldname * @return item to sort */ public String getItem() { return item; } /** * Gets the order to sort * @return order to sort */ public ORDER getOrder() { return order; } public boolean equals(Object other){ if (this == other) return true; if (!(other instanceof SortClause)) return false; final SortClause that = (SortClause) other; return this.getItem().equals(that.getItem()) && this.getOrder().equals(that.getOrder()); } public int hashCode(){ return this.getItem().hashCode(); } /** * Gets a human readable description of the sort clause. * <p> * The returned string is not suitable for passing to Solr, * but may be useful in debug output and the like. * @return a description of the current sort clause */ public String toString() { return "[" + getClass().getSimpleName() + ": item=" + getItem() + "; order=" + getOrder() + "]"; } } }