Index: lucene/core/src/java/org/apache/lucene/index/AtomicReader.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/AtomicReader.java (revision 1458834) +++ lucene/core/src/java/org/apache/lucene/index/AtomicReader.java (working copy) @@ -107,6 +107,33 @@ return 0; } } + + @Override + public final long getSumDocFreq(String field) throws IOException { + final Terms terms = terms(field); + if (terms == null) { + return 0; + } + return terms.getSumDocFreq(); + } + + @Override + public final int getDocCount(String field) throws IOException { + final Terms terms = terms(field); + if (terms == null) { + return 0; + } + return terms.getDocCount(); + } + + @Override + public final long getSumTotalTermFreq(String field) throws IOException { + final Terms terms = terms(field); + if (terms == null) { + return 0; + } + return terms.getSumTotalTermFreq(); + } /** This may return null if the field does not exist.*/ public final Terms terms(String field) throws IOException { Index: lucene/core/src/java/org/apache/lucene/index/BaseCompositeReader.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/BaseCompositeReader.java (revision 1458834) +++ lucene/core/src/java/org/apache/lucene/index/BaseCompositeReader.java (working copy) @@ -145,7 +145,49 @@ } return total; } + + @Override + public final long getSumDocFreq(String field) throws IOException { + ensureOpen(); + long total = 0; // sum doc freqs in subreaders + for (R reader : subReaders) { + long sub = reader.getSumDocFreq(field); + if (sub == -1) { + return -1; // if any of the subs doesn't support it, return -1 + } + total += sub; + } + return total; + } + + @Override + public final int getDocCount(String field) throws IOException { + ensureOpen(); + int total = 0; // sum doc counts in subreaders + for (R reader : subReaders) { + int sub = reader.getDocCount(field); + if (sub == -1) { + return -1; // if any of the subs doesn't support it, return -1 + } + total += sub; + } + return total; + } + @Override + public final long getSumTotalTermFreq(String field) throws IOException { + ensureOpen(); + long total = 0; // sum doc total term freqs in subreaders + for (R reader : subReaders) { + long sub = reader.getSumTotalTermFreq(field); + if (sub == -1) { + return -1; // if any of the subs doesn't support it, return -1 + } + total += sub; + } + return total; + } + /** Helper method for subclasses to get the corresponding reader for a doc ID */ protected final int readerIndex(int docID) { if (docID < 0 || docID >= maxDoc) { Index: lucene/core/src/java/org/apache/lucene/index/IndexReader.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/IndexReader.java (revision 1458834) +++ lucene/core/src/java/org/apache/lucene/index/IndexReader.java (working copy) @@ -446,4 +446,33 @@ * @see TermsEnum#totalTermFreq() */ public abstract long totalTermFreq(Term term) throws IOException; + + /** + * Returns the sum of {@link TermsEnum#docFreq()} for all terms in this field, + * or -1 if this measure isn't stored by the codec. Note that, just like other + * term measures, this measure does not take deleted documents into account. + * + * @see Terms#getSumDocFreq() + */ + public abstract long getSumDocFreq(String field) throws IOException; + + /** + * Returns the number of documents that have at least one term for this field, + * or -1 if this measure isn't stored by the codec. Note that, just like other + * term measures, this measure does not take deleted documents into account. + * + * @see Terms#getDocCount() + */ + public abstract int getDocCount(String field) throws IOException; + + /** + * Returns the sum of {@link TermsEnum#totalTermFreq} for all terms in this + * field, or -1 if this measure isn't stored by the codec (or if this fields + * omits term freq and positions). Note that, just like other term measures, + * this measure does not take deleted documents into account. + * + * @see Terms#getSumTotalTermFreq() + */ + public abstract long getSumTotalTermFreq(String field) throws IOException; + } Index: lucene/core/src/java/org/apache/lucene/index/MultiFields.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/MultiFields.java (revision 1458834) +++ lucene/core/src/java/org/apache/lucene/index/MultiFields.java (working copy) @@ -243,25 +243,6 @@ return -1; } - /** Returns the total number of occurrences of this term - * across all documents (the sum of the freq() for each - * doc that has this term). This will be -1 if the - * codec doesn't support this measure. Note that, like - * other term measures, this measure does not take - * deleted documents into account. - * @see TermsEnum#totalTermFreq() - */ - public static long totalTermFreq(IndexReader r, String field, BytesRef text) throws IOException { - final Terms terms = getTerms(r, field); - if (terms != null) { - final TermsEnum termsEnum = terms.iterator(null); - if (termsEnum.seekExact(text, true)) { - return termsEnum.totalTermFreq(); - } - } - return 0; - } - /** Call this to get the (merged) FieldInfos for a * composite reader. *

Index: lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java =================================================================== --- lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java (revision 1458834) +++ lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java (working copy) @@ -939,16 +939,79 @@ writer.close(); try { // Make sure codec impls totalTermFreq (eg PreFlex doesn't) - Assume.assumeTrue(MultiFields.totalTermFreq(r, "f", new BytesRef("b")) != -1); - assertEquals(1, MultiFields.totalTermFreq(r, "f", new BytesRef("b"))); - assertEquals(2, MultiFields.totalTermFreq(r, "f", new BytesRef("a"))); - assertEquals(1, MultiFields.totalTermFreq(r, "f", new BytesRef("b"))); + Assume.assumeTrue(r.totalTermFreq(new Term("f", new BytesRef("b"))) != -1); + assertEquals(1, r.totalTermFreq(new Term("f", new BytesRef("b")))); + assertEquals(2, r.totalTermFreq(new Term("f", new BytesRef("a")))); + assertEquals(1, r.totalTermFreq(new Term("f", new BytesRef("b")))); } finally { r.close(); dir.close(); } } + public void testGetSumDocFreq() throws Exception { + Directory dir = newDirectory(); + IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random()))); + Document d = new Document(); + d.add(newTextField("f", "a", Field.Store.NO)); + writer.addDocument(d); + d = new Document(); + d.add(newTextField("f", "b", Field.Store.NO)); + writer.addDocument(d); + DirectoryReader r = writer.getReader(); + writer.close(); + try { + // Make sure codec impls getSumDocFreq (eg PreFlex doesn't) + Assume.assumeTrue(r.getSumDocFreq("f") != -1); + assertEquals(2, r.getSumDocFreq("f")); + } finally { + r.close(); + dir.close(); + } + } + + public void testGetDocCount() throws Exception { + Directory dir = newDirectory(); + IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random()))); + Document d = new Document(); + d.add(newTextField("f", "a", Field.Store.NO)); + writer.addDocument(d); + d = new Document(); + d.add(newTextField("f", "a", Field.Store.NO)); + writer.addDocument(d); + DirectoryReader r = writer.getReader(); + writer.close(); + try { + // Make sure codec impls getSumDocFreq (eg PreFlex doesn't) + Assume.assumeTrue(r.getDocCount("f") != -1); + assertEquals(2, r.getDocCount("f")); + } finally { + r.close(); + dir.close(); + } + } + + public void testGetSumTotalTermFreq() throws Exception { + Directory dir = newDirectory(); + IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random()))); + Document d = new Document(); + d.add(newTextField("f", "a b b", Field.Store.NO)); + writer.addDocument(d); + d = new Document(); + d.add(newTextField("f", "a a b", Field.Store.NO)); + writer.addDocument(d); + DirectoryReader r = writer.getReader(); + writer.close(); + try { + // Make sure codec impls getSumDocFreq (eg PreFlex doesn't) + Assume.assumeTrue(r.getSumTotalTermFreq("f") != -1); + assertEquals(6, r.getSumTotalTermFreq("f")); + } finally { + r.close(); + dir.close(); + } + } + // LUCENE-2474 public void testReaderFinishedListener() throws Exception { Directory dir = newDirectory(); Index: lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java =================================================================== --- lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java (revision 1458834) +++ lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java (working copy) @@ -439,9 +439,8 @@ iw.addDocument(doc); IndexReader ir = iw.getReader(); iw.close(); - Terms terms = MultiFields.getTerms(ir, "foo"); - assertEquals(-1, MultiFields.totalTermFreq(ir, "foo", new BytesRef("bar"))); - assertEquals(-1, terms.getSumTotalTermFreq()); + assertEquals(-1, ir.totalTermFreq(new Term("foo", new BytesRef("bar")))); + assertEquals(-1, ir.getSumTotalTermFreq("foo")); ir.close(); dir.close(); }