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
|
to gather the hit-count per sub-clause and per document while a
|
||||||
search is running. (Simon Willnauer, Mike McCandless)
|
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
|
Optimizations
|
||||||
|
|
||||||
* LUCENE-2410: ~20% speedup on exact (slop=0) PhraseQuery matching.
|
* 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