Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TopFieldCollector;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.util.Version;
import org.opengrok.indexer.analysis.AbstractAnalyzer;
Expand All @@ -66,6 +69,7 @@
import org.opengrok.indexer.util.Statistics;
import org.opengrok.indexer.util.TandemPath;
import org.opengrok.indexer.web.Prefix;
import org.opengrok.indexer.web.SortOrder;

/**
* This is an encapsulation of the details on how to search in the index database.
Expand Down Expand Up @@ -114,6 +118,10 @@ public class SearchEngine {
* Holds value of property type.
*/
private String type;
/**
* Holds value of property sort.
*/
private SortOrder sortOrder;
/**
* Holds value of property indexDatabase.
*/
Expand Down Expand Up @@ -181,6 +189,10 @@ private void searchSingleDatabase(boolean paging) throws IOException {
SuperIndexSearcher superIndexSearcher = RuntimeEnvironment.getInstance().getSuperIndexSearcher("");
searcherList.add(superIndexSearcher);
searcher = superIndexSearcher;
// If a field-based sort is requested, collect all hits (disable paging optimization)
if (sortOrder != SortOrder.RELEVANCY) {
paging = false;
}
searchIndex(superIndexSearcher, paging);
}

Expand All @@ -205,18 +217,42 @@ private void searchMultiDatabase(List<Project> projectList, boolean paging) thro
}

private void searchIndex(IndexSearcher searcher, boolean paging) throws IOException {
collector = TopScoreDocCollector.create(hitsPerPage * cachePages, Short.MAX_VALUE);
// Determine if we need a field-based sort or relevancy (score) sort.
Sort luceneSort = null;
if (getSortOrder() == SortOrder.LASTMODIFIED) {
// Descending by date (newest first) - QueryBuilder.DATE is string sortable in index.
luceneSort = new Sort(new SortField(QueryBuilder.DATE, SortField.Type.STRING, true));
} else if (getSortOrder() == SortOrder.BY_PATH) {
luceneSort = new Sort(new SortField(QueryBuilder.FULLPATH, SortField.Type.STRING));
}

Statistics stat = new Statistics();
searcher.search(query, collector);
totalHits = collector.getTotalHits();
stat.report(LOGGER, Level.FINEST, "search via SearchEngine done",
"search.latency", new String[]{"category", "engine",
"outcome", totalHits > 0 ? "success" : "empty"});
if (!paging && totalHits > 0) {
collector = TopScoreDocCollector.create(totalHits, Short.MAX_VALUE);
if (luceneSort == null) {
collector = TopScoreDocCollector.create(hitsPerPage * cachePages, Short.MAX_VALUE);
searcher.search(query, collector);
totalHits = collector.getTotalHits();
stat.report(LOGGER, Level.FINEST, "search via SearchEngine done",
"search.latency", new String[]{"category", "engine",
"outcome", totalHits > 0 ? "success" : "empty"});
if (!paging && totalHits > 0) {
collector = TopScoreDocCollector.create(totalHits, Short.MAX_VALUE);
searcher.search(query, collector);
}
hits = collector.topDocs().scoreDocs;
} else {
// Field based sort; use TopFieldCollector
TopFieldCollector fieldCollector = TopFieldCollector.create(luceneSort, hitsPerPage * cachePages, Short.MAX_VALUE);
searcher.search(query, fieldCollector);
totalHits = fieldCollector.getTotalHits();
stat.report(LOGGER, Level.FINEST, "search via SearchEngine done (sorted)",
"search.latency", new String[]{"category", "engine",
"outcome", totalHits > 0 ? "success" : "empty"});
if (!paging && totalHits > 0) {
fieldCollector = TopFieldCollector.create(luceneSort, totalHits, Short.MAX_VALUE);
searcher.search(query, fieldCollector);
}
hits = fieldCollector.topDocs().scoreDocs;
}
hits = collector.topDocs().scoreDocs;
StoredFields storedFields = searcher.storedFields();
for (ScoreDoc hit : hits) {
int docId = hit.doc;
Expand Down Expand Up @@ -645,4 +681,22 @@ public String getType() {
public void setType(String fileType) {
this.type = fileType;
}

/**
* Getter for property sort.
*
* @return Value of property sortOrder.
*/
public SortOrder getSortOrder() {
return this.sortOrder;
}

/**
* Setter for property sort.
*
* @param sortOrder New value of property sortOrder.
*/
public void setSortOrder(SortOrder sortOrder) {
this.sortOrder = sortOrder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.opengrok.indexer.search.Hit;
import org.opengrok.indexer.search.SearchEngine;
import org.opengrok.indexer.web.QueryParameters;
import org.opengrok.indexer.web.SortOrder;
import org.opengrok.web.PageConfig;
import org.opengrok.web.api.v1.filter.CorsEnable;
import org.opengrok.web.api.v1.suggester.provider.service.SuggesterService;
Expand Down Expand Up @@ -81,9 +82,10 @@ public SearchResult search(
@QueryParam("projects") final List<String> projects,
@QueryParam("maxresults") // Akin to QueryParameters.COUNT_PARAM
@DefaultValue(MAX_RESULTS + "") final int maxResults,
@QueryParam(QueryParameters.SORT_PARAM) @DefaultValue("relevancy") final String sort,
@QueryParam(QueryParameters.START_PARAM) @DefaultValue(0 + "") final int startDocIndex
) {
try (SearchEngineWrapper engine = new SearchEngineWrapper(full, def, symbol, path, hist, type)) {
try (SearchEngineWrapper engine = new SearchEngineWrapper(full, def, symbol, path, hist, type, SortOrder.get(sort))) {

if (!engine.isValid()) {
throw new WebApplicationException("Invalid request", Response.Status.BAD_REQUEST);
Expand Down Expand Up @@ -119,14 +121,16 @@ private SearchEngineWrapper(
final String symbol,
final String path,
final String hist,
final String type
final String type,
final SortOrder sortOrder
) {
engine.setFreetext(full);
engine.setDefinition(def);
engine.setSymbol(symbol);
engine.setFile(path);
engine.setHistory(hist);
engine.setType(type);
engine.setSortOrder(sortOrder);
}

public List<Hit> search(
Expand Down