diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 27b96967f96..8834a428312 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -255,6 +255,11 @@ New Features
* SOLR-2099: Add ability to throttle rsync based replication using rsync option --bwlimit.
(Brandon Evans via koji)
+* SOLR-2113: Add TermQParserPlugin, registered as "term". This is useful
+ when generating filter queries from terms returned from field faceting or
+ the terms component. Example: fq={!term f=weight}1.5 (hossman, yonik)
+
+
Optimizations
----------------------
diff --git a/solr/src/java/org/apache/solr/search/QParserPlugin.java b/solr/src/java/org/apache/solr/search/QParserPlugin.java
index 738dbbfdb07..55059e3dcca 100755
--- a/solr/src/java/org/apache/solr/search/QParserPlugin.java
+++ b/solr/src/java/org/apache/solr/search/QParserPlugin.java
@@ -35,6 +35,7 @@ public abstract class QParserPlugin implements NamedListInitializedPlugin {
ExtendedDismaxQParserPlugin.NAME, ExtendedDismaxQParserPlugin.class,
FieldQParserPlugin.NAME, FieldQParserPlugin.class,
RawQParserPlugin.NAME, RawQParserPlugin.class,
+ TermQParserPlugin.NAME, TermQParserPlugin.class,
NestedQParserPlugin.NAME, NestedQParserPlugin.class,
FunctionRangeQParserPlugin.NAME, FunctionRangeQParserPlugin.class,
SpatialFilterQParserPlugin.NAME, SpatialFilterQParserPlugin.class,
diff --git a/solr/src/java/org/apache/solr/search/RawQParserPlugin.java b/solr/src/java/org/apache/solr/search/RawQParserPlugin.java
index dae4a13c546..70d4d5d8861 100644
--- a/solr/src/java/org/apache/solr/search/RawQParserPlugin.java
+++ b/solr/src/java/org/apache/solr/search/RawQParserPlugin.java
@@ -26,6 +26,11 @@ import org.apache.solr.request.SolrQueryRequest;
/**
* Create a term query from the input value without any text analysis or transformation whatsoever.
+ * This is useful in debugging, or when raw terms are returned from the terms component (this is not the default).
+ *
+ *
For easy filter construction to drill down in faceting, the {@link TermQParserPlugin} is recommended.
+ *
For full analysis on all fields, including text fields, see the {@link FieldQParserPlugin}.
+ *
*
Other parameters: f
, the field
*
Example: {!raw f=myfield}Foo Bar
creates TermQuery(Term("myfield","Foo Bar"))
*/
diff --git a/solr/src/java/org/apache/solr/search/TermQParserPlugin.java b/solr/src/java/org/apache/solr/search/TermQParserPlugin.java
new file mode 100644
index 00000000000..5499a71dfe0
--- /dev/null
+++ b/solr/src/java/org/apache/solr/search/TermQParserPlugin.java
@@ -0,0 +1,66 @@
+/**
+ * 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.search;
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.util.BytesRef;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.schema.FieldType;
+
+/**
+ * Create a single term query from the input value equivalent to readableToIndexed().
+ * This is useful for generating filter queries from the external human readable terms returned by the
+ * faceting or terms components.
+ *
+ *
+ * For text fields, no analysis is done since raw terms are already returned from the faceting
+ * and terms components, and not all text analysis is idempotent.
+ * To apply analysis to text fields as well, see the {@link FieldQParserPlugin}.
+ *
+ * If no analysis or transformation is desired for any type of field, see the {@link RawQParserPlugin}.
+ *
+ *
Other parameters: f
, the field
+ *
Example: {!term f=weight}1.5
+ */
+public class TermQParserPlugin extends QParserPlugin {
+ public static String NAME = "term";
+
+ public void init(NamedList args) {
+ }
+
+ public QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
+ return new QParser(qstr, localParams, params, req) {
+ public Query parse() throws ParseException {
+ String fname = localParams.get(QueryParsing.F);
+ FieldType ft = req.getSchema().getFieldTypeNoEx(fname);
+ String val = localParams.get(QueryParsing.V);
+ BytesRef term = new BytesRef();
+ if (ft != null) {
+ ft.readableToIndexed(val, term);
+ } else {
+ term.copy(val);
+ }
+ return new TermQuery(new Term(fname, term));
+ }
+ };
+ }
+}
diff --git a/solr/src/test/org/apache/solr/search/TestQueryTypes.java b/solr/src/test/org/apache/solr/search/TestQueryTypes.java
index 99478199147..6f61378bb5e 100755
--- a/solr/src/test/org/apache/solr/search/TestQueryTypes.java
+++ b/solr/src/test/org/apache/solr/search/TestQueryTypes.java
@@ -118,6 +118,8 @@ public class TestQueryTypes extends AbstractSolrTestCase {
req("q","{!raw f=v_t}hello")
,"//result[@numFound='2']"
);
+
+ // no analysis is done, so these should match nothing
assertQ("test raw query",
req("q","{!raw f=v_t}Hello")
,"//result[@numFound='0']"
@@ -127,6 +129,23 @@ public class TestQueryTypes extends AbstractSolrTestCase {
,"//result[@numFound='0']"
);
+ // test "term" qparser, which should only do readableToIndexed
+ assertQ(
+ req("q","{!term f=v_f}1.5")
+ ,"//result[@numFound='1']"
+ );
+
+ // text fields are *not* analyzed since they may not be idempotent
+ assertQ(
+ req("q","{!term f=v_t}Hello")
+ ,"//result[@numFound='0']"
+ );
+ assertQ(
+ req("q","{!term f=v_t}hello")
+ ,"//result[@numFound='2']"
+ );
+
+
//
// test escapes in quoted strings
//