Skip to content

Commit 58d1dfa

Browse files
committed
Allow sorting in the API calls by path and date
Signed-off-by: Bernát Gábor <gaborjbernat@gmail.com>
1 parent e0faa57 commit 58d1dfa

File tree

2 files changed

+69
-11
lines changed

2 files changed

+69
-11
lines changed

opengrok-indexer/src/main/java/org/opengrok/indexer/search/SearchEngine.java

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
import org.apache.lucene.search.IndexSearcher;
4949
import org.apache.lucene.search.Query;
5050
import org.apache.lucene.search.ScoreDoc;
51+
import org.apache.lucene.search.Sort;
52+
import org.apache.lucene.search.SortField;
53+
import org.apache.lucene.search.TopFieldCollector;
5154
import org.apache.lucene.search.TopScoreDocCollector;
5255
import org.apache.lucene.util.Version;
5356
import org.opengrok.indexer.analysis.AbstractAnalyzer;
@@ -66,6 +69,7 @@
6669
import org.opengrok.indexer.util.Statistics;
6770
import org.opengrok.indexer.util.TandemPath;
6871
import org.opengrok.indexer.web.Prefix;
72+
import org.opengrok.indexer.web.SortOrder;
6973

7074
/**
7175
* This is an encapsulation of the details on how to search in the index database.
@@ -114,6 +118,10 @@ public class SearchEngine {
114118
* Holds value of property type.
115119
*/
116120
private String type;
121+
/**
122+
* Holds value of property sort.
123+
*/
124+
private SortOrder sortOrder;
117125
/**
118126
* Holds value of property indexDatabase.
119127
*/
@@ -181,6 +189,10 @@ private void searchSingleDatabase(boolean paging) throws IOException {
181189
SuperIndexSearcher superIndexSearcher = RuntimeEnvironment.getInstance().getSuperIndexSearcher("");
182190
searcherList.add(superIndexSearcher);
183191
searcher = superIndexSearcher;
192+
// If a field-based sort is requested, collect all hits (disable paging optimization)
193+
if (sortOrder != SortOrder.RELEVANCY) {
194+
paging = false;
195+
}
184196
searchIndex(superIndexSearcher, paging);
185197
}
186198

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

207219
private void searchIndex(IndexSearcher searcher, boolean paging) throws IOException {
208-
collector = TopScoreDocCollector.create(hitsPerPage * cachePages, Short.MAX_VALUE);
220+
// Determine if we need a field-based sort or relevancy (score) sort.
221+
Sort luceneSort = null;
222+
if (getSortOrder() == SortOrder.LASTMODIFIED) {
223+
// Descending by date (newest first) - QueryBuilder.DATE is string sortable in index.
224+
luceneSort = new Sort(new SortField(QueryBuilder.DATE, SortField.Type.STRING, true));
225+
} else if (getSortOrder() == SortOrder.BY_PATH) {
226+
luceneSort = new Sort(new SortField(QueryBuilder.FULLPATH, SortField.Type.STRING));
227+
}
228+
209229
Statistics stat = new Statistics();
210-
searcher.search(query, collector);
211-
totalHits = collector.getTotalHits();
212-
stat.report(LOGGER, Level.FINEST, "search via SearchEngine done",
213-
"search.latency", new String[]{"category", "engine",
214-
"outcome", totalHits > 0 ? "success" : "empty"});
215-
if (!paging && totalHits > 0) {
216-
collector = TopScoreDocCollector.create(totalHits, Short.MAX_VALUE);
230+
if (luceneSort == null) {
231+
collector = TopScoreDocCollector.create(hitsPerPage * cachePages, Short.MAX_VALUE);
217232
searcher.search(query, collector);
233+
totalHits = collector.getTotalHits();
234+
stat.report(LOGGER, Level.FINEST, "search via SearchEngine done",
235+
"search.latency", new String[]{"category", "engine",
236+
"outcome", totalHits > 0 ? "success" : "empty"});
237+
if (!paging && totalHits > 0) {
238+
collector = TopScoreDocCollector.create(totalHits, Short.MAX_VALUE);
239+
searcher.search(query, collector);
240+
}
241+
hits = collector.topDocs().scoreDocs;
242+
} else {
243+
// Field based sort; use TopFieldCollector
244+
TopFieldCollector fieldCollector = TopFieldCollector.create(luceneSort, hitsPerPage * cachePages, Short.MAX_VALUE);
245+
searcher.search(query, fieldCollector);
246+
totalHits = fieldCollector.getTotalHits();
247+
stat.report(LOGGER, Level.FINEST, "search via SearchEngine done (sorted)",
248+
"search.latency", new String[]{"category", "engine",
249+
"outcome", totalHits > 0 ? "success" : "empty"});
250+
if (!paging && totalHits > 0) {
251+
fieldCollector = TopFieldCollector.create(luceneSort, totalHits, Short.MAX_VALUE);
252+
searcher.search(query, fieldCollector);
253+
}
254+
hits = fieldCollector.topDocs().scoreDocs;
218255
}
219-
hits = collector.topDocs().scoreDocs;
220256
StoredFields storedFields = searcher.storedFields();
221257
for (ScoreDoc hit : hits) {
222258
int docId = hit.doc;
@@ -645,4 +681,22 @@ public String getType() {
645681
public void setType(String fileType) {
646682
this.type = fileType;
647683
}
684+
685+
/**
686+
* Getter for property sort.
687+
*
688+
* @return Value of property sortOrder.
689+
*/
690+
public SortOrder getSortOrder() {
691+
return this.sortOrder;
692+
}
693+
694+
/**
695+
* Setter for property sort.
696+
*
697+
* @param sortOrder New value of property sortOrder.
698+
*/
699+
public void setSortOrder(SortOrder sortOrder) {
700+
this.sortOrder = sortOrder;
701+
}
648702
}

opengrok-web/src/main/java/org/opengrok/web/api/v1/controller/SearchController.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.opengrok.indexer.search.Hit;
4040
import org.opengrok.indexer.search.SearchEngine;
4141
import org.opengrok.indexer.web.QueryParameters;
42+
import org.opengrok.indexer.web.SortOrder;
4243
import org.opengrok.web.PageConfig;
4344
import org.opengrok.web.api.v1.filter.CorsEnable;
4445
import org.opengrok.web.api.v1.suggester.provider.service.SuggesterService;
@@ -81,9 +82,10 @@ public SearchResult search(
8182
@QueryParam("projects") final List<String> projects,
8283
@QueryParam("maxresults") // Akin to QueryParameters.COUNT_PARAM
8384
@DefaultValue(MAX_RESULTS + "") final int maxResults,
85+
@QueryParam(QueryParameters.SORT_PARAM) @DefaultValue("relevancy") final String sort,
8486
@QueryParam(QueryParameters.START_PARAM) @DefaultValue(0 + "") final int startDocIndex
8587
) {
86-
try (SearchEngineWrapper engine = new SearchEngineWrapper(full, def, symbol, path, hist, type)) {
88+
try (SearchEngineWrapper engine = new SearchEngineWrapper(full, def, symbol, path, hist, type, SortOrder.get(sort))) {
8789

8890
if (!engine.isValid()) {
8991
throw new WebApplicationException("Invalid request", Response.Status.BAD_REQUEST);
@@ -119,14 +121,16 @@ private SearchEngineWrapper(
119121
final String symbol,
120122
final String path,
121123
final String hist,
122-
final String type
124+
final String type,
125+
final SortOrder sortOrder
123126
) {
124127
engine.setFreetext(full);
125128
engine.setDefinition(def);
126129
engine.setSymbol(symbol);
127130
engine.setFile(path);
128131
engine.setHistory(hist);
129132
engine.setType(type);
133+
engine.setSortOrder(sortOrder);
130134
}
131135

132136
public List<Hit> search(

0 commit comments

Comments
 (0)