Skip to content

Commit d5166bb

Browse files
authored
Merge branch 'master' into fix-4878
2 parents 9a6fc12 + 2a808f7 commit d5166bb

24 files changed

Lines changed: 230 additions & 48 deletions

File tree

‎.github/workflows/build.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
distribution: 'oracle'
2929
java-version: '21'
3030
- name: Cache Maven packages
31-
uses: actions/cache@v4
31+
uses: actions/cache@v5
3232
with:
3333
path: ~/.m2
3434
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
@@ -57,7 +57,7 @@ jobs:
5757
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5858
run: ./dev/main
5959
- name: Upload artifact
60-
uses: actions/upload-artifact@v5
60+
uses: actions/upload-artifact@v6
6161
with:
6262
name: opengrok-${{ github.sha }}-${{ matrix.os }}.tar.gz
6363
path: distribution/target/opengrok-*.tar.gz

‎.github/workflows/javadoc.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
distribution: 'oracle'
2525
java-version: '21'
2626
- name: Cache Maven packages
27-
uses: actions/cache@v4
27+
uses: actions/cache@v5
2828
with:
2929
path: ~/.m2
3030
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}

‎.github/workflows/release.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
distribution: 'oracle'
3232
java-version: '21'
3333
- name: Cache Maven packages
34-
uses: actions/cache@v4
34+
uses: actions/cache@v5
3535
with:
3636
path: ~/.m2
3737
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,4 @@ pmd.bat
6060
.classpath
6161
.checkstyle
6262
.tox
63+
opengrok-indexer/index/dirty

‎Dockerfile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ RUN cp `ls -t distribution/target/*.tar.gz | head -1` /opengrok.tar.gz
4141
# Store the version in a file so that the tools can report it.
4242
RUN /mvn/mvnw help:evaluate -Dexpression=project.version -q -DforceStdout > /mvn/VERSION
4343

44-
FROM tomcat:10.1.49-jdk21
44+
FROM tomcat:10.1.50-jdk21
4545
LABEL maintainer="https://github.com/oracle/opengrok"
4646
LABEL org.opencontainers.image.source="https://github.com/oracle/opengrok"
4747
LABEL org.opencontainers.image.description="OpenGrok code search"

‎apiary.apib‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ The repository path is relative to source root.
643643
+ repository - repository path with native path separators (of the machine
644644
running the service) starting with path separator for which to return type
645645

646-
## Search [/search{?full,def,symbol,path,hist,type,projects,maxresults,start}]
646+
## Search [/search{?full,def,symbol,path,hist,type,projects,maxresults,start,sort}]
647647

648648
## return search results [GET]
649649

@@ -657,6 +657,15 @@ The repository path is relative to source root.
657657
+ projects (optional, string) - projects to search in
658658
+ maxresults (optional, string) - maximum number of documents whose hits will be returned (default 1000)
659659
+ start (optional, string) - start index from which to return results
660+
+ sort: relevancy (optional, enum[string])
661+
+ Enum
662+
+ relevancy
663+
+ fullpath
664+
+ lastmodtime
665+
+ Description: Sort order for results. Possible values:
666+
- `relevancy`: Sort by Lucene score (most relevant first).
667+
- `fullpath`: Sort by file path (alphabetical).
668+
- `lastmodtime`: Sort by last modification date (newest first).
660669

661670
+ Response 200 (application/json)
662671
+ Body

‎distribution/pom.xml‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<parent>
88
<groupId>org.opengrok</groupId>
99
<artifactId>opengrok-top</artifactId>
10-
<version>1.14.4</version>
10+
<version>1.14.5</version>
1111
</parent>
1212

1313
<artifactId>opengrok-dist</artifactId>
@@ -28,20 +28,20 @@
2828
<dependency>
2929
<groupId>org.opengrok</groupId>
3030
<artifactId>opengrok</artifactId>
31-
<version>1.14.4</version>
31+
<version>1.14.5</version>
3232
</dependency>
3333

3434
<dependency>
3535
<groupId>org.opengrok</groupId>
3636
<artifactId>opengrok-web</artifactId>
37-
<version>1.14.4</version>
37+
<version>1.14.5</version>
3838
<type>war</type>
3939
</dependency>
4040

4141
<dependency>
4242
<groupId>org.opengrok</groupId>
4343
<artifactId>tools</artifactId>
44-
<version>1.14.4</version>
44+
<version>1.14.5</version>
4545
<type>pom</type>
4646
</dependency>
4747
</dependencies>

‎opengrok-indexer/index/dirty‎

Whitespace-only changes.

‎opengrok-indexer/pom.xml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ Portions Copyright (c) 2020-2020, Lubos Kosco <tarzanek@gmail.com>.
2929
<parent>
3030
<groupId>org.opengrok</groupId>
3131
<artifactId>opengrok-top</artifactId>
32-
<version>1.14.4</version>
32+
<version>1.14.5</version>
3333
</parent>
3434

3535
<artifactId>opengrok</artifactId>
36-
<version>1.14.4</version>
36+
<version>1.14.5</version>
3737
<packaging>jar</packaging>
3838

3939
<name>OpenGrok Indexer</name>

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

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@
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.TopDocs;
54+
import org.apache.lucene.search.TopFieldCollectorManager;
5155
import org.apache.lucene.search.TopScoreDocCollectorManager;
5256
import org.apache.lucene.util.Version;
5357
import org.opengrok.indexer.analysis.AbstractAnalyzer;
@@ -66,6 +70,7 @@
6670
import org.opengrok.indexer.util.Statistics;
6771
import org.opengrok.indexer.util.TandemPath;
6872
import org.opengrok.indexer.web.Prefix;
73+
import org.opengrok.indexer.web.SortOrder;
6974

7075
/**
7176
* This is an encapsulation of the details on how to search in the index database.
@@ -114,6 +119,10 @@ public class SearchEngine {
114119
* Holds value of property type.
115120
*/
116121
private String type;
122+
/**
123+
* Holds value of property sort.
124+
*/
125+
private SortOrder sortOrder;
117126
/**
118127
* Holds value of property indexDatabase.
119128
*/
@@ -132,7 +141,6 @@ public class SearchEngine {
132141
int cachePages = RuntimeEnvironment.getInstance().getCachePages();
133142
int totalHits = 0;
134143
private ScoreDoc[] hits;
135-
private TopScoreDocCollectorManager collectorManager;
136144
private IndexSearcher searcher;
137145
boolean allCollected;
138146
private final ArrayList<SuperIndexSearcher> searcherList = new ArrayList<>();
@@ -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,20 +217,39 @@ private void searchMultiDatabase(List<Project> projectList, boolean paging) thro
205217
}
206218

207219
private void searchIndex(IndexSearcher searcher, boolean paging) throws IOException {
208-
collectorManager = new TopScoreDocCollectorManager(hitsPerPage * cachePages, Short.MAX_VALUE);
220+
Sort luceneSort = null;
221+
if (getSortOrder() == SortOrder.LASTMODIFIED) {
222+
luceneSort = new Sort(new SortField(QueryBuilder.DATE, SortField.Type.STRING, true));
223+
} else if (getSortOrder() == SortOrder.BY_PATH) {
224+
luceneSort = new Sort(new SortField(QueryBuilder.FULLPATH, SortField.Type.STRING));
225+
}
226+
227+
int numHits = hitsPerPage * cachePages;
228+
TopDocs topDocs;
229+
if (luceneSort == null) {
230+
topDocs = searcher.search(query, new TopScoreDocCollectorManager(numHits, Short.MAX_VALUE));
231+
} else {
232+
topDocs = searcher.search(query, new TopFieldCollectorManager(luceneSort, numHits, Short.MAX_VALUE));
233+
}
234+
hits = topDocs.scoreDocs;
235+
totalHits = (int) topDocs.totalHits.value;
236+
209237
Statistics stat = new Statistics();
210-
hits = searcher.search(query, collectorManager).scoreDocs;
211-
totalHits = searcher.count(query);
212238
stat.report(LOGGER, Level.FINEST, "search via SearchEngine done",
213239
"search.latency", new String[]{"category", "engine",
214240
"outcome", totalHits > 0 ? "success" : "empty"});
215-
if (!paging && totalHits > hitsPerPage * cachePages) {
216-
collectorManager = new TopScoreDocCollectorManager(totalHits, Short.MAX_VALUE);
217-
hits = searcher.search(query, collectorManager).scoreDocs;
218-
stat.report(LOGGER, Level.FINEST, "FULL search via SearchEngine done",
219-
"search.latency", new String[]{"category", "engine",
220-
"outcome", totalHits > 0 ? "success" : "empty"});
241+
242+
if (!paging && totalHits > numHits) {
243+
if (luceneSort == null) {
244+
topDocs = searcher.search(query, new TopScoreDocCollectorManager(totalHits, Short.MAX_VALUE));
245+
} else {
246+
topDocs = searcher.search(query, new TopFieldCollectorManager(luceneSort, totalHits, Short.MAX_VALUE));
247+
}
248+
hits = topDocs.scoreDocs;
221249
}
250+
251+
allCollected = !paging || totalHits <= numHits;
252+
222253
StoredFields storedFields = searcher.storedFields();
223254
for (ScoreDoc hit : hits) {
224255
int docId = hit.doc;
@@ -414,7 +445,7 @@ public void results(int start, int end, List<Hit> ret) {
414445
// TODO check if below fits for if end=old hits.length, or it should include it
415446
if (end > hits.length && !allCollected) {
416447
//do the requery, we want more than 5 pages
417-
collectorManager = new TopScoreDocCollectorManager(totalHits, Short.MAX_VALUE);
448+
var collectorManager = new TopScoreDocCollectorManager(totalHits, Short.MAX_VALUE);
418449
try {
419450
hits = searcher.search(query, collectorManager).scoreDocs;
420451
} catch (Exception e) { // this exception should never be hit, since search() will hit this before
@@ -646,4 +677,22 @@ public String getType() {
646677
public void setType(String fileType) {
647678
this.type = fileType;
648679
}
680+
681+
/**
682+
* Getter for property sort.
683+
*
684+
* @return Value of property sortOrder.
685+
*/
686+
public SortOrder getSortOrder() {
687+
return this.sortOrder;
688+
}
689+
690+
/**
691+
* Setter for property sort.
692+
*
693+
* @param sortOrder New value of property sortOrder.
694+
*/
695+
public void setSortOrder(SortOrder sortOrder) {
696+
this.sortOrder = sortOrder;
697+
}
649698
}

0 commit comments

Comments
 (0)