/** * Find all documents that contain a specific search term, ordered by relevance. This method * supports all Lucene search query syntax. * * @param virtualWiki The virtual wiki for the topic. * @param text The search term being searched for. * @return A list of SearchResultEntry objects for all documents that contain the search term. */ public List<SearchResultEntry> findResults( String virtualWiki, String text, List<Integer> namespaces) { StandardAnalyzer analyzer = new StandardAnalyzer(USE_LUCENE_VERSION); List<SearchResultEntry> results = new ArrayList<SearchResultEntry>(); logger.trace("search text: " + text); try { IndexSearcher searcher = this.retrieveIndexSearcher(virtualWiki); Query query = this.createSearchQuery(searcher, analyzer, text, namespaces); // actually perform the search TopScoreDocCollector collector = TopScoreDocCollector.create(MAXIMUM_RESULTS_PER_SEARCH, true); searcher.search(query, collector); Highlighter highlighter = new Highlighter( new SimpleHTMLFormatter("<span class=\"highlight\">", "</span>"), new SimpleHTMLEncoder(), new QueryScorer(query, FIELD_TOPIC_CONTENT)); ScoreDoc[] hits = collector.topDocs().scoreDocs; for (int i = 0; i < hits.length; i++) { int docId = hits[i].doc; Document doc = searcher.doc(docId); String summary = retrieveResultSummary(doc, highlighter, analyzer); SearchResultEntry result = new SearchResultEntry(); result.setRanking(hits[i].score); result.setTopic(doc.get(FIELD_TOPIC_NAME)); result.setSummary(summary); results.add(result); } } catch (Exception e) { logger.error("Exception while searching for " + text, e); } return results; }
/** Search, sorting by score, and computing drill down and sideways counts. */ public DrillSidewaysResult search(ScoreDoc after, DrillDownQuery query, int topN) throws IOException { int limit = searcher.getIndexReader().maxDoc(); if (limit == 0) { limit = 1; // the collector does not alow numHits = 0 } topN = Math.min(topN, limit); TopScoreDocCollector hitCollector = TopScoreDocCollector.create(topN, after, true); DrillSidewaysResult r = search(query, hitCollector); return new DrillSidewaysResult(r.facets, hitCollector.topDocs()); }
private int doSearch(String searchPhrase, int maxNumberOfHits, Version luenceVersion) throws NullPointerException, ParseException, IOException { LOG.trace("*** Search Phrase: {} ***", searchPhrase); QueryParser parser = new QueryParser(luenceVersion, "contents", analyzer); Query query = parser.parse(searchPhrase); TopScoreDocCollector collector = TopScoreDocCollector.create(maxNumberOfHits, true); indexSearcher.search(query, collector); hits = collector.topDocs().scoreDocs; LOG.trace("*** Search generated {} hits ***", hits.length); return hits.length; }
/** * Creates and submits a query to the Lucene engine. * * @param query The base query, using the query engine supported by Lucene. * @param sort A Lucene sort object, can contain one or more sort criterias. If <tt>null</tt>, * sort by hit score. * @param virtualWikiNames Comma separated list of virtual wiki names to search in, may be * <tt>null</tt> to search all virtual wikis. * @param languages Comma separated list of language codes to search in, may be <tt>null</tt> or * empty to search all languages. * @param indexes List of Lucene indexes (readers) to search. * @param context The context of the request. * @return The list of search results. * @throws IOException If the Lucene searchers encounter a problem reading the indexes. * @throws ParseException If the query is not valid. */ private SearchResults search( String query, Sort sort, String virtualWikiNames, String languages, IndexReader[] indexes, XWikiContext context) throws IOException, ParseException { IndexSearcher searcher = new IndexSearcher(new MultiReader(indexes, true)); // Enhance the base query with wiki names and languages. Query q = buildQuery(query, virtualWikiNames, languages); // Perform the actual search TopDocsCollector<? extends ScoreDoc> results; if (sort != null) { results = TopFieldCollector.create(sort, 1000, true, true, false, false); } else { results = TopScoreDocCollector.create(1000, false); } searcher.search(q, results); LOGGER.debug("query [{}] returned {} hits", q, results.getTotalHits()); // Transform the raw Lucene search results into XWiki-aware results return new SearchResults( results, searcher, new com.xpn.xwiki.api.XWiki(context.getWiki(), context), context); }
public ReRankCollector( int reRankDocs, int length, Query reRankQuery, double reRankWeight, SolrIndexSearcher.QueryCommand cmd, IndexSearcher searcher, Map<BytesRef, Integer> boostedPriority, boolean scale) throws IOException { super(null); this.reRankQuery = reRankQuery; this.reRankDocs = reRankDocs; this.length = length; this.boostedPriority = boostedPriority; this.scale = scale; Sort sort = cmd.getSort(); if (sort == null) { this.mainCollector = TopScoreDocCollector.create(Math.max(this.reRankDocs, length), true); } else { sort = sort.rewrite(searcher); this.mainCollector = TopFieldCollector.create( sort, Math.max(this.reRankDocs, length), false, true, true, true); } this.searcher = searcher; this.reRankWeight = reRankWeight; }
public static void main(String[] args) throws IOException, ParseException { // 0. Specify the analyzer for tokenizing text. // The same analyzer should be used for indexing and searching StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_35); // 1. create the index Directory index = new RAMDirectory(); IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, analyzer); IndexWriter w = new IndexWriter(index, config); addDoc(w, "Lucene in Action"); addDoc(w, "Lucene for Dummies"); addDoc(w, "Managing Gigabytes"); addDoc(w, "The Art of Computer Science"); w.close(); // 2. query String querystr = args.length > 0 ? args[0] : "lucene"; // the "title" arg specifies the default field to use // when no field is explicitly specified in the query. Query q = new QueryParser(Version.LUCENE_35, "title", analyzer).parse(querystr); // 3. search int hitsPerPage = 10; IndexReader reader = IndexReader.open(index); IndexSearcher searcher = new IndexSearcher(reader); TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true); searcher.search(q, collector); ScoreDoc[] hits = collector.topDocs().scoreDocs; // 4. display results System.out.println("Found " + hits.length + " hits."); for (int i = 0; i < hits.length; ++i) { int docId = hits[i].doc; Document d = searcher.doc(docId); System.out.println((i + 1) + ". " + d.get("title")); } // searcher can only be closed when there // is no need to access the documents any more. searcher.close(); }
public void testTimeLimitingCollector() throws Exception { Directory dir = TestUtil.getBookIndexDirectory(); IndexSearcher searcher = new IndexSearcher(dir); Query q = new MatchAllDocsQuery(); int numAllBooks = TestUtil.hitCount(searcher, q); TopScoreDocCollector topDocs = TopScoreDocCollector.create(10, false); Collector collector = new TimeLimitingCollector( topDocs, // #A 1000); // #A try { searcher.search(q, collector); assertEquals(numAllBooks, topDocs.getTotalHits()); // #B } catch (TimeExceededException tee) { // #C System.out.println("Too much time taken."); // #C } // #C searcher.close(); dir.close(); }
@Override public TopDocs topDocs(SearchContext context, FetchSubPhase.HitContext hitContext) throws IOException { final String field; final String term; if (isParentHit(hitContext.hit())) { field = ParentFieldMapper.NAME; term = Uid.createUid(hitContext.hit().type(), hitContext.hit().id()); } else if (isChildHit(hitContext.hit())) { field = UidFieldMapper.NAME; SearchHitField parentField = hitContext.hit().field(ParentFieldMapper.NAME); if (parentField != null) { term = parentField.getValue(); } else { SingleFieldsVisitor fieldsVisitor = new SingleFieldsVisitor(ParentFieldMapper.NAME); hitContext.reader().document(hitContext.docId(), fieldsVisitor); if (fieldsVisitor.fields().isEmpty()) { return Lucene.EMPTY_TOP_DOCS; } term = (String) fieldsVisitor.fields().get(ParentFieldMapper.NAME).get(0); } } else { return Lucene.EMPTY_TOP_DOCS; } // Only include docs that have the current hit as parent Filter filter = new TermFilter(new Term(field, term)); // Only include docs that have this inner hits type Filter typeFilter = documentMapper.typeFilter(); if (size() == 0) { TotalHitCountCollector collector = new TotalHitCountCollector(); context .searcher() .search( new XFilteredQuery(query, new AndFilter(Arrays.asList(filter, typeFilter))), collector); return new TopDocs(collector.getTotalHits(), Lucene.EMPTY_SCORE_DOCS, 0); } else { int topN = from() + size(); TopDocsCollector topDocsCollector; if (sort() != null) { topDocsCollector = TopFieldCollector.create(sort(), topN, true, trackScores(), trackScores(), false); } else { topDocsCollector = TopScoreDocCollector.create(topN, false); } context .searcher() .search( new XFilteredQuery(query, new AndFilter(Arrays.asList(filter, typeFilter))), topDocsCollector); return topDocsCollector.topDocs(from(), size()); } }
/** * The main search method * * @param query * @return * @throws ParseException * @throws IOException * @throws URISyntaxException */ public List<AppType> search(String query) throws ParseException, IOException, URISyntaxException { Query q = new QueryParser(Version.LUCENE_40, "body", analyzer).parse(query); logger.info(q.toString()); int hitsPerPage = 10; DirectoryReader reader = DirectoryReader.open(dir); IndexSearcher searcher = new IndexSearcher(reader); TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true); searcher.search(q, collector); ScoreDoc[] hits = collector.topDocs().scoreDocs; // Got results here logger.info("# score docs = " + hits.length); ArrayList<AppType> results = new ArrayList<AppType>(); for (int i = 0; i < hits.length; ++i) { int docId = hits[i].doc; Document d = searcher.doc(docId); results.add(new AppType(d.get("name"), d.get("body"), d.get("url"))); logger.info("collecting result"); } return results; }
public void doSearch(String queryStr) throws ParseException, IOException, org.apache.lucene.queryparser.classic.ParseException { Query query = parser.parse(queryStr); // 按照parse方式进行查询 TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true); searcher.search(query, collector); ScoreDoc[] hits = collector.topDocs().scoreDocs; // 评分定义 for (ScoreDoc doc : hits) { Document d = searcher.doc(doc.doc); // 按照评分输出 System.out.println( "[" + doc.doc + "]:" + d.get("title") + ",[" + d.get("pubTime") + "]" + ",[" + d.get("description") + "]"); } }
/** * Search with facets through the {@link AdaptiveFacetsAccumulator} * * @param indexDir Directory of the search index. * @param taxoDir Directory of the taxonomy index. * @throws Exception on error (no detailed exception handling here for sample simplicity * @return facet results */ public static List<FacetResult> searchWithFacets(Directory indexDir, Directory taxoDir) throws Exception { // prepare index reader and taxonomy. TaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); IndexReader indexReader = DirectoryReader.open(indexDir); // prepare searcher to search against IndexSearcher searcher = new IndexSearcher(indexReader); // faceted search is working in 2 steps: // 1. collect matching documents // 2. aggregate facets for collected documents and // generate the requested faceted results from the aggregated facets // step 1: collect matching documents into a collector Query q = new TermQuery(new Term(SimpleUtils.TEXT, "white")); ExampleUtils.log("Query: " + q); // regular collector for scoring matched documents TopScoreDocCollector topDocsCollector = TopScoreDocCollector.create(10, true); // docids collector for guiding facets accumulation (scoring disabled) ScoredDocIdCollector docIdsCollecor = ScoredDocIdCollector.create(indexReader.maxDoc(), false); // Faceted search parameters indicate which facets are we interested in FacetSearchParams facetSearchParams = new FacetSearchParams(); facetSearchParams.addFacetRequest(new CountFacetRequest(new CategoryPath("root", "a"), 10)); // search, into both collectors. note: in case only facets accumulation // is required, the topDocCollector part can be totally discarded searcher.search(q, MultiCollector.wrap(topDocsCollector, docIdsCollecor)); // Obtain facets results and print them AdaptiveFacetsAccumulator accumulator = new AdaptiveFacetsAccumulator(facetSearchParams, indexReader, taxo); List<FacetResult> res = accumulator.accumulate(docIdsCollecor.getScoredDocIDs()); int i = 0; for (FacetResult facetResult : res) { ExampleUtils.log("Res " + (i++) + ": " + facetResult); } // we're done, close the index reader and the taxonomy. indexReader.close(); taxo.close(); return res; }
@Override public TopDocs topDocs(SearchContext context, FetchSubPhase.HitContext hitContext) throws IOException { Filter rawParentFilter; if (parentObjectMapper == null) { rawParentFilter = NonNestedDocsFilter.INSTANCE; } else { rawParentFilter = parentObjectMapper.nestedTypeFilter(); } FixedBitSetFilter parentFilter = context.fixedBitSetFilterCache().getFixedBitSetFilter(rawParentFilter); Filter childFilter = context.filterCache().cache(childObjectMapper.nestedTypeFilter()); Query q = new XFilteredQuery( query, new NestedChildrenFilter(parentFilter, childFilter, hitContext)); if (size() == 0) { TotalHitCountCollector collector = new TotalHitCountCollector(); context.searcher().search(q, collector); return new TopDocs(collector.getTotalHits(), Lucene.EMPTY_SCORE_DOCS, 0); } else { int topN = from() + size(); TopDocsCollector topDocsCollector; if (sort() != null) { try { topDocsCollector = TopFieldCollector.create(sort(), topN, true, trackScores(), trackScores(), true); } catch (IOException e) { throw ExceptionsHelper.convertToElastic(e); } } else { topDocsCollector = TopScoreDocCollector.create(topN, true); } context.searcher().search(q, topDocsCollector); return topDocsCollector.topDocs(from(), size()); } }
@Test public void testIndexGuidedDecisionTableBRLFragmentActions() throws IOException, InterruptedException { // Add test files final Path path = basePath.resolve("dtable1.gdst"); final GuidedDecisionTable52 model = GuidedDecisionTableFactory.makeTableWithBRLFragmentActionCol( "org.drools.workbench.screens.guided.dtable.backend.server.indexing", new ArrayList<Import>() { { add( new Import( "org.drools.workbench.screens.guided.dtable.backend.server.indexing.classes.Applicant")); add( new Import( "org.drools.workbench.screens.guided.dtable.backend.server.indexing.classes.Mortgage")); } }, "dtable1"); final String xml = GuidedDTXMLPersistence.getInstance().marshal(model); ioService().write(path, xml); Thread.sleep( 5000); // wait for events to be consumed from jgit -> (notify changes -> watcher -> index) // -> lucene index final Index index = getConfig() .getIndexManager() .get(org.kie.uberfire.metadata.io.KObjectUtil.toKCluster(basePath.getFileSystem())); { final IndexSearcher searcher = ((LuceneIndex) index).nrtSearcher(); final TopScoreDocCollector collector = TopScoreDocCollector.create(10, true); final Query query = new QueryBuilder() .addTerm( new ValueTypeIndexTerm( "org.drools.workbench.screens.guided.dtable.backend.server.indexing.classes.Applicant")) .build(); searcher.search(query, collector); final ScoreDoc[] hits = collector.topDocs().scoreDocs; assertEquals(1, hits.length); final List<KObject> results = new ArrayList<KObject>(); for (int i = 0; i < hits.length; i++) { results.add(KObjectUtil.toKObject(searcher.doc(hits[i].doc))); } assertContains(results, path); ((LuceneIndex) index).nrtRelease(searcher); } { final IndexSearcher searcher = ((LuceneIndex) index).nrtSearcher(); final TopScoreDocCollector collector = TopScoreDocCollector.create(10, true); final Query query = new QueryBuilder() .addTerm( new ValueTypeIndexTerm( "org.drools.workbench.screens.guided.dtable.backend.server.indexing.classes.Mortgage")) .build(); searcher.search(query, collector); final ScoreDoc[] hits = collector.topDocs().scoreDocs; assertEquals(1, hits.length); final List<KObject> results = new ArrayList<KObject>(); for (int i = 0; i < hits.length; i++) { results.add(KObjectUtil.toKObject(searcher.doc(hits[i].doc))); } assertContains(results, path); ((LuceneIndex) index).nrtRelease(searcher); } }
@Test public void testRandom() throws Exception { Directory directory = newDirectory(); RandomIndexWriter indexWriter = new RandomIndexWriter(random(), directory); int numUniqueChildValues = 1 + random().nextInt(TEST_NIGHTLY ? 6000 : 600); String[] childValues = new String[numUniqueChildValues]; for (int i = 0; i < numUniqueChildValues; i++) { childValues[i] = Integer.toString(i); } int childDocId = 0; int numParentDocs = 1 + random().nextInt(TEST_NIGHTLY ? 20000 : 1000); ObjectObjectOpenHashMap<String, NavigableMap<String, FloatArrayList>> childValueToParentIds = new ObjectObjectOpenHashMap<String, NavigableMap<String, FloatArrayList>>(); for (int parentDocId = 0; parentDocId < numParentDocs; parentDocId++) { boolean markParentAsDeleted = rarely(); String parent = Integer.toString(parentDocId); Document document = new Document(); document.add( new StringField(UidFieldMapper.NAME, Uid.createUid("parent", parent), Field.Store.YES)); document.add(new StringField(TypeFieldMapper.NAME, "parent", Field.Store.NO)); if (markParentAsDeleted) { document.add(new StringField("delete", "me", Field.Store.NO)); } indexWriter.addDocument(document); int numChildDocs = random().nextInt(TEST_NIGHTLY ? 100 : 25); for (int i = 0; i < numChildDocs; i++) { boolean markChildAsDeleted = rarely(); String childValue = childValues[random().nextInt(childValues.length)]; document = new Document(); document.add( new StringField( UidFieldMapper.NAME, Uid.createUid("child", Integer.toString(childDocId)), Field.Store.NO)); document.add(new StringField(TypeFieldMapper.NAME, "child", Field.Store.NO)); document.add( new StringField( ParentFieldMapper.NAME, Uid.createUid("parent", parent), Field.Store.NO)); document.add(new StringField("field1", childValue, Field.Store.NO)); if (markChildAsDeleted) { document.add(new StringField("delete", "me", Field.Store.NO)); } indexWriter.addDocument(document); if (!markChildAsDeleted) { NavigableMap<String, FloatArrayList> parentIdToChildScores; if (childValueToParentIds.containsKey(childValue)) { parentIdToChildScores = childValueToParentIds.lget(); } else { childValueToParentIds.put( childValue, parentIdToChildScores = new TreeMap<String, FloatArrayList>()); } if (!markParentAsDeleted) { FloatArrayList childScores = parentIdToChildScores.get(parent); if (childScores == null) { parentIdToChildScores.put(parent, childScores = new FloatArrayList()); } childScores.add(1f); } } } } // Delete docs that are marked to be deleted. indexWriter.deleteDocuments(new Term("delete", "me")); indexWriter.close(); IndexReader indexReader = DirectoryReader.open(directory); IndexSearcher searcher = new IndexSearcher(indexReader); Engine.Searcher engineSearcher = new Engine.SimpleSearcher(ChildrenQueryTests.class.getSimpleName(), searcher); ((TestSearchContext) SearchContext.current()) .setSearcher(new ContextIndexSearcher(SearchContext.current(), engineSearcher)); TermFilter parentFilter = new TermFilter(new Term(TypeFieldMapper.NAME, "parent")); for (String childValue : childValues) { Query childQuery = new ConstantScoreQuery(new TermQuery(new Term("field1", childValue))); int shortCircuitParentDocSet = random().nextInt(numParentDocs); ScoreType scoreType = ScoreType.values()[random().nextInt(ScoreType.values().length)]; Query query = new ChildrenQuery( "parent", "child", parentFilter, childQuery, scoreType, shortCircuitParentDocSet); BitSetCollector collector = new BitSetCollector(indexReader.maxDoc()); int numHits = 1 + random().nextInt(25); TopScoreDocCollector actualTopDocsCollector = TopScoreDocCollector.create(numHits, false); searcher.search(query, MultiCollector.wrap(collector, actualTopDocsCollector)); FixedBitSet actualResult = collector.getResult(); FixedBitSet expectedResult = new FixedBitSet(indexReader.maxDoc()); MockScorer mockScorer = new MockScorer(scoreType); TopScoreDocCollector expectedTopDocsCollector = TopScoreDocCollector.create(numHits, false); expectedTopDocsCollector.setScorer(mockScorer); if (childValueToParentIds.containsKey(childValue)) { AtomicReader slowAtomicReader = SlowCompositeReaderWrapper.wrap(indexReader); Terms terms = slowAtomicReader.terms(UidFieldMapper.NAME); if (terms != null) { NavigableMap<String, FloatArrayList> parentIdToChildScores = childValueToParentIds.lget(); TermsEnum termsEnum = terms.iterator(null); DocsEnum docsEnum = null; for (Map.Entry<String, FloatArrayList> entry : parentIdToChildScores.entrySet()) { TermsEnum.SeekStatus seekStatus = termsEnum.seekCeil(Uid.createUidAsBytes("parent", entry.getKey())); if (seekStatus == TermsEnum.SeekStatus.FOUND) { docsEnum = termsEnum.docs(slowAtomicReader.getLiveDocs(), docsEnum, DocsEnum.FLAG_NONE); expectedResult.set(docsEnum.nextDoc()); mockScorer.scores = entry.getValue(); expectedTopDocsCollector.collect(docsEnum.docID()); } else if (seekStatus == TermsEnum.SeekStatus.END) { break; } } } } assertBitSet(actualResult, expectedResult, searcher); assertTopDocs(actualTopDocsCollector.topDocs(), expectedTopDocsCollector.topDocs()); } indexReader.close(); directory.close(); }
public static String[][] buscar( String termino, String campo1, String campo2, String tabla, int hitsPerPage, int crear) throws IOException, SQLException, ParseException { StandardAnalyzer analyzer = new StandardAnalyzer(); // Directory index = FSDirectory.open(Paths.get("INDICE")); Directory index = new RAMDirectory(); Connection conn = null; Statement stmt = null; ResultSet rs = null; rs = conectar(conn, stmt, rs, campo1, campo2, tabla); if (crear == 1) { /*Connection conn = null; Statement stmt = null; ResultSet rs = null; rs = conectar(conn, stmt, rs, campo1, campo2, tabla);*/ IndexWriterConfig config = new IndexWriterConfig(analyzer); try (IndexWriter w = new IndexWriter(index, config)) { while (rs.next()) { String comentario = rs.getString(campo2); String identificador = rs.getString(campo1); addDoc(w, identificador, comentario, campo1, campo2); } /*Cierre del while*/ w.close(); } /*Cierre del try*/ } Query q = new QueryParser(campo2, analyzer).parse(termino); ScoreDoc[] hits; String[][] matriz; try (IndexReader reader = DirectoryReader.open(index)) { IndexSearcher searcher = new IndexSearcher(reader); TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage); searcher.search(q, collector); hits = collector.topDocs().scoreDocs; matriz = new String[hits.length][3]; for (int i = 0; i < hits.length; i++) { /*Recorremos cada uno de los documentos*/ int docId = hits[i].doc; Document d = searcher.doc(docId); /*Buscamos el documento*/ matriz[i][0] = d.get(campo1); matriz[i][1] = d.get(campo2); String resultado = ""; if (tabla.equals("imagen")) { /*obtener id desde la tabla imagen*/ String consulta = "Select id_usuario from imagen where id_imagen = " + d.get(campo1) + ";"; resultado = ejecutarConsulta(conn, stmt, rs, consulta, "id_usuario"); } else { if (tabla.equals("comentario")) { /*Obtener id desde la tabla comentario*/ String consulta = "Select id_usuario from comentario where id_comentario = " + d.get(campo1) + ";"; resultado = ejecutarConsulta(conn, stmt, rs, consulta, "id_usuario"); } } String puntajeFinal = Integer.toString(calculaPuntaje(resultado, conn, stmt, rs)); matriz[i][2] = puntajeFinal; } /*Cierre del for*/ desconectar(rs, stmt, conn); int axl = matriz.length - 1; if (matriz.length != 0) { ordenar(matriz, 0, axl); } /*Cierre if*/ return matriz; } /*Cierre del try*/ } /*Cierre de la funcion buscar*/
@Test public void testRandom() throws Exception { Directory directory = newDirectory(); final Random r = random(); final IndexWriterConfig iwc = LuceneTestCase.newIndexWriterConfig(r, new MockAnalyzer(r)) .setMaxBufferedDocs(IndexWriterConfig.DISABLE_AUTO_FLUSH) .setRAMBufferSizeMB( scaledRandomIntBetween(16, 64)); // we might index a lot - don't go crazy here RandomIndexWriter indexWriter = new RandomIndexWriter(r, directory, iwc); int numUniqueChildValues = scaledRandomIntBetween(100, 2000); String[] childValues = new String[numUniqueChildValues]; for (int i = 0; i < numUniqueChildValues; i++) { childValues[i] = Integer.toString(i); } IntOpenHashSet filteredOrDeletedDocs = new IntOpenHashSet(); int childDocId = 0; int numParentDocs = scaledRandomIntBetween(1, numUniqueChildValues); ObjectObjectOpenHashMap<String, NavigableMap<String, FloatArrayList>> childValueToParentIds = new ObjectObjectOpenHashMap<>(); for (int parentDocId = 0; parentDocId < numParentDocs; parentDocId++) { boolean markParentAsDeleted = rarely(); boolean filterMe = rarely(); String parent = Integer.toString(parentDocId); Document document = new Document(); document.add( new StringField(UidFieldMapper.NAME, Uid.createUid("parent", parent), Field.Store.YES)); document.add(new StringField(TypeFieldMapper.NAME, "parent", Field.Store.NO)); if (markParentAsDeleted) { filteredOrDeletedDocs.add(parentDocId); document.add(new StringField("delete", "me", Field.Store.NO)); } if (filterMe) { filteredOrDeletedDocs.add(parentDocId); document.add(new StringField("filter", "me", Field.Store.NO)); } indexWriter.addDocument(document); int numChildDocs = scaledRandomIntBetween(0, 100); for (int i = 0; i < numChildDocs; i++) { boolean markChildAsDeleted = rarely(); String childValue = childValues[random().nextInt(childValues.length)]; document = new Document(); document.add( new StringField( UidFieldMapper.NAME, Uid.createUid("child", Integer.toString(childDocId++)), Field.Store.NO)); document.add(new StringField(TypeFieldMapper.NAME, "child", Field.Store.NO)); document.add( new StringField( ParentFieldMapper.NAME, Uid.createUid("parent", parent), Field.Store.NO)); document.add(new StringField("field1", childValue, Field.Store.NO)); if (markChildAsDeleted) { document.add(new StringField("delete", "me", Field.Store.NO)); } indexWriter.addDocument(document); if (!markChildAsDeleted) { NavigableMap<String, FloatArrayList> parentIdToChildScores; if (childValueToParentIds.containsKey(childValue)) { parentIdToChildScores = childValueToParentIds.lget(); } else { childValueToParentIds.put(childValue, parentIdToChildScores = new TreeMap<>()); } if (!markParentAsDeleted && !filterMe) { FloatArrayList childScores = parentIdToChildScores.get(parent); if (childScores == null) { parentIdToChildScores.put(parent, childScores = new FloatArrayList()); } childScores.add(1f); } } } } // Delete docs that are marked to be deleted. indexWriter.deleteDocuments(new Term("delete", "me")); indexWriter.commit(); IndexReader indexReader = DirectoryReader.open(directory); IndexSearcher searcher = new IndexSearcher(indexReader); Engine.Searcher engineSearcher = new Engine.Searcher(ChildrenQueryTests.class.getSimpleName(), searcher); ((TestSearchContext) SearchContext.current()) .setSearcher(new ContextIndexSearcher(SearchContext.current(), engineSearcher)); int max = numUniqueChildValues / 4; for (int i = 0; i < max; i++) { // Simulate a parent update if (random().nextBoolean()) { final int numberOfUpdatableParents = numParentDocs - filteredOrDeletedDocs.size(); int numberOfUpdates = RandomInts.randomIntBetween( random(), 0, Math.min(numberOfUpdatableParents, TEST_NIGHTLY ? 25 : 5)); for (int j = 0; j < numberOfUpdates; j++) { int parentId; do { parentId = random().nextInt(numParentDocs); } while (filteredOrDeletedDocs.contains(parentId)); String parentUid = Uid.createUid("parent", Integer.toString(parentId)); indexWriter.deleteDocuments(new Term(UidFieldMapper.NAME, parentUid)); Document document = new Document(); document.add(new StringField(UidFieldMapper.NAME, parentUid, Field.Store.YES)); document.add(new StringField(TypeFieldMapper.NAME, "parent", Field.Store.NO)); indexWriter.addDocument(document); } indexReader.close(); indexReader = DirectoryReader.open(indexWriter.w, true); searcher = new IndexSearcher(indexReader); engineSearcher = new Engine.Searcher(ChildrenConstantScoreQueryTests.class.getSimpleName(), searcher); ((TestSearchContext) SearchContext.current()) .setSearcher(new ContextIndexSearcher(SearchContext.current(), engineSearcher)); } String childValue = childValues[random().nextInt(numUniqueChildValues)]; int shortCircuitParentDocSet = random().nextInt(numParentDocs); ScoreType scoreType = ScoreType.values()[random().nextInt(ScoreType.values().length)]; // leave min/max set to 0 half the time int minChildren = random().nextInt(2) * scaledRandomIntBetween(0, 110); int maxChildren = random().nextInt(2) * scaledRandomIntBetween(minChildren, 110); QueryBuilder queryBuilder = hasChildQuery("child", constantScoreQuery(termQuery("field1", childValue))) .scoreType(scoreType.name().toLowerCase(Locale.ENGLISH)) .minChildren(minChildren) .maxChildren(maxChildren) .setShortCircuitCutoff(shortCircuitParentDocSet); // Using a FQ, will invoke / test the Scorer#advance(..) and also let the Weight#scorer not // get live docs as acceptedDocs queryBuilder = filteredQuery(queryBuilder, notFilter(termFilter("filter", "me"))); Query query = parseQuery(queryBuilder); BitSetCollector collector = new BitSetCollector(indexReader.maxDoc()); int numHits = 1 + random().nextInt(25); TopScoreDocCollector actualTopDocsCollector = TopScoreDocCollector.create(numHits); searcher.search(query, MultiCollector.wrap(collector, actualTopDocsCollector)); FixedBitSet actualResult = collector.getResult(); FixedBitSet expectedResult = new FixedBitSet(indexReader.maxDoc()); TopScoreDocCollector expectedTopDocsCollector = TopScoreDocCollector.create(numHits); if (childValueToParentIds.containsKey(childValue)) { LeafReader slowLeafReader = SlowCompositeReaderWrapper.wrap(indexReader); final FloatArrayList[] scores = new FloatArrayList[slowLeafReader.maxDoc()]; Terms terms = slowLeafReader.terms(UidFieldMapper.NAME); if (terms != null) { NavigableMap<String, FloatArrayList> parentIdToChildScores = childValueToParentIds.lget(); TermsEnum termsEnum = terms.iterator(null); DocsEnum docsEnum = null; for (Map.Entry<String, FloatArrayList> entry : parentIdToChildScores.entrySet()) { int count = entry.getValue().elementsCount; if (count >= minChildren && (maxChildren == 0 || count <= maxChildren)) { TermsEnum.SeekStatus seekStatus = termsEnum.seekCeil(Uid.createUidAsBytes("parent", entry.getKey())); if (seekStatus == TermsEnum.SeekStatus.FOUND) { docsEnum = termsEnum.docs(slowLeafReader.getLiveDocs(), docsEnum, DocsEnum.FLAG_NONE); expectedResult.set(docsEnum.nextDoc()); scores[docsEnum.docID()] = new FloatArrayList(entry.getValue()); } else if (seekStatus == TermsEnum.SeekStatus.END) { break; } } } } MockScorer mockScorer = new MockScorer(scoreType); final LeafCollector leafCollector = expectedTopDocsCollector.getLeafCollector(slowLeafReader.getContext()); leafCollector.setScorer(mockScorer); for (int doc = expectedResult.nextSetBit(0); doc < slowLeafReader.maxDoc(); doc = doc + 1 >= expectedResult.length() ? DocIdSetIterator.NO_MORE_DOCS : expectedResult.nextSetBit(doc + 1)) { mockScorer.scores = scores[doc]; leafCollector.collect(doc); } } assertBitSet(actualResult, expectedResult, searcher); assertTopDocs(actualTopDocsCollector.topDocs(), expectedTopDocsCollector.topDocs()); } indexWriter.close(); indexReader.close(); directory.close(); }
private void executeRandomJoin( boolean multipleValuesPerDocument, int maxIndexIter, int maxSearchIter, int numberOfDocumentsToIndex) throws Exception { for (int indexIter = 1; indexIter <= maxIndexIter; indexIter++) { if (VERBOSE) { System.out.println("indexIter=" + indexIter); } Directory dir = newDirectory(); RandomIndexWriter w = new RandomIndexWriter( random(), dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random(), MockTokenizer.KEYWORD, false)) .setMergePolicy(newLogMergePolicy())); final boolean scoreDocsInOrder = TestJoinUtil.random().nextBoolean(); IndexIterationContext context = createContext(numberOfDocumentsToIndex, w, multipleValuesPerDocument, scoreDocsInOrder); IndexReader topLevelReader = w.getReader(); w.close(); for (int searchIter = 1; searchIter <= maxSearchIter; searchIter++) { if (VERBOSE) { System.out.println("searchIter=" + searchIter); } IndexSearcher indexSearcher = newSearcher(topLevelReader); int r = random().nextInt(context.randomUniqueValues.length); boolean from = context.randomFrom[r]; String randomValue = context.randomUniqueValues[r]; FixedBitSet expectedResult = createExpectedResult(randomValue, from, indexSearcher.getIndexReader(), context); final Query actualQuery = new TermQuery(new Term("value", randomValue)); if (VERBOSE) { System.out.println("actualQuery=" + actualQuery); } final ScoreMode scoreMode = ScoreMode.values()[random().nextInt(ScoreMode.values().length)]; if (VERBOSE) { System.out.println("scoreMode=" + scoreMode); } final Query joinQuery; if (from) { joinQuery = JoinUtil.createJoinQuery( "from", multipleValuesPerDocument, "to", actualQuery, indexSearcher, scoreMode); } else { joinQuery = JoinUtil.createJoinQuery( "to", multipleValuesPerDocument, "from", actualQuery, indexSearcher, scoreMode); } if (VERBOSE) { System.out.println("joinQuery=" + joinQuery); } // Need to know all documents that have matches. TopDocs doesn't give me that and then I'd // be also testing TopDocsCollector... final FixedBitSet actualResult = new FixedBitSet(indexSearcher.getIndexReader().maxDoc()); final TopScoreDocCollector topScoreDocCollector = TopScoreDocCollector.create(10, false); indexSearcher.search( joinQuery, new Collector() { int docBase; @Override public void collect(int doc) throws IOException { actualResult.set(doc + docBase); topScoreDocCollector.collect(doc); } @Override public void setNextReader(AtomicReaderContext context) { docBase = context.docBase; topScoreDocCollector.setNextReader(context); } @Override public void setScorer(Scorer scorer) throws IOException { topScoreDocCollector.setScorer(scorer); } @Override public boolean acceptsDocsOutOfOrder() { return scoreDocsInOrder; } }); // Asserting bit set... if (VERBOSE) { System.out.println("expected cardinality:" + expectedResult.cardinality()); DocIdSetIterator iterator = expectedResult.iterator(); for (int doc = iterator.nextDoc(); doc != DocIdSetIterator.NO_MORE_DOCS; doc = iterator.nextDoc()) { System.out.println( String.format( Locale.ROOT, "Expected doc[%d] with id value %s", doc, indexSearcher.doc(doc).get("id"))); } System.out.println("actual cardinality:" + actualResult.cardinality()); iterator = actualResult.iterator(); for (int doc = iterator.nextDoc(); doc != DocIdSetIterator.NO_MORE_DOCS; doc = iterator.nextDoc()) { System.out.println( String.format( Locale.ROOT, "Actual doc[%d] with id value %s", doc, indexSearcher.doc(doc).get("id"))); } } assertEquals(expectedResult, actualResult); // Asserting TopDocs... TopDocs expectedTopDocs = createExpectedTopDocs(randomValue, from, scoreMode, context); TopDocs actualTopDocs = topScoreDocCollector.topDocs(); assertEquals(expectedTopDocs.totalHits, actualTopDocs.totalHits); assertEquals(expectedTopDocs.scoreDocs.length, actualTopDocs.scoreDocs.length); if (scoreMode == ScoreMode.None) { continue; } assertEquals(expectedTopDocs.getMaxScore(), actualTopDocs.getMaxScore(), 0.0f); for (int i = 0; i < expectedTopDocs.scoreDocs.length; i++) { if (VERBOSE) { System.out.printf( Locale.ENGLISH, "Expected doc: %d | Actual doc: %d\n", expectedTopDocs.scoreDocs[i].doc, actualTopDocs.scoreDocs[i].doc); System.out.printf( Locale.ENGLISH, "Expected score: %f | Actual score: %f\n", expectedTopDocs.scoreDocs[i].score, actualTopDocs.scoreDocs[i].score); } assertEquals(expectedTopDocs.scoreDocs[i].doc, actualTopDocs.scoreDocs[i].doc); assertEquals(expectedTopDocs.scoreDocs[i].score, actualTopDocs.scoreDocs[i].score, 0.0f); Explanation explanation = indexSearcher.explain(joinQuery, expectedTopDocs.scoreDocs[i].doc); assertEquals(expectedTopDocs.scoreDocs[i].score, explanation.getValue(), 0.0f); } } topLevelReader.close(); dir.close(); } }
@Test public void testIndexGuidedScoreCard() throws IOException, InterruptedException { // Add test files final Path path1 = basePath.resolve("scorecard1.scgd"); final ScoreCardModel model1 = GuidedScoreCardFactory.makeScoreCardWithCharacteristics( "org.drools.workbench.screens.guided.scorecard.backend.server.indexing", new ArrayList<Import>() { { add( new Import( "org.drools.workbench.screens.guided.scorecard.backend.server.indexing.classes.Applicant")); add( new Import( "org.drools.workbench.screens.guided.scorecard.backend.server.indexing.classes.Mortgage")); } }, "scorecard1"); final String xml1 = GuidedScoreCardXMLPersistence.getInstance().marshal(model1); ioService().write(path1, xml1); final Path path2 = basePath.resolve("scorecard2.scgd"); final ScoreCardModel model2 = GuidedScoreCardFactory.makeScoreCardWithoutCharacteristics( "org.drools.workbench.screens.guided.scorecard.backend.server.indexing", new ArrayList<Import>() { { add( new Import( "org.drools.workbench.screens.guided.scorecard.backend.server.indexing.classes.Applicant")); add( new Import( "org.drools.workbench.screens.guided.scorecard.backend.server.indexing.classes.Mortgage")); } }, "scorecard2"); final String xml2 = GuidedScoreCardXMLPersistence.getInstance().marshal(model2); ioService().write(path2, xml2); final Path path3 = basePath.resolve("scorecard3.scgd"); final ScoreCardModel model3 = GuidedScoreCardFactory.makeEmptyScoreCard( "org.drools.workbench.screens.guided.scorecard.backend.server.indexing", "scorecard3"); final String xml3 = GuidedScoreCardXMLPersistence.getInstance().marshal(model3); ioService().write(path3, xml3); Thread.sleep( 5000); // wait for events to be consumed from jgit -> (notify changes -> watcher -> index) // -> lucene index final Index index = getConfig() .getIndexManager() .get(org.uberfire.ext.metadata.io.KObjectUtil.toKCluster(basePath.getFileSystem())); // Score Cards using // org.drools.workbench.screens.guided.scorecard.backend.server.indexing.classes.Applicant { final IndexSearcher searcher = ((LuceneIndex) index).nrtSearcher(); final TopScoreDocCollector collector = TopScoreDocCollector.create(10, true); final Query query = new BasicQueryBuilder() .addTerm( new ValueTypeIndexTerm( "org.drools.workbench.screens.guided.scorecard.backend.server.indexing.classes.Applicant")) .build(); searcher.search(query, collector); final ScoreDoc[] hits = collector.topDocs().scoreDocs; assertEquals(2, hits.length); final List<KObject> results = new ArrayList<KObject>(); for (int i = 0; i < hits.length; i++) { results.add(KObjectUtil.toKObject(searcher.doc(hits[i].doc))); } assertContains(results, path1); assertContains(results, path2); ((LuceneIndex) index).nrtRelease(searcher); } // Score Cards using // org.drools.workbench.screens.guided.scorecard.backend.server.indexing.classes.Mortgage { final IndexSearcher searcher = ((LuceneIndex) index).nrtSearcher(); final TopScoreDocCollector collector = TopScoreDocCollector.create(10, true); final Query query = new BasicQueryBuilder() .addTerm( new ValueTypeIndexTerm( "org.drools.workbench.screens.guided.scorecard.backend.server.indexing.classes.Mortgage")) .build(); searcher.search(query, collector); final ScoreDoc[] hits = collector.topDocs().scoreDocs; assertEquals(1, hits.length); final List<KObject> results = new ArrayList<KObject>(); for (int i = 0; i < hits.length; i++) { results.add(KObjectUtil.toKObject(searcher.doc(hits[i].doc))); } assertContains(results, path1); ((LuceneIndex) index).nrtRelease(searcher); } // Score Cards using // org.drools.workbench.screens.guided.scorecard.backend.server.indexing.classes.Mortgage#amount { final IndexSearcher searcher = ((LuceneIndex) index).nrtSearcher(); final TopScoreDocCollector collector = TopScoreDocCollector.create(10, true); final Query query = new BasicQueryBuilder() .addTerm( new ValueTypeIndexTerm( "org.drools.workbench.screens.guided.scorecard.backend.server.indexing.classes.Mortgage")) .addTerm(new ValueFieldIndexTerm("amount")) .build(); searcher.search(query, collector); final ScoreDoc[] hits = collector.topDocs().scoreDocs; assertEquals(1, hits.length); final List<KObject> results = new ArrayList<KObject>(); for (int i = 0; i < hits.length; i++) { results.add(KObjectUtil.toKObject(searcher.doc(hits[i].doc))); } assertContains(results, path1); ((LuceneIndex) index).nrtRelease(searcher); } // Score Cards using java.lang.Integer { final IndexSearcher searcher = ((LuceneIndex) index).nrtSearcher(); final TopScoreDocCollector collector = TopScoreDocCollector.create(10, true); final Query query = new BasicQueryBuilder().addTerm(new ValueTypeIndexTerm("java.lang.Integer")).build(); searcher.search(query, collector); final ScoreDoc[] hits = collector.topDocs().scoreDocs; assertEquals(2, hits.length); final List<KObject> results = new ArrayList<KObject>(); for (int i = 0; i < hits.length; i++) { results.add(KObjectUtil.toKObject(searcher.doc(hits[i].doc))); } assertContains(results, path1); assertContains(results, path2); ((LuceneIndex) index).nrtRelease(searcher); } }
@Test public void testIndexDrlRuleMultipleTypes() throws IOException, InterruptedException { // Add test files final Path path1 = basePath.resolve("drl3.rdrl"); final String drl1 = loadText("drl3.rdrl"); ioService().write(path1, drl1); final Path path2 = basePath.resolve("drl4.rdrl"); final String drl2 = loadText("drl4.rdrl"); ioService().write(path2, drl2); Thread.sleep( 5000); // wait for events to be consumed from jgit -> (notify changes -> watcher -> index) // -> lucene index final Index index = getConfig() .getIndexManager() .get(org.kie.uberfire.metadata.io.KObjectUtil.toKCluster(basePath.getFileSystem())); { final IndexSearcher searcher = ((LuceneIndex) index).nrtSearcher(); final TopScoreDocCollector collector = TopScoreDocCollector.create(10, true); final Query query = new QueryBuilder() .addTerm( new ValueTypeIndexTerm( "org.drools.workbench.screens.guided.rule.backend.server.indexing.classes.Applicant")) .build(); searcher.search(query, collector); final ScoreDoc[] hits = collector.topDocs().scoreDocs; assertEquals(2, hits.length); final List<KObject> results = new ArrayList<KObject>(); for (int i = 0; i < hits.length; i++) { results.add(KObjectUtil.toKObject(searcher.doc(hits[i].doc))); } assertContains(results, path1); assertContains(results, path2); ((LuceneIndex) index).nrtRelease(searcher); } { final IndexSearcher searcher = ((LuceneIndex) index).nrtSearcher(); final TopScoreDocCollector collector = TopScoreDocCollector.create(10, true); final Query query = new QueryBuilder() .addTerm( new ValueTypeIndexTerm( "org.drools.workbench.screens.guided.rule.backend.server.indexing.classes.Mortgage")) .build(); searcher.search(query, collector); final ScoreDoc[] hits = collector.topDocs().scoreDocs; assertEquals(1, hits.length); final List<KObject> results = new ArrayList<KObject>(); for (int i = 0; i < hits.length; i++) { results.add(KObjectUtil.toKObject(searcher.doc(hits[i].doc))); } assertContains(results, path2); ((LuceneIndex) index).nrtRelease(searcher); } }
public static void main(String[] args) throws IOException, ParseException { // 0. Specify the analyzer for tokenizing text. // The same analyzer should be used for indexing and searching StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_40); // 1. create the index Directory index = new RAMDirectory(); IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_40, analyzer); IndexWriter w = new IndexWriter(index, config); addDoc(w, "Lucene in Action", "193398817"); addDoc(w, "Lucene for Dummies", "55320055Z"); addDoc(w, "Managing Gigabytes", "55063554A"); addDoc(w, "The Art of Computer Science", "9900333X"); w.close(); // 2. query Query q = null; String query = "lucene"; String[] fields = {"title", "isbn"}; BooleanClause.Occur[] clauses = {BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD}; try { q = MultiFieldQueryParser.parse(Version.LUCENE_40, query, fields, clauses, analyzer); } catch (org.apache.lucene.queryparser.classic.ParseException e) { e.printStackTrace(); } // 3. search int hitsPerPage = 10; IndexReader reader = DirectoryReader.open(index); IndexSearcher searcher = new IndexSearcher(reader); TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true); searcher.search(q, collector); ScoreDoc[] hits = collector.topDocs().scoreDocs; // 4. display results System.out.println("Found " + hits.length + " hits."); for (int i = 0; i < hits.length; ++i) { int docId = hits[i].doc; Document d = searcher.doc(docId); System.out.println((i + 1) + ". " + d.get("isbn") + "\t" + d.get("title")); } // 分页(实现)-----start int currentpageNum = 2; // 当前页 int pageSize = 1; // 每页显示多少条记录 reader = DirectoryReader.open(index); searcher = new IndexSearcher(reader); collector = TopScoreDocCollector.create(currentpageNum * pageSize, true); // 根据当前页和每页多少,查询出结果 searcher.search(q, collector); TopDocs docs = collector.topDocs(); getResult(searcher, docs, currentpageNum, pageSize); // 分页显示 // 分页(实现)-----end // reader can only be closed when there // is no need to access the documents any more. reader.close(); }
/** * Accumulates groups for the BlockJoinQuery specified by its slot. * * @param slot Search query's slot * @param offset Parent docs offset * @param maxDocsPerGroup Upper bound of documents per group number * @param withinGroupOffset Offset within each group of child docs * @param withinGroupSort Sort criteria within groups * @param fillSortFields Specifies whether to add sort fields or not * @return TopGroups for the query specified by slot * @throws IOException if there is a low-level I/O error */ @SuppressWarnings({"unchecked", "rawtypes"}) private TopGroups<Integer> accumulateGroups( int slot, int offset, int maxDocsPerGroup, int withinGroupOffset, Sort withinGroupSort, boolean fillSortFields) throws IOException { final GroupDocs<Integer>[] groups = new GroupDocs[sortedGroups.length - offset]; final FakeScorer fakeScorer = new FakeScorer(); int totalGroupedHitCount = 0; // System.out.println("slot=" + slot); for (int groupIDX = offset; groupIDX < sortedGroups.length; groupIDX++) { final OneGroup og = sortedGroups[groupIDX]; final int numChildDocs; if (slot == -1 || slot >= og.counts.length) { numChildDocs = 0; } else { numChildDocs = og.counts[slot]; } // Number of documents in group should be bounded to prevent redundant memory allocation final int numDocsInGroup = Math.max(1, Math.min(numChildDocs, maxDocsPerGroup)); // System.out.println("parent doc=" + og.doc + " numChildDocs=" + numChildDocs + " maxDocsPG=" // + maxDocsPerGroup); // At this point we hold all docs w/ in each group, // unsorted; we now sort them: final TopDocsCollector<?> collector; if (withinGroupSort == null) { // System.out.println("sort by score"); // Sort by score if (!trackScores) { throw new IllegalArgumentException( "cannot sort by relevance within group: trackScores=false"); } collector = TopScoreDocCollector.create(numDocsInGroup, true); } else { // Sort by fields collector = TopFieldCollector.create( withinGroupSort, numDocsInGroup, fillSortFields, trackScores, trackMaxScore, true); } collector.setScorer(fakeScorer); collector.setNextReader(og.readerContext); for (int docIDX = 0; docIDX < numChildDocs; docIDX++) { // System.out.println("docIDX=" + docIDX + " vs " + og.docs[slot].length); final int doc = og.docs[slot][docIDX]; fakeScorer.doc = doc; if (trackScores) { fakeScorer.score = og.scores[slot][docIDX]; } collector.collect(doc); } totalGroupedHitCount += numChildDocs; final Object[] groupSortValues; if (fillSortFields) { groupSortValues = new Object[comparators.length]; for (int sortFieldIDX = 0; sortFieldIDX < comparators.length; sortFieldIDX++) { groupSortValues[sortFieldIDX] = comparators[sortFieldIDX].value(og.slot); } } else { groupSortValues = null; } final TopDocs topDocs = collector.topDocs(withinGroupOffset, numDocsInGroup); groups[groupIDX - offset] = new GroupDocs<>( og.score, topDocs.getMaxScore(), numChildDocs, topDocs.scoreDocs, og.doc, groupSortValues); } return new TopGroups<>( new TopGroups<>( sort.getSort(), withinGroupSort == null ? null : withinGroupSort.getSort(), 0, totalGroupedHitCount, groups, maxScore), totalHitCount); }