Index: oak-solr-core/pom.xml =================================================================== --- oak-solr-core/pom.xml (revision 1584525) +++ oak-solr-core/pom.xml (working copy) @@ -32,6 +32,13 @@ Oak support for Apache Solr indexing and search bundle + + + org.apache.jackrabbit.core.query.FulltextQueryTest#testMultipleOrExpressions + org.apache.jackrabbit.core.query.FulltextQueryTest#testMultiByte + + + Index: oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/DefaultSolrConfiguration.java =================================================================== --- oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/DefaultSolrConfiguration.java (revision 1584525) +++ oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/configuration/DefaultSolrConfiguration.java (working copy) @@ -20,7 +20,7 @@ import org.apache.jackrabbit.oak.spi.query.Filter; /** - * An {@link org.apache.jackrabbit.oak.plugins.index.solr.configuration.OakSolrConfiguration} for the embedded Solr server + * Default {@link org.apache.jackrabbit.oak.plugins.index.solr.configuration.OakSolrConfiguration} */ public class DefaultSolrConfiguration implements OakSolrConfiguration { Index: oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java =================================================================== --- oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java (revision 1584525) +++ oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java (working copy) @@ -133,15 +133,14 @@ int mltFlIndex = parameterString.indexOf(mltFlString); if (mltFlIndex > -1) { int beginIndex = mltFlIndex + mltFlString.length(); - int endIndex = parameterString.indexOf('&',beginIndex); + int endIndex = parameterString.indexOf('&', beginIndex); String fields; if (endIndex > beginIndex) { fields = parameterString.substring(beginIndex, endIndex); - } - else { + } else { fields = parameterString.substring(beginIndex); } - kv[1] = "_query_:\"{!dismax qf="+fields+" q.op=OR}"+kv[1]+"\""; + kv[1] = "_query_:\"{!dismax qf=" + fields + " q.op=OR}" + kv[1] + "\""; } } solrQuery.setParam(kv[0], kv[1]); @@ -258,9 +257,7 @@ } FullTextExpression e = or.list.get(i); String orTerm = getFullTextQuery(e); - fullTextString.append('('); fullTextString.append(orTerm); - fullTextString.append(')'); } fullTextString.append(')'); fullTextString.append(' '); @@ -276,9 +273,7 @@ } FullTextExpression e = and.list.get(i); String andTerm = getFullTextQuery(e); - fullTextString.append('('); fullTextString.append(andTerm); - fullTextString.append(')'); } fullTextString.append(')'); fullTextString.append(' '); @@ -299,7 +294,14 @@ } fullTextString.append(p); fullTextString.append(':'); - fullTextString.append(partialEscape(term.getText())); + String termText = term.getText(); + if (termText.indexOf(' ') > 0) { + fullTextString.append('"'); + } + fullTextString.append(termText.replace("/", "\\/").replace(":", "\\:")); + if (termText.indexOf(' ') > 0) { + fullTextString.append('"'); + } String boost = term.getBoost(); if (boost != null) { fullTextString.append('^'); Index: oak-solr-core/src/main/resources/solr/oak/conf/schema.xml =================================================================== --- oak-solr-core/src/main/resources/solr/oak/conf/schema.xml (revision 1584525) +++ oak-solr-core/src/main/resources/solr/oak/conf/schema.xml (working copy) @@ -131,7 +131,7 @@ - + path_exact Index: oak-solr-core/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryJcrTest.java =================================================================== --- oak-solr-core/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryJcrTest.java (revision 1584525) +++ oak-solr-core/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryJcrTest.java (working copy) @@ -19,7 +19,7 @@ import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; -import org.apache.jackrabbit.core.query.LimitAndOffsetTest; +import org.apache.jackrabbit.core.query.FulltextQueryTest; import org.apache.jackrabbit.core.query.PathQueryNodeTest; import org.apache.jackrabbit.core.query.SQL2OffsetLimitTest; import org.apache.jackrabbit.core.query.SQL2QueryResultTest; @@ -36,7 +36,7 @@ public static Test suite() { TestSuite suite = new ConcurrentTestSuite( "Jackrabbit query tests using a Solr based index"); -// suite.addTestSuite(FulltextQueryTest.class); // fail + suite.addTestSuite(FulltextQueryTest.class); // fail suite.addTestSuite(SQLTest.class); // suite.addTestSuite(JoinTest.class); // fail suite.addTestSuite(SkipDeletedNodesTest.class); Index: oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTest.java =================================================================== --- oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTest.java (revision 1584525) +++ oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTest.java (working copy) @@ -17,6 +17,8 @@ package org.apache.jackrabbit.oak.plugins.index.solr.query; import java.util.Iterator; + +import com.google.common.collect.ImmutableList; import org.apache.jackrabbit.oak.Oak; import org.apache.jackrabbit.oak.api.ContentRepository; import org.apache.jackrabbit.oak.api.Tree; @@ -72,11 +74,11 @@ .with(new CompositeQueryIndexProvider( new SolrQueryIndexProvider(provider, provider), new PropertyIndexProvider() - )) + )) .with(new CompositeIndexEditorProvider( new SolrIndexEditorProvider(provider, provider), new PropertyIndexEditorProvider() - )) + )) .createContentRepository(); } catch (Exception e) { throw new RuntimeException(e); @@ -275,4 +277,95 @@ test("native_solr.txt"); } +// @Test +// public void testFulltextExcludeSQL() throws Exception { +// +// String sql = "SELECT * FROM nt:base" +// + " WHERE \"jcr:path\" LIKE '/test/%" +// + "' AND CONTAINS(., 'text ''fox jumps'' -other')"; +// +// Tree tree = root.getTree("/"); +// Tree test = tree.addChild("test"); +// Tree a = test.addChild("a"); +// a.setProperty("title", "test text"); +// a.setProperty("mytext", "the quick brown fox jumps over the lazy dog."); +// Tree b = test.addChild("b"); +// b.setProperty("title", "other text"); +// b.setProperty("mytext", "the quick brown fox jumps over the lazy dog."); +// Tree c = test.addChild("c"); +// c.setProperty("name", "Halo Welt, today sky is cloudy"); +// root.commit(); +// +// Iterator strings = executeQuery(sql, "sql").iterator(); +// assertTrue(strings.hasNext()); +// assertEquals("/test/a", strings.next()); +// assertFalse(strings.hasNext()); +// +// } + +// @Test +// public void testContainsPropScopeSQL() throws Exception { +// +// String sql = "SELECT * FROM nt:base" +// + " WHERE jcr:path LIKE '/test/%" +// + "' AND CONTAINS(mytext, 'fox jumps')"; +// +// Tree tree = root.getTree("/"); +// Tree test = tree.addChild("test"); +// Tree a = test.addChild("a"); +// a.setProperty("title", "test text"); +// a.setProperty("mytext", "the quick brown fox jumps over the lazy dog."); +// Tree b = test.addChild("b"); +// b.setProperty("title", "other text"); +// b.setProperty("mytext", "the quick brown fox suddenly jumps over the lazy dog."); +// Tree c = test.addChild("c"); +// c.setProperty("name", "Halo Welt, today sky is cloudy"); +// root.commit(); +// +// Iterator strings = executeQuery(sql, "sql").iterator(); +// assertTrue(strings.hasNext()); +// assertEquals("/test/a", strings.next()); +// assertFalse(strings.hasNext()); +// +// } + + +// @Test +// public void testMultiByte() throws Exception { +// String multibyte = "\u7530\u4e2d"; +// String sql = "SELECT * FROM nt:base" +// + " WHERE jcr:path LIKE '/test/%" +// + "' AND CONTAINS(., '" + multibyte + "')"; +// +// Tree tree = root.getTree("/"); +// Tree test = tree.addChild("test"); +// Tree a = test.addChild("a"); +// a.setProperty("title", "some text with multi byte " + multibyte + " characters."); +// root.commit(); +// +// Iterator strings = executeQuery(sql, "sql").iterator(); +// assertTrue(strings.hasNext()); +// assertEquals("/test/a", strings.next()); +// assertFalse(strings.hasNext()); +// +// StringBuffer stmt = new StringBuffer(); +// stmt.append("/jcr:root").append("/test").append("/*"); +// stmt.append("[jcr:contains(., '").append(multibyte).append("*"); +// stmt.append("')]"); +// +// String xpath = stmt.toString(); +// strings = executeQuery(xpath, "xpath").iterator(); +// assertTrue(strings.hasNext()); +// assertEquals("/test/a", strings.next()); +// assertFalse(strings.hasNext()); +// } + + @Test + public void testTokenizeCN() throws Exception { + Tree t = root.getTree("/").addChild("containsCN"); + Tree one = t.addChild("one"); + one.setProperty("t", "美女衬衫"); + root.commit(); + assertQuery("//*[jcr:contains(., '美女')]", "xpath", ImmutableList.of(one.getPath())); + } } Index: oak-solr-core/src/test/resources/solr/oak/conf/schema.xml =================================================================== --- oak-solr-core/src/test/resources/solr/oak/conf/schema.xml (revision 1584525) +++ oak-solr-core/src/test/resources/solr/oak/conf/schema.xml (working copy) @@ -141,7 +141,7 @@ - + path_exact