This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 72f46ce43c02d8680ca116d4f62340193ffaff27 Author: Quan Tran <[email protected]> AuthorDate: Thu Jan 29 15:25:09 2026 +0700 JAMES-4166 JMAP search: drop scroll search, use from/size pagination and collapse by messageId --- .../OpenSearchListeningMessageSearchIndex.java | 6 +-- .../opensearch/search/OpenSearchSearcher.java | 44 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndex.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndex.java index c88bd7dba7..15a3227a99 100644 --- a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndex.java +++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndex.java @@ -369,10 +369,8 @@ public class OpenSearchListeningMessageSearchIndex extends ListeningMessageSearc return Flux.empty(); } - return searcher.search(mailboxIds, searchQuery, Optional.empty(), MESSAGE_ID_FIELD, !SEARCH_HIGHLIGHT) - .handle(this::extractMessageIdFromHit) - .distinct() - .take(limit); + return searcher.searchCollapsedByMessageId(mailboxIds, searchQuery, Math.toIntExact(limit), MESSAGE_ID_FIELD, !SEARCH_HIGHLIGHT) + .handle(this::extractMessageIdFromHit); } @Override diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcher.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcher.java index 3d61f747a8..d11bdf8333 100644 --- a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcher.java +++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcher.java @@ -21,6 +21,7 @@ package org.apache.james.mailbox.opensearch.search; import static org.apache.james.mailbox.opensearch.search.OpenSearchSearchHighlighter.ATTACHMENT_TEXT_CONTENT_FIELD; +import java.io.IOException; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -104,6 +105,22 @@ public class OpenSearchSearcher { .searchHits(); } + public Flux<Hit<ObjectNode>> searchCollapsedByMessageId(Collection<MailboxId> mailboxIds, SearchQuery query, + int limit, List<String> fields, + boolean searchHighlight) { + if (limit == 0) { + return Flux.empty(); + } + + SearchRequest searchRequest = prepareCollapsedSearchByMessageId(mailboxIds, query, 0, limit, fields, searchHighlight); + try { + return client.search(searchRequest) + .flatMapMany(response -> Flux.fromIterable(response.hits().hits())); + } catch (IOException e) { + return Flux.error(e); + } + } + private SearchRequest prepareSearch(Collection<MailboxId> mailboxIds, SearchQuery query, Optional<Integer> limit, List<String> fields, boolean highlight) { List<SortOptions> sorts = query.getSorts() @@ -130,6 +147,33 @@ public class OpenSearchSearcher { .build(); } + private SearchRequest prepareCollapsedSearchByMessageId(Collection<MailboxId> mailboxIds, SearchQuery query, + int from, int size, List<String> fields, boolean highlight) { + List<SortOptions> sorts = query.getSorts() + .stream() + .flatMap(SortConverter::convertSort) + .map(fieldSort -> new SortOptions.Builder().field(fieldSort).build()) + .collect(Collectors.toList()); + + SearchRequest.Builder request = new SearchRequest.Builder() + .index(aliasName.getValue()) + .query(queryConverter.from(mailboxIds, query)) + .from(from) + .size(size) + .storedFields(fields) + .sort(sorts) + .collapse(collapse -> collapse.field(JsonMessageConstants.MESSAGE_ID)); + + if (highlight) { + request.highlight(highlightQuery); + } + + return toRoutingKey(mailboxIds) + .map(request::routing) + .orElse(request) + .build(); + } + private Optional<String> toRoutingKey(Collection<MailboxId> mailboxIds) { if (mailboxIds.size() < MAX_ROUTING_KEY) { return Optional.of(mailboxIds.stream() --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
