mirror of https://github.com/apache/lucene.git
LUCENE-2636: Create ChainingCollector (trunk)
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@995375 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f60c6dab5b
commit
1fc5c8ee22
|
@ -213,6 +213,9 @@ New features
|
|||
to gather the hit-count per sub-clause and per document while a
|
||||
search is running. (Simon Willnauer, Mike McCandless)
|
||||
|
||||
* LUCENE-2636: Added ChainingCollector which allows chaining several Collectors
|
||||
together and be passed to IndexSearcher.search methods. (Shai Erera)
|
||||
|
||||
Optimizations
|
||||
|
||||
* LUCENE-2410: ~20% speedup on exact (slop=0) PhraseQuery matching.
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
package org.apache.lucene.search;
|
||||
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.search.Collector;
|
||||
import org.apache.lucene.search.Scorer;
|
||||
|
||||
/**
|
||||
* A {@link Collector} which allows chaining several {@link Collector}s in order
|
||||
* to process the matching documents emitted to {@link #collect(int)}. This
|
||||
* collector accepts a list of {@link Collector}s in its constructor, allowing
|
||||
* for some of them to be <code>null</code>. It optimizes away those
|
||||
* <code>null</code> collectors, so that they are not acessed during collection
|
||||
* time.
|
||||
* <p>
|
||||
* <b>NOTE:</b> if all the collectors passed to the constructor are null, then
|
||||
* {@link IllegalArgumentException} is thrown - it is useless to run the search
|
||||
* with 0 collectors.
|
||||
*/
|
||||
public class ChainingCollector extends Collector {
|
||||
|
||||
private final Collector[] collectors;
|
||||
|
||||
public ChainingCollector(Collector... collectors) {
|
||||
// For the user's convenience, we allow null collectors to be passed.
|
||||
// However, to improve performance, these null collectors are found
|
||||
// and dropped from the array we save for actual collection time.
|
||||
int n = 0;
|
||||
for (Collector c : collectors) {
|
||||
if (c != null) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
throw new IllegalArgumentException("At least 1 collector must not be null");
|
||||
} else if (n == collectors.length) {
|
||||
// No null collectors, can use the given list as is.
|
||||
this.collectors = collectors;
|
||||
} else {
|
||||
this.collectors = new Collector[n];
|
||||
n = 0;
|
||||
for (Collector c : collectors) {
|
||||
if (c != null) {
|
||||
this.collectors[n++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsDocsOutOfOrder() {
|
||||
for (Collector c : collectors) {
|
||||
if (!c.acceptsDocsOutOfOrder()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collect(int doc) throws IOException {
|
||||
for (Collector c : collectors) {
|
||||
c.collect(doc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextReader(IndexReader reader, int o) throws IOException {
|
||||
for (Collector c : collectors) {
|
||||
c.setNextReader(reader, o);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScorer(Scorer s) throws IOException {
|
||||
for (Collector c : collectors) {
|
||||
c.setScorer(s);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package org.apache.lucene.search;
|
||||
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.search.Collector;
|
||||
import org.apache.lucene.search.Scorer;
|
||||
import org.apache.lucene.util.LuceneTestCaseJ4;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ChainingCollectorTest extends LuceneTestCaseJ4 {
|
||||
|
||||
private static class DummyCollector extends Collector {
|
||||
|
||||
boolean acceptsDocsOutOfOrderCalled = false;
|
||||
boolean collectCalled = false;
|
||||
boolean setNextReaderCalled = false;
|
||||
boolean setScorerCalled = false;
|
||||
|
||||
@Override
|
||||
public boolean acceptsDocsOutOfOrder() {
|
||||
acceptsDocsOutOfOrderCalled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collect(int doc) throws IOException {
|
||||
collectCalled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextReader(IndexReader reader, int docBase) throws IOException {
|
||||
setNextReaderCalled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScorer(Scorer scorer) throws IOException {
|
||||
setScorerCalled = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullCollectors() throws Exception {
|
||||
// Tests that the collector rejects all null collectors.
|
||||
try {
|
||||
new ChainingCollector(null, null);
|
||||
fail("all collectors null should not be supported");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
// Tests that the collector handles some null collectors well. If it
|
||||
// doesn't, an NPE would be thrown.
|
||||
Collector c = new ChainingCollector(new DummyCollector(), null, new DummyCollector());
|
||||
assertTrue(c.acceptsDocsOutOfOrder());
|
||||
c.collect(1);
|
||||
c.setNextReader(null, 0);
|
||||
c.setScorer(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCollector() throws Exception {
|
||||
// Tests that the collector delegates calls to input collectors properly.
|
||||
|
||||
// Tests that the collector handles some null collectors well. If it
|
||||
// doesn't, an NPE would be thrown.
|
||||
DummyCollector[] dcs = new DummyCollector[] { new DummyCollector(), new DummyCollector() };
|
||||
Collector c = new ChainingCollector(dcs);
|
||||
assertTrue(c.acceptsDocsOutOfOrder());
|
||||
c.collect(1);
|
||||
c.setNextReader(null, 0);
|
||||
c.setScorer(null);
|
||||
|
||||
for (DummyCollector dc : dcs) {
|
||||
assertTrue(dc.acceptsDocsOutOfOrderCalled);
|
||||
assertTrue(dc.collectCalled);
|
||||
assertTrue(dc.setNextReaderCalled);
|
||||
assertTrue(dc.setScorerCalled);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue