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 ca...@apache.org on 2015/12/03 15:05:04 UTC

svn commit: r1717768 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/query/ oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ oak-doc/src/site/markdown/query/ oak-lucene/src/main/java/org/apache/jackrabbit/oak/plu...

Author: catholicon
Date: Thu Dec  3 14:05:04 2015
New Revision: 1717768

URL: http://svn.apache.org/viewvc?rev=1717768&view=rev
Log:
OAK-3352 Expose Lucene search score explanation
Use oak:scoreExplanation to show explanation of score as calculated by lucene. Filter is parsed in the same way as for rep:excerpt()

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
    jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/lucene.md
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
    jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java?rev=1717768&r1=1717767&r2=1717768&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java Thu Dec  3 14:05:04 2015
@@ -119,6 +119,11 @@ public class QueryImpl implements Query
     public static final String REP_EXCERPT = "rep:excerpt";
 
     /**
+     * The "oak:explainScore" pseudo-property.
+     */
+    public static final String OAK_SCORE_EXPLANATION = "oak:scoreExplanation";
+
+    /**
      * The "rep:spellcheck" pseudo-property.
      */
     public static final String REP_SPELLCHECK = "rep:spellcheck()";

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java?rev=1717768&r1=1717767&r2=1717768&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java Thu Dec  3 14:05:04 2015
@@ -661,6 +661,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.OAK_SCORE_EXPLANATION)) {
+            result = currentRow.getValue(QueryImpl.OAK_SCORE_EXPLANATION);
         } else if (oakPropertyName.equals(QueryImpl.REP_SPELLCHECK)) {
             result = currentRow.getValue(QueryImpl.REP_SPELLCHECK);
         } else if (oakPropertyName.equals(QueryImpl.REP_SUGGEST)) {

Modified: jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/lucene.md
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/lucene.md?rev=1717768&r1=1717767&r2=1717768&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/lucene.md (original)
+++ jackrabbit/oak/trunk/oak-doc/src/site/markdown/query/lucene.md Thu Dec  3 14:05:04 2015
@@ -1008,6 +1008,16 @@ Since Oak 1.3.11, the each suggestion wo
           - useInSpellcheck = true
 ```
 
+
+#### Score Explanation
+
+`@since Oak 1.3.12`
+
+Lucene supports [explanation of scores][score-explanation] which can be selected in a query using a virtual column `oak:scoreExplanation`.
+e.g. `select [oak:scoreExplanation], * from [nt:base] where foo='bar'`
+
+_Note that showing explanation score is expensive. So, this feature should be used for debug purposes only_.
+
 ### Design Considerations
 
 Lucene index provides quite a few features to meet various query requirements. 
@@ -1432,4 +1442,5 @@ such fields
 [tika-download]: https://tika.apache.org/download.html
 [oak-run-tika]: https://github.com/apache/jackrabbit-oak/tree/trunk/oak-run#tika
 [jcr-contains]: http://www.day.com/specs/jcr/1.0/6.6.5.2_jcr_contains_Function.html
-[boost-faq]: https://wiki.apache.org/lucene-java/LuceneFAQ#How_do_I_make_sure_that_a_match_in_a_document_title_has_greater_weight_than_a_match_in_a_document_body.3F
\ No newline at end of file
+[boost-faq]: https://wiki.apache.org/lucene-java/LuceneFAQ#How_do_I_make_sure_that_a_match_in_a_document_title_has_greater_weight_than_a_match_in_a_document_body.3F
+[score-explanation]: https://lucene.apache.org/core/4_6_0/core/org/apache/lucene/search/IndexSearcher.html#explain%28org.apache.lucene.search.Query,%20int%29
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java?rev=1717768&r1=1717767&r2=1717768&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java Thu Dec  3 14:05:04 2015
@@ -299,7 +299,8 @@ public class LucenePropertyIndex impleme
                 return endOfData();
             }
 
-            private LuceneResultRow convertToRow(ScoreDoc doc, IndexSearcher searcher, String excerpt) throws IOException {
+            private LuceneResultRow convertToRow(ScoreDoc doc, IndexSearcher searcher, String excerpt,
+                                                 String explanation) throws IOException {
                 IndexReader reader = searcher.getIndexReader();
                 //TODO Look into usage of field cache for retrieving the path
                 //instead of reading via reader if no of docs in index are limited
@@ -328,7 +329,7 @@ public class LucenePropertyIndex impleme
                     }
 
                     LOG.trace("Matched path {}", path);
-                    return new LuceneResultRow(path, doc.score, excerpt);
+                    return new LuceneResultRow(path, doc.score, excerpt, explanation);
                 }
                 return null;
             }
@@ -382,14 +383,22 @@ public class LucenePropertyIndex impleme
                             PERF_LOGGER.end(start, -1, "{} ...", docs.scoreDocs.length);
                             nextBatchSize = (int) Math.min(nextBatchSize * 2L, 100000);
 
-                            boolean addExcerpt = filter.getQueryStatement() != null && filter.getQueryStatement().contains(QueryImpl.REP_EXCERPT);
+                            String queryStatement = filter.getQueryStatement();
+                            boolean addExcerpt = queryStatement != null && queryStatement.contains(QueryImpl.REP_EXCERPT);
+                            boolean addExplain = queryStatement != null && queryStatement.contains(QueryImpl.OAK_SCORE_EXPLANATION);
+
                             for (ScoreDoc doc : docs.scoreDocs) {
                                 String excerpt = null;
                                 if (addExcerpt) {
                                     excerpt = getExcerpt(indexNode, searcher, query, doc);
                                 }
 
-                                LuceneResultRow row = convertToRow(doc, searcher, excerpt);
+                                String explanation = null;
+                                if (addExplain) {
+                                    explanation = searcher.explain(query, doc.doc).toString();
+                                }
+
+                                LuceneResultRow row = convertToRow(doc, searcher, excerpt, explanation);
                                 if (row != null) {
                                     queue.add(row);
                                 }
@@ -1324,8 +1333,10 @@ public class LucenePropertyIndex impleme
         final String suggestion;
         final boolean isVirutal;
         final String excerpt;
+        final String explanation;
 
-        LuceneResultRow(String path, double score, String excerpt) {
+        LuceneResultRow(String path, double score, String excerpt, String explanation) {
+            this.explanation = explanation;
             this.excerpt = excerpt;
             this.isVirutal = false;
             this.path = path;
@@ -1339,6 +1350,7 @@ public class LucenePropertyIndex impleme
             this.score = weight;
             this.suggestion = suggestion;
             this.excerpt = null;
+            this.explanation = null;
         }
 
         LuceneResultRow(String suggestion) {
@@ -1428,6 +1440,9 @@ public class LucenePropertyIndex impleme
                     if (QueryImpl.REP_SPELLCHECK.equals(columnName) || QueryImpl.REP_SUGGEST.equals(columnName)) {
                         return PropertyValues.newString(currentRow.suggestion);
                     }
+                    if (QueryImpl.OAK_SCORE_EXPLANATION.equals(columnName)) {
+                        return PropertyValues.newString(currentRow.explanation);
+                    }
                     if (QueryImpl.REP_EXCERPT.equals(columnName)) {
                         return PropertyValues.newString(currentRow.excerpt);
                     }

Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java?rev=1717768&r1=1717767&r2=1717768&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java Thu Dec  3 14:05:04 2015
@@ -432,6 +432,22 @@ public class LucenePropertyIndexTest ext
         assertQuery("select [jcr:path] from [nt:base] where propa is not null", asList("/test/a", "/test/b"));
     }
 
+    @Test
+    public void explainScoreTest() throws Exception {
+        Tree idx = createIndex("test1", of("propa"));
+        idx.addChild(PROP_NODE).addChild("propa");
+        root.commit();
+
+        Tree test = root.getTree("/").addChild("test");
+        test.addChild("a").setProperty("propa", "a");
+        root.commit();
+
+        String query = "select [oak:scoreExplanation] from [nt:base] where propa='a'";
+        List<String> result = executeQuery(query, SQL2, false, false);
+        assertEquals(1, result.size());
+        assertTrue(result.get(0).contains("(MATCH)"));
+    }
+
     //OAK-2568
     @Test
     public void multiValueAnd() throws Exception{