GEODE-11: Remote TopDocs and refactor QueryResults * The function of TopDocsResultMerger is now performed by TopEntriesCollector. So TopDocs related classes and test code is not needed. * LuceneQueryResults will serve result pages and also fetch EntryValue on demand. The methods to return entire result set is not needed.
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/38ff05e5 Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/38ff05e5 Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/38ff05e5 Branch: refs/heads/feature/GEODE-11 Commit: 38ff05e5863c12a671ea4b3a6b0bbd70cb785fd1 Parents: 02d56eb Author: Ashvin Agrawal <[email protected]> Authored: Fri Sep 11 17:01:43 2015 -0700 Committer: Ashvin Agrawal <[email protected]> Committed: Fri Sep 11 17:01:43 2015 -0700 ---------------------------------------------------------------------- .../cache/lucene/LuceneQueryResults.java | 5 - .../lucene/internal/LuceneQueryResultsImpl.java | 5 - .../lucene/internal/mergers/ResultMerger.java | 25 --- .../internal/mergers/TopDocsResultMerger.java | 78 ------- .../internal/LuceneQueryResultsJUnitTest.java | 24 --- .../internal/mergers/TopDocsMergeJUnitTest.java | 206 ------------------- 6 files changed, 343 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/38ff05e5/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQueryResults.java ---------------------------------------------------------------------- diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQueryResults.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQueryResults.java index 1a3515d..d597b66 100644 --- a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQueryResults.java +++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQueryResults.java @@ -22,11 +22,6 @@ public interface LuceneQueryResults { public int size(); /** - * Returns the list of the top hits for the query. - */ - public List<LuceneResultStruct> getHits(); - - /** * Returns the maximum score value encountered. Note that in case scores are not tracked, this returns {@link Float#NaN}. */ public float getMaxScore(); http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/38ff05e5/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryResultsImpl.java ---------------------------------------------------------------------- diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryResultsImpl.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryResultsImpl.java index 02b596a..11200c2 100644 --- a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryResultsImpl.java +++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryResultsImpl.java @@ -68,11 +68,6 @@ public class LuceneQueryResultsImpl implements LuceneQueryResults, } @Override - public List<LuceneResultStruct> getHits() { - return hits; - } - - @Override public float getMaxScore() { return maxScore; } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/38ff05e5/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/mergers/ResultMerger.java ---------------------------------------------------------------------- diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/mergers/ResultMerger.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/mergers/ResultMerger.java deleted file mode 100644 index cb60604..0000000 --- a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/mergers/ResultMerger.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.gemstone.gemfire.cache.lucene.internal.mergers; - -import java.util.List; - -import com.gemstone.gemfire.cache.lucene.LuceneQuery; -import com.gemstone.gemfire.cache.lucene.LuceneQueryResults; - -/** - * Search results collected from individual shards/members are combined into one result set by {@link ResultMergers}. - */ -public abstract class ResultMerger<E> { - /** - * @param results - * List of the result collected from the shards - * @return merge result set - */ - public abstract LuceneQueryResults mergeResults(List<LuceneQueryResults> results); - - /** - * @param query - * Merge operation will be executed within the context of a query For e.g. the query context could be used to control the total number of results - * returned. - */ - public abstract void init(LuceneQuery query); -} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/38ff05e5/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/mergers/TopDocsResultMerger.java ---------------------------------------------------------------------- diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/mergers/TopDocsResultMerger.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/mergers/TopDocsResultMerger.java deleted file mode 100644 index bd1c4bb..0000000 --- a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/mergers/TopDocsResultMerger.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.gemstone.gemfire.cache.lucene.internal.mergers; - -import java.util.Comparator; -import java.util.List; -import java.util.PriorityQueue; - -import org.apache.logging.log4j.Logger; - -import com.gemstone.gemfire.cache.lucene.LuceneQuery; -import com.gemstone.gemfire.cache.lucene.LuceneQueryFactory; -import com.gemstone.gemfire.cache.lucene.LuceneQueryResults; -import com.gemstone.gemfire.cache.lucene.LuceneResultStruct; -import com.gemstone.gemfire.cache.lucene.internal.LuceneQueryResultsImpl; -import com.gemstone.gemfire.internal.logging.LogService; - -/** - * An implementation of {@link ResultMerger} which combines search results from shards on the basis of score - */ -public class TopDocsResultMerger extends ResultMerger<LuceneResultStruct> { - // execute merge within the context of this query - LuceneQuery queryCtx; - - private static final Logger logger = LogService.getLogger(); - - @Override - public void init(LuceneQuery query) { - this.queryCtx = query; - } - - @Override - public LuceneQueryResults mergeResults(List<LuceneQueryResults> results) { - if (logger.isDebugEnabled()) { - logger.debug("Merging {} shard results for query {}", results.size(), queryCtx); - } - - // orders a doc with higher score above a doc with lower score - Comparator<List<LuceneResultStruct>> comparator = new Comparator<List<LuceneResultStruct>>() { - @Override - public int compare(List<LuceneResultStruct> l1, List<LuceneResultStruct> l2) { - LuceneResultStruct o1 = l1.get(0); - LuceneResultStruct o2 = l2.get(0); - int result = Float.compare(o1.getScore(), o2.getScore()) * (-1); - if (result != 0) { - return result; - } - - return Integer.compare(o1.getKey().hashCode(), o2.getKey().hashCode()); - } - }; - - // The queue contains iterators for all shard results. The iterator with the highest score doc is put at the head of the queue using score comparator - PriorityQueue<List<LuceneResultStruct>> queue = new PriorityQueue<List<LuceneResultStruct>>(11, comparator); - - LuceneQueryResultsImpl mergedResult = new LuceneQueryResultsImpl(); - for (LuceneQueryResults result : results) { - if (logger.isDebugEnabled()) { - logger.debug("Count of results returned from shard {} is {}", result.getID(), result.size()); - } - - List<LuceneResultStruct> list = result.getHits(); - if (list.size() > 0) { - queue.add(list); - } - } - - int limit = queryCtx == null ? LuceneQueryFactory.DEFAULT_LIMIT : queryCtx.getLimit(); - logger.debug("Merge result count will be limited to: " + limit); - while (queue.size() > 0 && limit-- > 0) { - List<LuceneResultStruct> list = queue.remove(); - mergedResult.addHit(list.remove(0)); - if (list.size() > 0) { - queue.add(list); - } - } - - return mergedResult; - } -} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/38ff05e5/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryResultsJUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryResultsJUnitTest.java b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryResultsJUnitTest.java deleted file mode 100644 index b2ba845..0000000 --- a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryResultsJUnitTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.gemstone.gemfire.cache.lucene.internal; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.junit.experimental.categories.Category; - -import com.gemstone.gemfire.test.junit.categories.UnitTest; - -@Category(UnitTest.class) -public class LuceneQueryResultsJUnitTest { - @Test - public void addHitTest() { - LuceneQueryResultsImpl results = new LuceneQueryResultsImpl(); - assertEquals(0, results.getHits().size()); - results.addHit(new LuceneResultStructImpl("key", 0.1f)); - assertEquals(1, results.getHits().size()); - assertEquals(0.1f, results.getMaxScore(), 0f); - - results.addHit(new LuceneResultStructImpl("key", 0.2f)); - assertEquals(2, results.getHits().size()); - assertEquals(0.2f, results.getMaxScore(), 0f); - } -} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/38ff05e5/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/mergers/TopDocsMergeJUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/mergers/TopDocsMergeJUnitTest.java b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/mergers/TopDocsMergeJUnitTest.java deleted file mode 100644 index 8c6899f..0000000 --- a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/mergers/TopDocsMergeJUnitTest.java +++ /dev/null @@ -1,206 +0,0 @@ -package com.gemstone.gemfire.cache.lucene.internal.mergers; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; - -import java.util.ArrayList; -import java.util.List; - -import org.jmock.Expectations; -import org.jmock.Mockery; -import org.jmock.lib.concurrent.Synchroniser; -import org.jmock.lib.legacy.ClassImposteriser; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -import com.gemstone.gemfire.cache.lucene.LuceneQuery; -import com.gemstone.gemfire.cache.lucene.LuceneQueryFactory; -import com.gemstone.gemfire.cache.lucene.LuceneQueryResults; -import com.gemstone.gemfire.cache.lucene.LuceneResultStruct; -import com.gemstone.gemfire.cache.lucene.internal.LuceneQueryResultsImpl; -import com.gemstone.gemfire.cache.lucene.internal.LuceneResultStructImpl; -import com.gemstone.gemfire.test.junit.categories.UnitTest; - -@Category(UnitTest.class) -public class TopDocsMergeJUnitTest { - Mockery mockContext; - - @Before - public void setupMock() { - mockContext = new Mockery() { - { - setImposteriser(ClassImposteriser.INSTANCE); - setThreadingPolicy(new Synchroniser()); - } - }; - } - - @After - public void validateMock() { - mockContext.assertIsSatisfied(); - mockContext = null; - } - - @Test - public void mergeMultipleShardResults() throws Exception { - LuceneResultStructImpl r1_1 = new LuceneResultStructImpl("k1_1", .9f); - LuceneResultStructImpl r1_2 = new LuceneResultStructImpl("k1_2", .8f); - - LuceneQueryResultsImpl r1 = new LuceneQueryResultsImpl(); - r1.addHit(r1_1); - r1.addHit(r1_2); - - LuceneResultStructImpl r2_1 = new LuceneResultStructImpl("k2_1", 0.85f); - LuceneResultStructImpl r2_2 = new LuceneResultStructImpl("k2_2", 0.1f); - LuceneQueryResultsImpl r2 = new LuceneQueryResultsImpl(); - r2.addHit(r2_1); - r2.addHit(r2_2); - - List<LuceneQueryResults> results = new ArrayList<LuceneQueryResults>(); - results.add(r1); - results.add(r2); - - ResultMerger<LuceneResultStruct> merger = new TopDocsResultMerger(); - LuceneQueryResults merged = merger.mergeResults(results); - assertNotNull(merged); - assertEquals(4, merged.size()); - assertEquals(.9f, merged.getMaxScore(), 0f); - - verifyResultOrder(merged, r1_1, r2_1, r1_2, r2_2); - } - - @Test - public void mergeShardAndLimitResults() throws Exception { - LuceneResultStructImpl r1_1 = new LuceneResultStructImpl("k1_1", .9f); - LuceneResultStructImpl r1_2 = new LuceneResultStructImpl("k1_2", .8f); - - LuceneQueryResultsImpl r1 = new LuceneQueryResultsImpl(); - r1.addHit(r1_1); - r1.addHit(r1_2); - assertEquals(2, r1.size()); - - LuceneResultStructImpl r2_1 = new LuceneResultStructImpl("k2_1", 0.85f); - LuceneResultStructImpl r2_2 = new LuceneResultStructImpl("k2_2", 0.1f); - LuceneQueryResultsImpl r2 = new LuceneQueryResultsImpl(); - r2.addHit(r2_1); - r2.addHit(r2_2); - assertEquals(2, r2.size()); - - List<LuceneQueryResults> results = new ArrayList<LuceneQueryResults>(); - results.add(r1); - results.add(r2); - - final LuceneQuery mockQuery = mockContext.mock(LuceneQuery.class); - mockContext.checking(new Expectations() { - { - oneOf(mockQuery).getLimit(); - will(returnValue(3)); - } - }); - - ResultMerger<LuceneResultStruct> merger = new TopDocsResultMerger(); - merger.init(mockQuery); - LuceneQueryResults merged = merger.mergeResults(results); - assertNotNull(merged); - assertEquals(3, merged.size()); - assertEquals(.9f, merged.getMaxScore(), 0f); - - verifyResultOrder(merged, r1_1, r2_1, r1_2); - } - - @Test - public void mergeDocsWithSameScoreandSameHashcode() throws Exception { - class KeyObject { - String str; - - public KeyObject(String str) { - this.str = str; - } - - @Override - public int hashCode() { - return str.length(); - } - - @Override - public boolean equals(Object obj) { - KeyObject tmp = (KeyObject) obj; - return tmp.str.equals(this.str); - } - - @Override - public String toString() { - return str; - } - } - - // Add at least two docs with different key, same score, same hashcode - KeyObject key1 = new KeyObject("1_2"); - KeyObject key2 = new KeyObject("2_1"); - float keyScore = .5f; - assertNotEquals(key1, key2); - assertEquals(key1.hashCode(), key2.hashCode()); - - LuceneQueryResultsImpl r1 = new LuceneQueryResultsImpl(); - LuceneResultStructImpl r1_1 = new LuceneResultStructImpl(new KeyObject("1_1"), .9f); - LuceneResultStructImpl r1_2 = new LuceneResultStructImpl(key1, keyScore); - LuceneResultStructImpl r1_3 = new LuceneResultStructImpl(new KeyObject("1_3"), .2f); - r1.addHit(r1_1); - r1.addHit(r1_2); - r1.addHit(r1_3); - - LuceneResultStructImpl r2_1 = new LuceneResultStructImpl(key2, keyScore); - LuceneResultStructImpl r2_2 = new LuceneResultStructImpl(new KeyObject("2_2"), .1f); - LuceneQueryResultsImpl r2 = new LuceneQueryResultsImpl(); - r2.addHit(r2_1); - r2.addHit(r2_2); - - List<LuceneQueryResults> results = new ArrayList<LuceneQueryResults>(); - results.add(r1); - results.add(r2); - - ResultMerger<LuceneResultStruct> merger = new TopDocsResultMerger(); - LuceneQueryResults merged = merger.mergeResults(results); - assertNotNull(merged); - assertEquals(5, merged.size()); - - verifyResultOrder(merged, r1_1, r2_1, r1_2, r1_3, r2_2); - } - - public static void verifyResultOrder(LuceneQueryResults merged, LuceneResultStruct... results) { - int i = 0; - for (LuceneResultStruct result : results) { - LuceneResultStruct doc = merged.getHits().get(i++); - assertEquals(result.getKey(), doc.getKey()); - assertEquals(result.getScore(), doc.getScore(), .0f); - } - } - - @Test - public void verifyDefaultLimit() throws Exception { - LuceneQueryResultsImpl r1 = new LuceneQueryResultsImpl(); - for (int i = 0; i < LuceneQueryFactory.DEFAULT_LIMIT; i++) { - r1.addHit(new LuceneResultStructImpl("k1_" + i, .9f)); - } - assertEquals(LuceneQueryFactory.DEFAULT_LIMIT, r1.size()); - - LuceneQueryResultsImpl r2 = new LuceneQueryResultsImpl(); - for (int i = 0; i < LuceneQueryFactory.DEFAULT_LIMIT; i++) { - r2.addHit(new LuceneResultStructImpl("k2_" + i, .9f)); - } - assertEquals(LuceneQueryFactory.DEFAULT_LIMIT, r2.size()); - - List<LuceneQueryResults> results = new ArrayList<LuceneQueryResults>(); - results.add(r1); - results.add(r2); - - ResultMerger<LuceneResultStruct> merger = new TopDocsResultMerger(); - LuceneQueryResults merged = merger.mergeResults(results); - assertNotNull(merged); - assertEquals(LuceneQueryFactory.DEFAULT_LIMIT, merged.size()); - assertEquals(.9f, merged.getMaxScore(), 0f); - } -}
