Index: oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java =================================================================== --- oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java (revision 1574507) +++ oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java (working copy) @@ -54,7 +54,6 @@ import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; - import org.apache.jackrabbit.oak.plugins.index.aggregate.NodeAggregator; import org.apache.jackrabbit.oak.query.fulltext.FullTextAnd; import org.apache.jackrabbit.oak.query.fulltext.FullTextExpression; @@ -79,6 +78,7 @@ import org.apache.lucene.index.Term; import org.apache.lucene.index.Terms; import org.apache.lucene.index.TermsEnum; +import org.apache.lucene.queries.mlt.MoreLikeThis; import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.BooleanClause; @@ -104,11 +104,11 @@ /** * Provides a QueryIndex that does lookups against a Lucene-based index - * + * *
* To define a lucene index on a subtree you have to add an
* oak:index node.
- *
+ *
* Under it follows the index definition node that:
*
*
- *
+ *
* @see QueryIndex
- *
+ *
*/
public class LuceneIndex implements FulltextQueryIndex {
@@ -200,7 +200,7 @@
* { "a", "c" } is returned. If there are no relative properties, then one
* entry is returned (the empty string). If there is no expression, then an
* empty set is returned.
- *
+ *
* @param ft the full-text expression
* @return the set of relative paths (possibly empty)
*/
@@ -409,7 +409,7 @@
/**
* Get the Lucene query for the given filter.
- *
+ *
* @param filter the filter, including full-text constraint
* @param reader the Lucene reader
* @param nonFullTextConstraints whether non-full-text constraints (such a
@@ -431,13 +431,51 @@
}
PropertyRestriction pr = filter.getPropertyRestriction(NATIVE_QUERY_FUNCTION);
if (pr != null) {
+ String query = String.valueOf(pr.first.getValue(pr.first.getType()));
QueryParser queryParser = new QueryParser(VERSION, "", analyzer);
- String query = String.valueOf(pr.first.getValue(pr.first.getType()));
- try {
- qs.add(queryParser.parse(query));
- } catch (ParseException e) {
- throw new RuntimeException(e);
+ if (query.startsWith("mlt?")) {
+ String mltQueryString = query.replace("mlt?", "");
+ if (reader != null) {
+ MoreLikeThis mlt = new MoreLikeThis(reader);
+ mlt.setAnalyzer(analyzer);
+ try {
+ String text = null;
+ for (String param : mltQueryString.split("&")) {
+ String[] kv = param.split("=");
+ if (kv.length != 2 || kv[0] == null || kv[1] == null) {
+ throw new RuntimeException("Unparsable native Lucene MLT query: "+mltQueryString);
+ } else {
+ if ("stream.body".equals(kv[0])) {
+ text = kv[1];
+ }
+ else if ("mlt.fl".equals(kv[0])) {
+ mlt.setFieldNames(kv[1].split(","));
+ }
+ else if ("mlt.mindf".equals(kv[0])) {
+ mlt.setMinDocFreq(Integer.parseInt(kv[1]));
+ }
+ else if ("mlt.mintf".equals(kv[0])) {
+ mlt.setMinTermFreq(Integer.parseInt(kv[1]));
+ }
+ // TODO : add support for other MLT parameters
+ }
+ }
+ if (text != null) {
+ Query mltQuery = mlt.like(new StringReader(text), mlt.getFieldNames()[0]);
+ qs.add(mltQuery);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("could not handle MLT query " + query);
+ }
+ }
}
+ else {
+ try {
+ qs.add(queryParser.parse(query));
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
else if (nonFullTextConstraints) {
addNonFullTextConstraints(qs, filter, reader, analyzer);
@@ -772,8 +810,8 @@
/**
* Tries to merge back tokens that are split on relevant fulltext query
* wildcards ('*' or '?')
- *
- *
+ *
+ *
* @param text
* @param analyzer
* @return
Index: oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.java
===================================================================
--- oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.java (revision 1574507)
+++ oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.java (working copy)
@@ -253,4 +253,23 @@
assertFalse(result.hasNext());
}
+ @Test
+ public void testNativeMLTQuery() throws Exception {
+ String nativeQueryString = "select [jcr:path] from [nt:base] where native('lucene', 'mlt?stream.body=World&mlt.fl=name&mlt.mindf=0&mlt.mintf=0')";
+
+ Tree tree = root.getTree("/");
+ Tree test = tree.addChild("test");
+ test.addChild("a").setProperty("name", "Hello World, today weather is nice");
+ test.addChild("b").setProperty("name", "Cheers World, today weather is quite nice");
+ tree.addChild("c");
+ root.commit();
+
+ Iterator
*
oak:QueryIndexDefinition