You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by to...@apache.org on 2015/03/09 13:21:50 UTC
svn commit: r1665206 - in /jackrabbit/oak/branches/1.0: ./
oak-core/src/main/java/org/apache/jackrabbit/oak/query/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/
oak-core/src/te...
Author: tommaso
Date: Mon Mar 9 12:21:49 2015
New Revision: 1665206
URL: http://svn.apache.org/r1665206
Log:
OAK-2175 - backported to branch 1.0
Added:
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java
- copied, changed from r1656019, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java
jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneRequestFacade.java
- copied unchanged from r1656019, jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneRequestFacade.java
jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/SpellcheckHelper.java
- copied unchanged from r1656019, jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/SpellcheckHelper.java
jackrabbit/oak/branches/1.0/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/SpellcheckTest.java
- copied unchanged from r1656019, jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/SpellcheckTest.java
jackrabbit/oak/branches/1.0/oak-lucene/src/test/resources/org/apache/jackrabbit/oak/query/
- copied from r1656019, jackrabbit/oak/trunk/oak-lucene/src/test/resources/org/apache/jackrabbit/oak/query/
jackrabbit/oak/branches/1.0/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/jcr/query/SpellcheckTest.java
- copied unchanged from r1656019, jackrabbit/oak/trunk/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/jcr/query/SpellcheckTest.java
jackrabbit/oak/branches/1.0/oak-solr-core/src/test/resources/org/apache/jackrabbit/oak/query/sql1.txt
- copied unchanged from r1656019, jackrabbit/oak/trunk/oak-solr-core/src/test/resources/org/apache/jackrabbit/oak/query/sql1.txt
Modified:
jackrabbit/oak/branches/1.0/ (props changed)
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
jackrabbit/oak/branches/1.0/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql1.txt
jackrabbit/oak/branches/1.0/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt
jackrabbit/oak/branches/1.0/oak-lucene/pom.xml
jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java
jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/AdvancedSolrQueryIndex.java
jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParser.java
jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java
jackrabbit/oak/branches/1.0/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml
jackrabbit/oak/branches/1.0/oak-solr-core/src/main/resources/solr/oak/conf/solrconfig.xml
jackrabbit/oak/branches/1.0/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTestIT.java
jackrabbit/oak/branches/1.0/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml
jackrabbit/oak/branches/1.0/oak-solr-core/src/test/resources/solr/oak/conf/solrconfig.xml
Propchange: jackrabbit/oak/branches/1.0/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Mar 9 12:21:49 2015
@@ -1,2 +1,2 @@
-/jackrabbit/oak/trunk:1584578,1584602,1584614,1584616,1584709,1584781,1584937,1585297,1585304-1585305,1585420,1585424,1585427,1585448,1585465,1585468,1585486,1585497,1585509,1585647,1585655-1585656,1585661,1585665-1585666,1585669-1585670,1585673,1585680,1585719,1585763,1585770,1585896,1585904,1585907,1585940,1585949,1585951,1585956,1585962-1585963,1586287,1586320,1586364,1586372,1586655,1586836,1587130,1587224,1587399,1587408,1587472,1587485,1587488,1587538,1587580,1587807,1588033,1588042,1588046,1588066,1588201,1589025,1589101,1589137,1589141,1589263,1589440,1589442,1589484,1589488,1589661,1589664,1589682,1589708,1589741,1589748,1589789,1589794,1589850,1589864,1590628,1590660,1590684,1590697,1590701,1590980,1590988,1591101,1591226,1591229,1591293,1591314,1591317,1591362,1591374,1591381,1591438,1591467,1591552,1591704,1591713,1591715,1591723,1591874,1592487,1592512,1592658,1592665,1592677,1592742,1592744,1592787,1592809,1592955,1593036,1593048,1593061,1593133,1593210-1593211,1593231
,1593245,1593250,1593294,1593304,1593317,1593342,1593554,1594158-1594164,1594166-1594167,1594169,1594237,1594800,1594808,1594835,1594888,1595147,1595457,1595856,1596241,1596474,1596534,1596844,1597569,1597795,1597854,1597860,1598292,1598302,1598352,1598369,1598595,1598631,1598696,1598732,1598797-1598798,1599299,1599332,1599416,1599434,1599671,1600088,1600935,1601309,1601388,1601578,1601649,1601676,1601757,1601768,1601814,1601833,1601838,1601853,1601878,1601888,1601922,1602156,1602170,1602174,1602179,1602183,1602201,1602207,1602227,1602256,1602261,1602342,1602796-1602797,1602800,1602809,1602853,1602872,1602914,1603155,1603307,1603401,1603441,1603748,1604166,1605030,1605036,1605038,1605292,1605447,1605526,1605670,1605725,1605831,1605852,1606077,1606079,1606087,1606638,1606641,1606644,1606708,1606711,1607031-1607032,1607077,1607127,1607141,1607152,1607185,1607196,1607331,1607362,1607366,1607392,1607526,1607557,1607664,1607737,1608560,1608731,1608783,1609064,1609081,1609165,1609214,1609
488,1610489,1610592,1610603,1610634,1610658,1610664,1611021,1611041,1611270,1611275,1611277,1611313,1611332,1611584,1612560,1612825,1612993,1613018,1613041,1614265,1614272,1614344-1614345,1614384-1614385,1614397,1614405-1614406,1614574,1614591,1614593,1614596,1614604,1614689,1614807,1614835,1614891,1615417-1615418,1616182,1616236,1616463,1616719,1617417,1617451,1617463,1617711,1618158,1618613,1618624,1618709,1619222,1619411,1619695,1619800,1619808,1619815,1619823-1619824,1620512,1620581,1620585,1620634,1620898,1620905,1621115,1621123-1621124,1621168,1621192,1621201,1621706,1621962,1622197,1622201,1622207,1622250,1622479,1623364,1623766,1623827,1623949,1623969,1623973,1624216,1624317,1624551,1624559,1624973,1624993-1624994,1625025,1625036,1625158,1625224,1625237,1625299,1625348,1625620,1625916,1625962-1625963,1626021,1626053,1626163,1626168,1626175,1626191,1626265,1626770,1627047,1627052,1627228,1627346,1627470,1627473,1627479,1627503,1627586,1627590,1627715,1627731,1628180,1628198,1
628262,1628447,1628608,1629688,1629840,1629917,1630055-1630057,1630156,1630299,1630338,1630773,1631283-1631284,1631333-1631334,1631617-1631619,1631630,1631699,1631704,1631711,1631967-1631969,1631986,1631990,1631999,1632002-1632003,1632017,1632258,1632264,1632270,1632293,1632303,1632592,1632605,1633315,1633559-1633560,1633562,1633567,1633571,1633598,1633608,1633641,1633687,1633697,1633768,1633783,1634505,1634513,1634774,1634779,1634781,1634792,1634803,1634814,1634816,1634838,1634841,1634852,1634864,1634896,1634898,1635044-1635045,1635060,1635077,1635089,1635102,1635108,1635218,1635387,1635435,1635518,1635563,1635586,1636336,1636348,1636505,1636585,1636799,1637368,1637382,1637413,1637651,1637815,1638779-1638783,1639260,1639577,1639622,1639963,1639966,1639973,1640134,1640143,1640555-1640556,1640694-1640695,1640715,1640722-1640723,1640728,1640863-1640872,1641340,1641350,1641352,1641541,1641596-1641599,1641601,1641662,1641671,1641695,1641771,1641802,1641811,1641950,1642031,1642056,164211
9,1642285,1642648,1642667,1642954,1642959,1643111,1643178,1643186,1643204,1643287,1643767,1643774,1643982,1644016,1644106,1644366,1644383,1644397-1644398,1644407,1644479,1644547,1644552,1644554,1644588,1644645,1644650,1644654,1644689,1644750,1645421,1645424,1645459,1645585,1645611,1645637,1645646,1645660-1645663,1645888,1645901,1645948,1645966,1645970-1645971,1646014,1646164,1646174,1646469,1646684,1646766,1646795,1646981,1649743,1649803,1650015,1650239,1650529,1650797,1651323,1651382,1651643,1651652,1651730,1651988-1651989,1651996,1652024,1652035,1652058-1652059,1652075,1652127,1652158,1652467,1652965,1652971,1653207,1653446,1653463,1653484,1653572,1653579,1653591,1653804,1653809,1653813,1653848-1653850,1653882,1654116,1654174,1654743,1654756,1654778,1655049,1655054-1655055,1655086,1655237,1655248,1655996,1656027,1656394,1656400,1656425,1656427,1656453,1656628,1657804,1658470,1659483,1659527,1659550,1659578,1659765,1660154-1660155,1660383,1660409,1660426,1660676,1660870,1660872,166
0897,1660903,1661069,1661122,1661146,1661158,1661226,1661630,1661643,1661645,1662313-1662315,1662323,1662450,1663241,1663275,1663288,1663448,1663565,1663666,1663705,1663730,1664038,1664184,1664228-1664229,1664231
+/jackrabbit/oak/trunk:1584578,1584602,1584614,1584616,1584709,1584781,1584937,1585297,1585304-1585305,1585420,1585424,1585427,1585448,1585465,1585468,1585486,1585497,1585509,1585647,1585655-1585656,1585661,1585665-1585666,1585669-1585670,1585673,1585680,1585719,1585763,1585770,1585896,1585904,1585907,1585940,1585949,1585951,1585956,1585962-1585963,1586287,1586320,1586364,1586372,1586655,1586836,1587130,1587224,1587399,1587408,1587472,1587485,1587488,1587538,1587580,1587807,1588033,1588042,1588046,1588066,1588201,1589025,1589101,1589137,1589141,1589263,1589440,1589442,1589484,1589488,1589661,1589664,1589682,1589708,1589741,1589748,1589789,1589794,1589850,1589864,1590628,1590660,1590684,1590697,1590701,1590980,1590988,1591101,1591226,1591229,1591293,1591314,1591317,1591362,1591374,1591381,1591438,1591467,1591552,1591704,1591713,1591715,1591723,1591874,1592487,1592512,1592658,1592665,1592677,1592742,1592744,1592787,1592809,1592955,1593036,1593048,1593061,1593133,1593210-1593211,1593231
,1593245,1593250,1593294,1593304,1593317,1593342,1593554,1594158-1594164,1594166-1594167,1594169,1594237,1594800,1594808,1594835,1594888,1595147,1595457,1595856,1596241,1596474,1596534,1596844,1597569,1597795,1597854,1597860,1598292,1598302,1598352,1598369,1598595,1598631,1598696,1598732,1598797-1598798,1599299,1599332,1599416,1599434,1599671,1600088,1600935,1601309,1601388,1601578,1601649,1601676,1601757,1601768,1601814,1601833,1601838,1601853,1601878,1601888,1601922,1602156,1602170,1602174,1602179,1602183,1602201,1602207,1602227,1602256,1602261,1602342,1602796-1602797,1602800,1602809,1602853,1602872,1602914,1603155,1603307,1603401,1603441,1603748,1604166,1605030,1605036,1605038,1605292,1605447,1605526,1605670,1605725,1605831,1605852,1606077,1606079,1606087,1606638,1606641,1606644,1606708,1606711,1607031-1607032,1607077,1607127,1607141,1607152,1607185,1607196,1607331,1607362,1607366,1607392,1607526,1607557,1607664,1607737,1608560,1608731,1608783,1609064,1609081,1609165,1609214,1609
488,1610489,1610592,1610603,1610634,1610658,1610664,1611021,1611041,1611270,1611275,1611277,1611313,1611332,1611584,1612560,1612825,1612993,1613018,1613041,1614265,1614272,1614344-1614345,1614384-1614385,1614397,1614405-1614406,1614574,1614591,1614593,1614596,1614604,1614689,1614807,1614835,1614891,1615417-1615418,1616182,1616236,1616463,1616719,1617417,1617451,1617463,1617711,1618158,1618613,1618624,1618709,1619222,1619411,1619695,1619800,1619808,1619815,1619823-1619824,1620512,1620581,1620585,1620634,1620898,1620905,1621115,1621123-1621124,1621168,1621192,1621201,1621706,1621962,1622197,1622201,1622207,1622250,1622479,1623364,1623766,1623827,1623949,1623969,1623973,1624216,1624317,1624551,1624559,1624973,1624993-1624994,1625025,1625036,1625158,1625224,1625237,1625299,1625348,1625620,1625916,1625962-1625963,1626021,1626053,1626163,1626168,1626175,1626191,1626265,1626770,1627047,1627052,1627228,1627346,1627470,1627473,1627479,1627503,1627586,1627590,1627715,1627731,1628180,1628198,1
628262,1628447,1628608,1629688,1629840,1629917,1630055-1630057,1630156,1630299,1630338,1630773,1631283-1631284,1631333-1631334,1631617-1631619,1631630,1631699,1631704,1631711,1631967-1631969,1631986,1631990,1631999,1632002-1632003,1632017,1632258,1632264,1632270,1632293,1632303,1632592,1632605,1633315,1633559-1633560,1633562,1633567,1633571,1633598,1633608,1633641,1633687,1633697,1633768,1633783,1634505,1634513,1634774,1634779,1634781,1634792,1634803,1634814,1634816,1634838,1634841,1634852,1634864,1634896,1634898,1635044-1635045,1635060,1635077,1635089,1635102,1635108,1635218,1635387,1635435,1635518,1635563,1635586,1636336,1636348,1636505,1636585,1636799,1637368,1637382,1637413,1637651,1637815,1638779-1638783,1639260,1639577,1639622,1639963,1639966,1639973,1640134,1640143,1640555-1640556,1640694-1640695,1640715,1640722-1640723,1640728,1640863-1640872,1641340,1641350,1641352,1641541,1641596-1641599,1641601,1641662,1641671,1641695,1641771,1641802,1641811,1641950,1642031,1642056,164211
9,1642285,1642648,1642667,1642954,1642959,1643111,1643178,1643186,1643204,1643287,1643767,1643774,1643982,1644016,1644106,1644366,1644383,1644397-1644398,1644407,1644479,1644547,1644552,1644554,1644588,1644645,1644650,1644654,1644689,1644750,1645421,1645424,1645459,1645585,1645611,1645637,1645646,1645660-1645663,1645888,1645901,1645948,1645966,1645970-1645971,1646014,1646164,1646174,1646469,1646684,1646766,1646795,1646981,1649743,1649803,1650015,1650239,1650529,1650797,1651323,1651382,1651643,1651652,1651730,1651988-1651989,1651996,1652024,1652035,1652058-1652059,1652075,1652127,1652158,1652467,1652965,1652971,1653207,1653446,1653463,1653484,1653572,1653579,1653591,1653804,1653809,1653813,1653848-1653850,1653882,1654116,1654174,1654743,1654756,1654778,1655049,1655054-1655055,1655086,1655237,1655248,1655996,1656019,1656027,1656033,1656394,1656400,1656425,1656427,1656453,1656628,1656678,1657804,1658470,1659483,1659527,1659550,1659578,1659765,1660154-1660155,1660383,1660409,1660426,166
0676,1660870,1660872,1660897,1660903,1661069,1661122,1661146,1661158,1661226,1661630,1661643,1661645,1662313-1662315,1662323,1662450,1663241,1663275,1663288,1663448,1663565,1663666,1663705,1663730,1664038,1664184,1664228-1664229,1664231
/jackrabbit/trunk:1345480
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java Mon Mar 9 12:21:49 2015
@@ -62,6 +62,7 @@ import org.apache.jackrabbit.oak.query.a
import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
import org.apache.jackrabbit.oak.query.ast.SimilarImpl;
import org.apache.jackrabbit.oak.query.ast.SourceImpl;
+import org.apache.jackrabbit.oak.query.ast.SpellcheckImpl;
import org.apache.jackrabbit.oak.query.ast.UpperCaseImpl;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
import org.apache.jackrabbit.oak.query.index.TraversingIndex;
@@ -101,6 +102,11 @@ public class QueryImpl implements Query
*/
public static final String REP_EXCERPT = "rep:excerpt";
+ /**
+ * The "rep:spellcheck" pseudo-property.
+ */
+ public static final String REP_SPELLCHECK = "rep:spellcheck()";
+
private static final Logger LOG = LoggerFactory.getLogger(QueryImpl.class);
SourceImpl source;
@@ -226,6 +232,13 @@ public class QueryImpl implements Query
node.setQuery(query);
node.bindSelector(source);
return super.visit(node);
+ }
+
+ @Override
+ public boolean visit(SpellcheckImpl node) {
+ node.setQuery(query);
+ node.bindSelector(source);
+ return super.visit(node);
}
@Override
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java Mon Mar 9 12:21:49 2015
@@ -555,6 +555,15 @@ public class SQL2Parser {
String language = readString().getValue(Type.STRING);
read(",");
c = factory.nativeFunction(selectorName, language, parseStaticOperand());
+ } else if ("SPELLCHECK".equalsIgnoreCase(functionName)) {
+ String selectorName;
+ if (currentTokenType == IDENTIFIER) {
+ selectorName = readName();
+ read(",");
+ } else {
+ selectorName = getOnlySelectorName();
+ }
+ c = factory.spellcheck(selectorName, parseStaticOperand());
} else {
return null;
}
@@ -827,26 +836,29 @@ public class SQL2Parser {
}
read(")");
}
+ readOptionalAlias(column);
} else {
column.propertyName = readName();
- if (readIf(".")) {
+ if (column.propertyName.equals("rep:spellcheck")) {
+ if (readIf("(")) {
+ read(")");
+ column.propertyName = ":spellcheck";
+ }
+ readOptionalAlias(column);
+ } else if (readIf(".")) {
column.selectorName = column.propertyName;
if (readIf("*")) {
column.propertyName = null;
} else {
column.propertyName = readName();
- if (readIf("AS")) {
- column.columnName = readName();
- } else {
+ if (!readOptionalAlias(column)) {
column.columnName =
column.selectorName
+ "." + column.propertyName;
}
}
} else {
- if (readIf("AS")) {
- column.columnName = readName();
- }
+ readOptionalAlias(column);
}
}
list.add(column);
@@ -854,6 +866,14 @@ public class SQL2Parser {
}
return list;
}
+
+ private boolean readOptionalAlias(ColumnOrWildcard column) throws ParseException {
+ if (readIf("AS")) {
+ column.columnName = readName();
+ return true;
+ }
+ return false;
+ }
private ColumnImpl[] resolveColumns(ArrayList<ColumnOrWildcard> list) throws ParseException {
ArrayList<ColumnImpl> columns = new ArrayList<ColumnImpl>();
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java Mon Mar 9 12:21:49 2015
@@ -157,4 +157,8 @@ public class AstElementFactory {
return new SimilarImpl(selectorName, propertyName, path);
}
+ public ConstraintImpl spellcheck(String selectorName, StaticOperandImpl expression) {
+ return new SpellcheckImpl(selectorName, expression);
+ }
+
}
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java Mon Mar 9 12:21:49 2015
@@ -79,8 +79,10 @@ public interface AstVisitor {
boolean visit(UpperCaseImpl node);
- boolean visit(NativeFunctionImpl nativeFunctionImpl);
+ boolean visit(NativeFunctionImpl node);
- boolean visit(SimilarImpl similarImpl);
+ boolean visit(SimilarImpl node);
+
+ boolean visit(SpellcheckImpl node);
}
\ No newline at end of file
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java Mon Mar 9 12:21:49 2015
@@ -81,6 +81,15 @@ public abstract class AstVisitorBase imp
node.getPathExpression().accept(this);
return true;
}
+
+ /**
+ * Calls accept on the static operand in the spellcheck search constraint.
+ */
+ @Override
+ public boolean visit(SpellcheckImpl node) {
+ node.getExpression().accept(this);
+ return true;
+ }
/**
* Calls accept on the two sources and the join condition in the join node.
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java Mon Mar 9 12:21:49 2015
@@ -620,6 +620,8 @@ public class SelectorImpl extends Source
result = currentRow.getValue(QueryImpl.JCR_SCORE);
} else if (oakPropertyName.equals(QueryImpl.REP_EXCERPT)) {
result = currentRow.getValue(QueryImpl.REP_EXCERPT);
+ } else if (oakPropertyName.equals(QueryImpl.REP_SPELLCHECK)) {
+ result = currentRow.getValue(QueryImpl.REP_SPELLCHECK);
} else {
result = PropertyValues.create(t.getProperty(oakPropertyName));
}
Copied: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java (from r1656019, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java?p2=jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java&p1=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java&r1=1656019&r2=1665206&rev=1665206&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java Mon Mar 9 12:21:49 2015
@@ -19,6 +19,7 @@
package org.apache.jackrabbit.oak.query.ast;
import java.util.Collections;
+import java.util.Map;
import java.util.Set;
import org.apache.jackrabbit.oak.api.PropertyValue;
@@ -28,7 +29,7 @@ import org.apache.jackrabbit.oak.spi.que
import org.apache.jackrabbit.oak.spi.query.QueryIndex.FulltextQueryIndex;
/**
- * Support for "similar(...)
+ * Support for "spellcheck(...)
*/
public class SpellcheckImpl extends ConstraintImpl {
@@ -74,6 +75,11 @@ public class SpellcheckImpl extends Cons
}
@Override
+ public Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap() {
+ return Collections.emptyMap();
+ }
+
+ @Override
public void restrict(FilterImpl f) {
if (f.getSelector().equals(selector)) {
PropertyValue p = expression.currentValue();
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java Mon Mar 9 12:21:49 2015
@@ -544,7 +544,38 @@ abstract class Expression {
return false;
}
- }
+ }
+
+ /**
+ * A rep:spellcheck condition.
+ */
+ static class Spellcheck extends Expression {
+
+ final Expression term;
+
+ Spellcheck(Expression term) {
+ this.term = term;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buff = new StringBuilder("spellcheck(");
+ buff.append(term);
+ buff.append(')');
+ return buff.toString();
+ }
+
+ @Override
+ boolean isCondition() {
+ return true;
+ }
+
+ @Override
+ boolean isName() {
+ return false;
+ }
+
+ }
/**
* A function call.
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java Mon Mar 9 12:21:49 2015
@@ -209,6 +209,12 @@ public class XPathToSQL2Converter {
readExcerpt();
Expression.Property p = new Expression.Property(currentSelector, "rep:excerpt", false);
statement.addSelectColumn(p);
+ } else if (readIf("rep:spellcheck")) {
+ // only rep:spellcheck() is currently supported
+ read("(");
+ read(")");
+ Expression.Property p = new Expression.Property(currentSelector, "rep:spellcheck()", false);
+ statement.addSelectColumn(p);
}
} while (readIf("|"));
read(")");
@@ -622,12 +628,12 @@ public class XPathToSQL2Converter {
Expression.Similar f = new Expression.Similar(property, path);
return f;
} else if ("rep:spellcheck".equals(functionName)) {
- // TODO maybe support rep:spellcheck as in
- // /jcr:root[rep:spellcheck('${query}')]/(rep:spellcheck())
- throw getSyntaxError("rep:spellcheck is not supported");
+ Expression term = parseExpression();
+ read(")");
+ return new Expression.Spellcheck(term);
} else {
throw getSyntaxError("jcr:like | jcr:contains | jcr:score | xs:dateTime | " +
- "fn:lower-case | fn:upper-case | fn:name");
+ "fn:lower-case | fn:upper-case | fn:name | rep:similar | rep:spellcheck");
}
}
Modified: jackrabbit/oak/branches/1.0/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql1.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql1.txt?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql1.txt (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql1.txt Mon Mar 9 12:21:49 2015
@@ -26,6 +26,12 @@
# sql-1 query (nt:unstructured needs to be escaped in sql-2)
+sql1 SELECT [rep:spellcheck()] FROM nt:base WHERE [jcr:path] = '/' AND SPELLCHECK('jackrabit')
+java.lang.IllegalArgumentException: No full-text index was found that can process the condition spellcheck([nt:base], 'jackrabit')
+
+sql1 SELECT rep:spellcheck() FROM nt:base WHERE jcr:path = '/' AND SPELLCHECK('jackrabit')
+java.lang.IllegalArgumentException: No full-text index was found that can process the condition spellcheck([nt:base], 'jackrabit')
+
sql1 select prop1 from nt:unstructured where prop1 is not null order by prop1 asc
sql1 select excerpt(.) from nt:resource where contains(., 'jackrabbit')
Modified: jackrabbit/oak/branches/1.0/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt Mon Mar 9 12:21:49 2015
@@ -1353,7 +1353,7 @@ xpath2sql //element(*, my:type)[@my:valu
invalid: Query: //element(*, my:type)[@my:value = [(*)'x']; expected: @, true, false, -, +, *, ., @, (
xpath2sql //element(*, my:type)[jcr:strike(@title,'%Java%')]
-invalid: Query: //element(*, my:type)[jcr:strike(@(*)title,'%Java%')]; expected: jcr:like | jcr:contains | jcr:score | xs:dateTime | fn:lower-case | fn:upper-case | fn:name
+invalid: Query: //element(*, my:type)[jcr:strike(@(*)title,'%Java%')]; expected: jcr:like | jcr:contains | jcr:score | xs:dateTime | fn:lower-case | fn:upper-case | fn:name | rep:similar | rep:spellcheck
xpath2sql //element(*, my:type)[
invalid: Query: //element(*, my:type)(*)[; expected: fn:not, not, (, @, true, false, -, +, *, ., @, (
Modified: jackrabbit/oak/branches/1.0/oak-lucene/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-lucene/pom.xml?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-lucene/pom.xml (original)
+++ jackrabbit/oak/branches/1.0/oak-lucene/pom.xml Mon Mar 9 12:21:49 2015
@@ -198,6 +198,12 @@
<version>${lucene.version}</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.lucene</groupId>
+ <artifactId>lucene-suggest</artifactId>
+ <version>${lucene.version}</version>
+ <scope>provided</scope>
+ </dependency>
<!-- Logging -->
<dependency>
Modified: jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java (original)
+++ jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java Mon Mar 9 12:21:49 2015
@@ -58,6 +58,7 @@ import org.apache.jackrabbit.oak.api.Pro
import org.apache.jackrabbit.oak.plugins.index.aggregate.NodeAggregator;
import org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition.IndexingRule;
import org.apache.jackrabbit.oak.plugins.index.lucene.util.MoreLikeThisHelper;
+import org.apache.jackrabbit.oak.plugins.index.lucene.util.SpellcheckHelper;
import org.apache.jackrabbit.oak.query.QueryEngineSettings;
import org.apache.jackrabbit.oak.query.QueryImpl;
import org.apache.jackrabbit.oak.query.fulltext.FullTextAnd;
@@ -99,6 +100,7 @@ import org.apache.lucene.search.TermQuer
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.WildcardQuery;
+import org.apache.lucene.search.spell.SuggestWord;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.automaton.Automaton;
import org.apache.lucene.util.automaton.CompiledAutomaton;
@@ -242,7 +244,7 @@ public class LuceneIndex implements Adva
// we only restrict non-full-text conditions if there is
// no relative property in the full-text constraint
boolean nonFullTextConstraints = parent.isEmpty();
- String planDesc = getQuery(filter, null, nonFullTextConstraints, index.getDefinition()) + " ft:(" + ft + ")";
+ String planDesc = getLuceneRequest(filter, null, nonFullTextConstraints, index.getDefinition()) + " ft:(" + ft + ")";
if (!parent.isEmpty()) {
planDesc += " parent:" + parent;
}
@@ -277,6 +279,7 @@ public class LuceneIndex implements Adva
private final Set<String> seenPaths = Sets.newHashSet();
private ScoreDoc lastDoc;
private int nextBatchSize = LUCENE_QUERY_BATCH_SIZE;
+ private boolean noDocs = false;
@Override
protected LuceneResultRow computeNext() {
@@ -321,33 +324,49 @@ public class LuceneIndex implements Adva
* @return true if any document is loaded
*/
private boolean loadDocs() {
+
+ if (noDocs) {
+ return false;
+ }
+
ScoreDoc lastDocToRecord = null;
IndexNode indexNode = tracker.acquireIndexNode((String) plan.getAttribute(ATTR_INDEX_PATH));
checkState(indexNode != null);
try {
IndexSearcher searcher = indexNode.getSearcher();
- Query query = getQuery(filter, searcher.getIndexReader(),
+ LuceneRequestFacade luceneRequestFacade = getLuceneRequest(filter, searcher.getIndexReader(),
nonFullTextConstraints, indexNode.getDefinition());
- TopDocs docs;
- long time = System.currentTimeMillis();
- if (lastDoc != null) {
- LOG.debug("loading the next {} entries for query {}", nextBatchSize, query);
- docs = searcher.searchAfter(lastDoc, query, nextBatchSize);
- } else {
- LOG.debug("loading the first {} entries for query {}", nextBatchSize, query);
- docs = searcher.search(query, nextBatchSize);
- }
- time = System.currentTimeMillis() - time;
- LOG.debug("... took {} ms", time);
- nextBatchSize = (int) Math.min(nextBatchSize * 2L, 100000);
-
- for (ScoreDoc doc : docs.scoreDocs) {
- LuceneResultRow row = convertToRow(doc, searcher);
- if(row != null) {
- queue.add(row);
+ if (luceneRequestFacade.getLuceneRequest() instanceof Query) {
+ Query query = (Query) luceneRequestFacade.getLuceneRequest();
+ TopDocs docs;
+ long time = System.currentTimeMillis();
+ if (lastDoc != null) {
+ LOG.debug("loading the next {} entries for query {}", nextBatchSize, query);
+ docs = searcher.searchAfter(lastDoc, query, nextBatchSize);
+ } else {
+ LOG.debug("loading the first {} entries for query {}", nextBatchSize, query);
+ docs = searcher.search(query, nextBatchSize);
}
- lastDocToRecord = doc;
+ time = System.currentTimeMillis() - time;
+ LOG.debug("... took {} ms", time);
+ nextBatchSize = (int) Math.min(nextBatchSize * 2L, 100000);
+
+ for (ScoreDoc doc : docs.scoreDocs) {
+ LuceneResultRow row = convertToRow(doc, searcher);
+ if (row != null) {
+ queue.add(row);
+ }
+ lastDocToRecord = doc;
+ }
+ } else if (luceneRequestFacade.getLuceneRequest() instanceof SuggestWord[]) {
+ SuggestWord[] intent = (SuggestWord[]) luceneRequestFacade.getLuceneRequest();
+ Collection<String> suggestedWords = new ArrayList<String>(intent.length);
+ for (SuggestWord suggestWord : intent) {
+ suggestedWords.add(suggestWord.string);
+ }
+ queue.add(new LuceneResultRow(suggestedWords));
+ noDocs = true;
}
} catch (IOException e) {
LOG.warn("query via {} failed.", LuceneIndex.this, e);
@@ -430,12 +449,11 @@ public class LuceneIndex implements Adva
* @param nonFullTextConstraints whether non-full-text constraints (such a
* path, node type, and so on) should be added to the Lucene
* query
- * @param analyzer the Lucene analyzer used for building the fulltext query
* @param indexDefinition nodestate that contains the index definition
* @return the Lucene query
*/
- private static Query getQuery(Filter filter, IndexReader reader,
- boolean nonFullTextConstraints, IndexDefinition indexDefinition) {
+ private static LuceneRequestFacade getLuceneRequest(Filter filter, IndexReader reader,
+ boolean nonFullTextConstraints, IndexDefinition indexDefinition) {
List<Query> qs = new ArrayList<Query>();
Analyzer analyzer = indexDefinition.getAnalyzer();
FullTextExpression ft = filter.getFullTextConstraint();
@@ -459,6 +477,12 @@ public class LuceneIndex implements Adva
}
}
}
+ if (query.startsWith("spellcheck?")) {
+ String spellcheckQueryString = query.replace("spellcheck?", "");
+ if (reader != null) {
+ return new LuceneRequestFacade<SuggestWord[]>(SpellcheckHelper.getSpellcheck(spellcheckQueryString, reader));
+ }
+ }
else {
try {
qs.add(queryParser.parse(query));
@@ -471,16 +495,16 @@ public class LuceneIndex implements Adva
indexDefinition);
}
if (qs.size() == 0) {
- return new MatchAllDocsQuery();
+ return new LuceneRequestFacade<Query>(new MatchAllDocsQuery());
}
if (qs.size() == 1) {
- return qs.get(0);
+ return new LuceneRequestFacade<Query>(qs.get(0));
}
BooleanQuery bq = new BooleanQuery();
for (Query q : qs) {
bq.add(q, MUST);
}
- return bq;
+ return new LuceneRequestFacade<Query>(bq);
}
private static void addNonFullTextConstraints(List<Query> qs,
@@ -739,19 +763,22 @@ public class LuceneIndex implements Adva
@Override
public boolean visit(FullTextTerm term) {
- String p = term.getPropertyName();
+ return visitTerm(term.getPropertyName(), term.getText(), term.getBoost(), term.isNot());
+ }
+
+ private boolean visitTerm(String propertyName, String text, String boost, boolean not) {
+ String p = propertyName;
if (p != null && p.indexOf('/') >= 0) {
p = getName(p);
}
- Query q = tokenToQuery(term.getText(), p, analyzer, reader);
+ Query q = tokenToQuery(text, p, analyzer, reader);
if (q == null) {
return false;
}
- String boost = term.getBoost();
if (boost != null) {
q.setBoost(Float.parseFloat(boost));
}
- if (term.isNot()) {
+ if (not) {
BooleanQuery bq = new BooleanQuery();
bq.add(q, MUST_NOT);
result.set(bq);
@@ -938,10 +965,18 @@ public class LuceneIndex implements Adva
static class LuceneResultRow {
final String path;
final double score;
+ final Iterable<String> suggestWords;
LuceneResultRow(String path, double score) {
this.path = path;
this.score = score;
+ this.suggestWords = Collections.emptySet();
+ }
+
+ LuceneResultRow(Iterable<String> suggestWords) {
+ this.path = "/";
+ this.score = 1.0d;
+ this.suggestWords = suggestWords;
}
@Override
@@ -949,16 +984,16 @@ public class LuceneIndex implements Adva
return String.format("%s (%1.2f)", path, score);
}
}
-
+
/**
* A cursor over Lucene results. The result includes the path,
* and the jcr:score pseudo-property as returned by Lucene.
*/
static class LucenePathCursor implements Cursor {
-
+
private final Cursor pathCursor;
LuceneResultRow currentRow;
-
+
LucenePathCursor(final Iterator<LuceneResultRow> it, QueryEngineSettings settings) {
Iterator<String> pathIterator = new Iterator<String>() {
@@ -969,7 +1004,7 @@ public class LuceneIndex implements Adva
@Override
public String next() {
- currentRow = it.next();
+ currentRow = it.next();
return currentRow.path;
}
@@ -977,11 +1012,11 @@ public class LuceneIndex implements Adva
public void remove() {
it.remove();
}
-
+
};
pathCursor = new PathCursor(pathIterator, true, settings);
}
-
+
@Override
public boolean hasNext() {
@@ -1009,9 +1044,12 @@ public class LuceneIndex implements Adva
if (QueryImpl.JCR_SCORE.equals(columnName)) {
return PropertyValues.newDouble(currentRow.score);
}
+ if (QueryImpl.REP_SPELLCHECK.equals(columnName)) {
+ return PropertyValues.newString(currentRow.suggestWords);
+ }
return pathRow.getValue(columnName);
}
-
+
};
}
}
Modified: jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java (original)
+++ jackrabbit/oak/branches/1.0/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java Mon Mar 9 12:21:49 2015
@@ -21,7 +21,9 @@ package org.apache.jackrabbit.oak.plugin
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
@@ -42,6 +44,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition.IndexingRule;
import org.apache.jackrabbit.oak.plugins.index.lucene.IndexPlanner.PlanResult;
import org.apache.jackrabbit.oak.plugins.index.lucene.util.MoreLikeThisHelper;
+import org.apache.jackrabbit.oak.plugins.index.lucene.util.SpellcheckHelper;
import org.apache.jackrabbit.oak.query.QueryEngineSettings;
import org.apache.jackrabbit.oak.query.QueryImpl;
import org.apache.jackrabbit.oak.query.fulltext.FullTextAnd;
@@ -87,6 +90,7 @@ import org.apache.lucene.search.TermQuer
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.WildcardQuery;
+import org.apache.lucene.search.spell.SuggestWord;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.automaton.Automaton;
import org.apache.lucene.util.automaton.CompiledAutomaton;
@@ -224,7 +228,7 @@ public class LucenePropertyIndex impleme
.append("(")
.append(path)
.append(") ");
- sb.append(getQuery(plan, null));
+ sb.append(getLuceneRequest(plan, null));
if(plan.getSortOrder() != null && !plan.getSortOrder().isEmpty()){
sb.append(" ordering:").append(plan.getSortOrder());
}
@@ -253,6 +257,7 @@ public class LucenePropertyIndex impleme
private final Set<String> seenPaths = Sets.newHashSet();
private ScoreDoc lastDoc;
private int nextBatchSize = LUCENE_QUERY_BATCH_SIZE;
+ private boolean noDocs = false;
@Override
protected LuceneResultRow computeNext() {
@@ -292,40 +297,56 @@ public class LucenePropertyIndex impleme
* @return true if any document is loaded
*/
private boolean loadDocs() {
+
+ if (noDocs) {
+ return false;
+ }
+
ScoreDoc lastDocToRecord = null;
IndexNode indexNode = acquireIndexNode(plan);
checkState(indexNode != null);
try {
IndexSearcher searcher = indexNode.getSearcher();
- Query query = getQuery(plan, searcher.getIndexReader());
- TopDocs docs;
- long time = System.currentTimeMillis();
- if (lastDoc != null) {
- LOG.debug("loading the next {} entries for query {}", nextBatchSize, query);
- if (sort == null) {
- docs = searcher.searchAfter(lastDoc, query, nextBatchSize);
+ LuceneRequestFacade luceneRequestFacade = getLuceneRequest(plan, searcher.getIndexReader());
+ if (luceneRequestFacade.getLuceneRequest() instanceof Query) {
+ Query query = (Query) luceneRequestFacade.getLuceneRequest();
+ TopDocs docs;
+ long time = System.currentTimeMillis();
+ if (lastDoc != null) {
+ LOG.debug("loading the next {} entries for query {}", nextBatchSize, query);
+ if (sort == null) {
+ docs = searcher.searchAfter(lastDoc, query, nextBatchSize);
+ } else {
+ docs = searcher.searchAfter(lastDoc, query, LUCENE_QUERY_BATCH_SIZE, sort);
+ }
} else {
- docs = searcher.searchAfter(lastDoc, query, LUCENE_QUERY_BATCH_SIZE, sort);
+ LOG.debug("loading the first {} entries for query {}", nextBatchSize, query);
+ if (sort == null) {
+ docs = searcher.search(query, nextBatchSize);
+ } else {
+ docs = searcher.search(query, LUCENE_QUERY_BATCH_SIZE, sort);
+ }
}
- } else {
- LOG.debug("loading the first {} entries for query {}", nextBatchSize, query);
- if (sort == null) {
- docs = searcher.search(query, nextBatchSize);
- } else {
- docs = searcher.search(query, LUCENE_QUERY_BATCH_SIZE, sort);
+ time = System.currentTimeMillis() - time;
+ LOG.debug("... took {} ms", time);
+ nextBatchSize = (int) Math.min(nextBatchSize * 2L, 100000);
+
+ for (ScoreDoc doc : docs.scoreDocs) {
+ LuceneResultRow row = convertToRow(doc, searcher);
+ if (row != null) {
+ queue.add(row);
+ }
+ lastDocToRecord = doc;
}
- }
- time = System.currentTimeMillis() - time;
- LOG.debug("... took {} ms", time);
- nextBatchSize = (int) Math.min(nextBatchSize * 2L, 100000);
-
- for (ScoreDoc doc : docs.scoreDocs) {
- LuceneResultRow row = convertToRow(doc, searcher);
- if(row != null) {
- queue.add(row);
+ } else if (luceneRequestFacade.getLuceneRequest() instanceof SuggestWord[]) {
+ SuggestWord[] suggestWords = (SuggestWord[]) luceneRequestFacade.getLuceneRequest();
+ String[] suggestedWordsStrings = new String[suggestWords.length];
+ for (int i = 0; i < suggestWords.length; i++) {
+ suggestedWordsStrings[i] = suggestWords[i].string;
}
- lastDocToRecord = doc;
+ queue.add(new LuceneResultRow(suggestedWordsStrings));
+ noDocs = true;
}
} catch (IOException e) {
LOG.warn("query via {} failed.", LucenePropertyIndex.this, e);
@@ -426,14 +447,9 @@ public class LucenePropertyIndex impleme
*
* @param plan index plan containing filter details
* @param reader the Lucene reader
- * @param nonFullTextConstraints whether non-full-text constraints (such a
- * path, node type, and so on) should be added to the Lucene
- * query
- * @param analyzer the Lucene analyzer used for building the fulltext query
- * @param defn nodestate that contains the index definition
* @return the Lucene query
*/
- private static Query getQuery(IndexPlan plan, IndexReader reader) {
+ private static LuceneRequestFacade getLuceneRequest(IndexPlan plan, IndexReader reader) {
List<Query> qs = new ArrayList<Query>();
Filter filter = plan.getFilter();
FullTextExpression ft = filter.getFullTextConstraint();
@@ -466,6 +482,11 @@ public class LucenePropertyIndex impleme
qs.add(moreLikeThis);
}
}
+ } else if (query.startsWith("spellcheck?")) {
+ String spellcheckQueryString = query.replace("spellcheck?", "");
+ if (reader != null) {
+ return new LuceneRequestFacade<SuggestWord[]>(SpellcheckHelper.getSpellcheck(spellcheckQueryString, reader));
+ }
}
else {
try {
@@ -503,24 +524,18 @@ public class LucenePropertyIndex impleme
//When called in planning mode then some queries like rep:similar
//cannot create query as reader is not provided. In such case we
//just return match all queries
- return new MatchAllDocsQuery();
- }
- //For purely nodeType based queries all the documents would have to
- //be returned (if the index definition has a single rule)
- if (planResult.evaluateNodeTypeRestriction()) {
- return new MatchAllDocsQuery();
+ return new LuceneRequestFacade<Query>(new MatchAllDocsQuery());
}
-
- throw new IllegalStateException("No query created for filter " + filter);
+ return new LuceneRequestFacade<Query>(new MatchAllDocsQuery());
}
if (qs.size() == 1) {
- return qs.get(0);
+ return new LuceneRequestFacade<Query>(qs.get(0));
}
BooleanQuery bq = new BooleanQuery();
for (Query q : qs) {
bq.add(q, MUST);
}
- return bq;
+ return new LuceneRequestFacade<Query>(bq);
}
private static void addNonFullTextConstraints(List<Query> qs,
@@ -1107,10 +1122,18 @@ public class LucenePropertyIndex impleme
static class LuceneResultRow {
final String path;
final double score;
+ final String[] suggestWords;
LuceneResultRow(String path, double score) {
this.path = path;
this.score = score;
+ this.suggestWords = new String[0];
+ }
+
+ LuceneResultRow(String[] suggestWords) {
+ this.path = "/";
+ this.score = 1.0d;
+ this.suggestWords = suggestWords;
}
@Override
@@ -1185,6 +1208,9 @@ public class LucenePropertyIndex impleme
if (QueryImpl.JCR_SCORE.equals(columnName)) {
return PropertyValues.newDouble(currentRow.score);
}
+ if (QueryImpl.REP_SPELLCHECK.equals(columnName)) {
+ return PropertyValues.newString(Arrays.toString(currentRow.suggestWords));
+ }
return pathRow.getValue(columnName);
}
Modified: jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/AdvancedSolrQueryIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/AdvancedSolrQueryIndex.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/AdvancedSolrQueryIndex.java (original)
+++ jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/AdvancedSolrQueryIndex.java Mon Mar 9 12:21:49 2015
@@ -101,7 +101,7 @@ public class AdvancedSolrQueryIndex exte
}
@Override
- void onRetrievedResults(Filter filter, SolrDocumentList docs) {
+ void onRetrievedDocs(Filter filter, SolrDocumentList docs) {
// update estimates cache
cache.put(filter.toString(), docs.getNumFound());
}
Modified: jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParser.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParser.java (original)
+++ jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParser.java Mon Mar 9 12:21:49 2015
@@ -78,26 +78,38 @@ class FilterQueryParser {
if (kv.length != 2) {
throw new RuntimeException("Unparsable native HTTP Solr query");
} else {
- if ("stream.body".equals(kv[0])) {
- kv[0] = "q";
- String mltFlString = "mlt.fl=";
- int mltFlIndex = parameterString.indexOf(mltFlString);
- if (mltFlIndex > -1) {
- int beginIndex = mltFlIndex + mltFlString.length();
- int endIndex = parameterString.indexOf('&', beginIndex);
- String fields;
- if (endIndex > beginIndex) {
- fields = parameterString.substring(beginIndex, endIndex);
- } else {
- fields = parameterString.substring(beginIndex);
+ // more like this
+ if ("/mlt".equals(requestHandlerString)) {
+ if ("stream.body".equals(kv[0])) {
+ kv[0] = "q";
+ String mltFlString = "mlt.fl=";
+ int mltFlIndex = parameterString.indexOf(mltFlString);
+ if (mltFlIndex > -1) {
+ int beginIndex = mltFlIndex + mltFlString.length();
+ int endIndex = parameterString.indexOf('&', beginIndex);
+ String fields;
+ if (endIndex > beginIndex) {
+ fields = parameterString.substring(beginIndex, endIndex);
+ } 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] + "\"";
+ }
+ if ("mlt.fl".equals(kv[0]) && ":path".equals(kv[1])) {
+ // rep:similar passes the path of the node to find similar documents for in the :path
+ // but needs its indexed content to find similar documents
+ kv[1] = configuration.getCatchAllField();
}
}
- if ("mlt.fl".equals(kv[0]) && ":path".equals(kv[1])) {
- // rep:similar passes the path of the node to find similar documents for in the :path
- // but needs its indexed content to find similar documents
- kv[1] = configuration.getCatchAllField();
+ if ("/spellcheck".equals(requestHandlerString)) {
+ if ("term".equals(kv[0])) {
+ kv[0] = "spellcheck.q";
+ }
+ solrQuery.setParam("spellcheck", true);
+
+ // TODO : this should not be always passed to avoid building the dictionary on each spellcheck request
+ solrQuery.setParam("spellcheck.build", true);
}
solrQuery.setParam(kv[0], kv[1]);
}
@@ -285,7 +297,7 @@ class FilterQueryParser {
private static boolean isSupportedHttpRequest(String nativeQueryString) {
// the query string starts with ${supported-handler.selector}?
- return nativeQueryString.matches("(mlt|query|select|get)\\\\?.*");
+ return nativeQueryString.matches("(spellcheck|mlt|query|select|get)\\\\?.*");
}
private static void setDefaults(SolrQuery solrQuery, OakSolrConfiguration configuration) {
Modified: jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java (original)
+++ jackrabbit/oak/branches/1.0/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java Mon Mar 9 12:21:49 2015
@@ -47,6 +47,8 @@ import org.apache.jackrabbit.oak.spi.que
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.client.solrj.response.SpellCheckResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.slf4j.Logger;
@@ -193,15 +195,17 @@ public class SolrQueryIndex implements F
final int parentDepth = getDepth(parent);
cursor = new SolrRowCursor(new AbstractIterator<SolrResultRow>() {
+
private final Set<String> seenPaths = Sets.newHashSet();
private final Deque<SolrResultRow> queue = Queues.newArrayDeque();
private SolrDocument lastDoc;
private int offset = 0;
+ private boolean noDocs = false;
public long numFound = 0;
@Override
protected SolrResultRow computeNext() {
- while (!queue.isEmpty() || loadDocs()) {
+ if (!queue.isEmpty() || loadDocs()) {
return queue.remove();
}
return endOfData();
@@ -238,6 +242,12 @@ public class SolrQueryIndex implements F
*/
private boolean loadDocs() {
+ if (noDocs) {
+ return false;
+ }
+
+ SolrDocument lastDocToRecord = null;
+
try {
if (log.isDebugEnabled()) {
log.debug("converting filter {}", filter);
@@ -254,9 +264,11 @@ public class SolrQueryIndex implements F
if (log.isDebugEnabled()) {
log.debug("sending query {}", query);
}
- SolrDocumentList docs = solrServer.query(query).getResults();
+ QueryResponse queryResponse = solrServer.query(query);
+
+ SolrDocumentList docs = queryResponse.getResults();
- onRetrievedResults(filter, docs);
+ onRetrievedDocs(filter, docs);
if (log.isDebugEnabled()) {
log.debug("getting docs {}", docs);
@@ -273,6 +285,19 @@ public class SolrQueryIndex implements F
}
}
}
+
+ // handle spellcheck
+ SpellCheckResponse spellCheckResponse = queryResponse.getSpellCheckResponse();
+ if (spellCheckResponse != null && spellCheckResponse.getSuggestions() != null &&
+ spellCheckResponse.getSuggestions().size() > 0) {
+ SolrDocument fakeDoc = new SolrDocument();
+ for (SpellCheckResponse.Suggestion suggestion : spellCheckResponse.getSuggestions()) {
+ fakeDoc.addField("rep:spellcheck()", suggestion.getAlternatives());
+ }
+ queue.add(new SolrResultRow("/", 1.0, fakeDoc));
+ noDocs = true;
+ }
+
} catch (Exception e) {
if (log.isWarnEnabled()) {
log.warn("query via {} failed.", solrServer, e);
@@ -289,7 +314,7 @@ public class SolrQueryIndex implements F
return cursor;
}
- void onRetrievedResults(Filter filter, SolrDocumentList docs) {
+ void onRetrievedDocs(Filter filter, SolrDocumentList docs) {
// do nothing
}
@@ -308,11 +333,12 @@ public class SolrQueryIndex implements F
}
static boolean isIgnoredProperty(String propertyName, OakSolrConfiguration configuration) {
- return !configuration.useForPropertyRestrictions() // Solr index not used for properties
- || (configuration.getUsedProperties().size() > 0 && !configuration.getUsedProperties().contains(propertyName)) // not explicitly contained in the used properties
- || propertyName.contains("/") // no child-level property restrictions
- || "rep:excerpt".equals(propertyName) // rep:excerpt is handled by the query engine
- || configuration.getIgnoredProperties().contains(propertyName); // property is explicitly ignored
+ return !(NATIVE_LUCENE_QUERY.equals(propertyName) || NATIVE_SOLR_QUERY.equals(propertyName)) &&
+ (!configuration.useForPropertyRestrictions() // Solr index not used for properties
+ || (configuration.getUsedProperties().size() > 0 && !configuration.getUsedProperties().contains(propertyName)) // not explicitly contained in the used properties
+ || propertyName.contains("/") // no child-level property restrictions
+ || "rep:excerpt".equals(propertyName) // rep:excerpt is handled by the query engine
+ || configuration.getIgnoredProperties().contains(propertyName));
}
static class SolrResultRow {
Modified: jackrabbit/oak/branches/1.0/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml (original)
+++ jackrabbit/oak/branches/1.0/oak-solr-core/src/main/resources/solr/oak/conf/schema.xml Mon Mar 9 12:21:49 2015
@@ -71,6 +71,13 @@
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
+ <fieldType name="textSpell" class="solr.TextField" positionIncrementGap="100" >
+ <analyzer>
+ <tokenizer class="solr.StandardTokenizerFactory"/>
+ <filter class="solr.LowerCaseFilterFactory"/>
+ <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
+ </analyzer>
+ </fieldType>
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
@@ -108,38 +115,16 @@
<field name=":path" type="string" indexed="true" stored="false" />
<field name="_version_" type="long" indexed="true" stored="true"/>
- <dynamicField name="*_i" type="int" indexed="true" stored="true"/>
- <dynamicField name="*_is" type="int" indexed="true" stored="true" multiValued="true"/>
- <dynamicField name="*_s" type="string" indexed="true" stored="true" />
- <dynamicField name="*_ss" type="string" indexed="true" stored="true" multiValued="true"/>
- <dynamicField name="*_l" type="long" indexed="true" stored="true"/>
- <dynamicField name="*_ls" type="long" indexed="true" stored="true" multiValued="true"/>
- <dynamicField name="*_t" type="text_general" indexed="true" stored="true"/>
- <dynamicField name="*_txt" type="text_general" indexed="true" stored="true" multiValued="true"/>
- <dynamicField name="*_b" type="boolean" indexed="true" stored="true"/>
- <dynamicField name="*_bs" type="boolean" indexed="true" stored="true" multiValued="true"/>
- <dynamicField name="*_f" type="float" indexed="true" stored="true"/>
- <dynamicField name="*_fs" type="float" indexed="true" stored="true" multiValued="true"/>
- <dynamicField name="*_d" type="double" indexed="true" stored="true"/>
- <dynamicField name="*_ds" type="double" indexed="true" stored="true" multiValued="true"/>
-
- <dynamicField name="*_dt" type="date" indexed="true" stored="true"/>
- <dynamicField name="*_dts" type="date" indexed="true" stored="true" multiValued="true"/>
-
- <dynamicField name="*_ti" type="tint" indexed="true" stored="true"/>
- <dynamicField name="*_tl" type="tlong" indexed="true" stored="true"/>
- <dynamicField name="*_tf" type="tfloat" indexed="true" stored="true"/>
- <dynamicField name="*_td" type="tdouble" indexed="true" stored="true"/>
- <dynamicField name="*_tdt" type="tdate" indexed="true" stored="true"/>
-
- <dynamicField name="*_pi" type="pint" indexed="true" stored="true"/>
- <dynamicField name="*_c" type="currency" indexed="true" stored="true"/>
- <dynamicField name="*" type="text_general" indexed="true" stored="true" multiValued="true"/>
- </fields>
- <uniqueKey>path_exact</uniqueKey>
- <copyField source="path_exact" dest="path_anc"/>
- <copyField source="path_exact" dest="path_des"/>
- <copyField source="path_exact" dest="path_child"/>
+ <field name="rep:members" type="string" indexed="true" stored="true" multiValued="true"/>
+ <field name="rep:principalName" type="string" indexed="true" stored="true" multiValued="true"/>
+ <field name=":indexed" type="tdate" indexed="true" stored="false" default="NOW" docValues="numeric"/>
+ <dynamicField name="*_bin" type="string" indexed="true" stored="true" multiValued="true"/>
+ <dynamicField name="*" type="text_general" indexed="true" stored="true" multiValued="true"/>
+ </fields>
+ <uniqueKey>path_exact</uniqueKey>
+ <copyField source="path_exact" dest="path_anc"/>
+ <copyField source="path_exact" dest="path_des"/>
+ <copyField source="path_exact" dest="path_child"/>
<copyField source="path_exact" dest=":path"/>
<copyField source="*" dest="catch_all"/>
</schema>
Modified: jackrabbit/oak/branches/1.0/oak-solr-core/src/main/resources/solr/oak/conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-solr-core/src/main/resources/solr/oak/conf/solrconfig.xml?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-solr-core/src/main/resources/solr/oak/conf/solrconfig.xml (original)
+++ jackrabbit/oak/branches/1.0/oak-solr-core/src/main/resources/solr/oak/conf/solrconfig.xml Mon Mar 9 12:21:49 2015
@@ -866,6 +866,10 @@
<str>nameOfCustomComponent2</str>
</arr>
-->
+ <arr name="last-components">
+ <str>mlt</str>
+ <str>spellcheck</str>
+ </arr>
</requestHandler>
<!-- A request handler that returns indented JSON by default -->
@@ -1163,6 +1167,65 @@
-->
+ <searchComponent name="spellcheck" class="solr.SpellCheckComponent">
+
+ <str name="queryAnalyzerFieldType">text_general</str>
+
+ <!-- Multiple "Spell Checkers" can be declared and used by this
+ component
+ -->
+
+ <!-- a spellchecker built from a field of the main index -->
+ <lst name="spellchecker">
+ <str name="name">default</str>
+ <str name="field">catch_all</str>
+ <str name="classname">solr.DirectSolrSpellChecker</str>
+ <str name="distanceMeasure">internal</str>
+ <!-- minimum accuracy needed to be considered a valid spellcheck suggestion -->
+ <float name="accuracy">0.5</float>
+ <!-- the maximum #edits we consider when enumerating terms: can be 1 or 2 -->
+ <int name="maxEdits">2</int>
+ <!-- the minimum shared prefix when enumerating terms -->
+ <int name="minPrefix">1</int>
+ <!-- maximum number of inspections per result. -->
+ <int name="maxInspections">5</int>
+ <!-- minimum length of a query term to be considered for correction -->
+ <int name="minQueryLength">4</int>
+ <!-- maximum threshold of documents a query term can appear to be considered for correction -->
+ <float name="maxQueryFrequency">0.01</float>
+ </lst>
+
+ <lst name="spellchecker">
+ <str name="name">wordbreak</str>
+ <str name="classname">solr.WordBreakSolrSpellChecker</str>
+ <str name="field">name</str>
+ <str name="combineWords">true</str>
+ <str name="breakWords">true</str>
+ <int name="maxChanges">10</int>
+ </lst>
+
+ </searchComponent>
+
+ <requestHandler name="/spellcheck" class="solr.SearchHandler" startup="lazy">
+ <lst name="defaults">
+ <str name="df">catch_all</str>
+ <str name="spellcheck.dictionary">default</str>
+ <str name="spellcheck.dictionary">wordbreak</str>
+ <str name="spellcheck">on</str>
+ <str name="spellcheck.extendedResults">true</str>
+ <str name="spellcheck.count">10</str>
+ <str name="spellcheck.alternativeTermCount">5</str>
+ <str name="spellcheck.maxResultsForSuggest">5</str>
+ <str name="spellcheck.collate">true</str>
+ <str name="spellcheck.collateExtendedResults">true</str>
+ <str name="spellcheck.maxCollationTries">10</str>
+ <str name="spellcheck.maxCollations">5</str>
+ </lst>
+ <arr name="last-components">
+ <str>spellcheck</str>
+ </arr>
+ </requestHandler>
+
<!-- Update Processors
Chains of Update Processor Factories for dealing with Update
Modified: jackrabbit/oak/branches/1.0/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTestIT.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTestIT.java?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTestIT.java (original)
+++ jackrabbit/oak/branches/1.0/oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrIndexQueryTestIT.java Mon Mar 9 12:21:49 2015
@@ -88,6 +88,11 @@ public class SolrIndexQueryTestIT extend
}
@Test
+ public void sql1() throws Exception {
+ test("sql1.txt");
+ }
+
+ @Test
public void sql2() throws Exception {
test("sql2.txt");
}
Modified: jackrabbit/oak/branches/1.0/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml (original)
+++ jackrabbit/oak/branches/1.0/oak-solr-core/src/test/resources/solr/oak/conf/schema.xml Mon Mar 9 12:21:49 2015
@@ -70,6 +70,13 @@
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
+ <fieldType name="textSpell" class="solr.TextField" positionIncrementGap="100" >
+ <analyzer>
+ <tokenizer class="solr.StandardTokenizerFactory"/>
+ <filter class="solr.LowerCaseFilterFactory"/>
+ <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
+ </analyzer>
+ </fieldType>
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
@@ -113,6 +120,7 @@
<field name="catch_all" type="text_general" indexed="true" stored="false" multiValued="true" termVectors="true"/> <!-- term vectors used for rep:similar -->
<field name="_version_" type="long" indexed="true" stored="true"/>
<field name=":path" type="string" indexed="true" stored="false"/>
+ <field name=":indexed" type="tdate" indexed="true" stored="false" default="NOW" docValues="numeric"/>
<field name="jcr:data" type="binary" indexed="true" stored="false" multiValued="true"/>
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
Modified: jackrabbit/oak/branches/1.0/oak-solr-core/src/test/resources/solr/oak/conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-solr-core/src/test/resources/solr/oak/conf/solrconfig.xml?rev=1665206&r1=1665205&r2=1665206&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-solr-core/src/test/resources/solr/oak/conf/solrconfig.xml (original)
+++ jackrabbit/oak/branches/1.0/oak-solr-core/src/test/resources/solr/oak/conf/solrconfig.xml Mon Mar 9 12:21:49 2015
@@ -808,6 +808,10 @@ Lucene will flush based on whichever lim
<str>nameOfCustomComponent2</str>
</arr>
-->
+ <arr name="last-components">
+ <str>mlt</str>
+ <str>spellcheck</str>
+ </arr>
</requestHandler>
<!-- A request handler that returns indented JSON by default -->
@@ -1196,7 +1200,7 @@ current implementation relies on the upd
-->
<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
- <str name="queryAnalyzerFieldType">textSpell</str>
+ <str name="queryAnalyzerFieldType">text_general</str>
<!-- Multiple "Spell Checkers" can be declared and used by this
component
@@ -1205,7 +1209,7 @@ current implementation relies on the upd
<!-- a spellchecker built from a field of the main index -->
<lst name="spellchecker">
<str name="name">default</str>
- <str name="field">name</str>
+ <str name="field">catch_all</str>
<str name="classname">solr.DirectSolrSpellChecker</str>
<!-- the spellcheck distance measure used, the default is the internal levenshtein -->
<str name="distanceMeasure">internal</str>
@@ -1221,9 +1225,7 @@ current implementation relies on the upd
<int name="minQueryLength">4</int>
<!-- maximum threshold of documents a query term can appear to be considered for correction -->
<float name="maxQueryFrequency">0.01</float>
- <!-- uncomment this to require suggestions to occur in 1% of the documents
- <float name="thresholdTokenFrequency">.01</float>
- -->
+
</lst>
<!-- a spellchecker that can break or combine words. See "/spell" handler below for usage -->
@@ -1288,9 +1290,9 @@ current implementation relies on the upd
See http://wiki.apache.org/solr/SpellCheckComponent for details
on the request parameters.
-->
- <requestHandler name="/spell" class="solr.SearchHandler" startup="lazy">
+ <requestHandler name="/spellcheck" class="solr.SearchHandler" startup="lazy">
<lst name="defaults">
- <str name="df">text</str>
+ <str name="df">catch_all</str>
<!-- Solr will use suggestions from both the 'default' spellchecker
and from the 'wordbreak' spellchecker and combine them.
collations (re-written queries) can include a combination of