This is an automated email from the ASF dual-hosted git repository.

Arsnael pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git


The following commit(s) were added to refs/heads/master by this push:
     new 81c2fcb9e0 JAMES-4202 OpenSearch: Group single uid clauses into a 
single term
81c2fcb9e0 is described below

commit 81c2fcb9e0b029176a5d8e7f159648dcd94ccadc
Author: Benoit TELLIER <[email protected]>
AuthorDate: Thu Apr 23 07:52:41 2026 +0200

    JAMES-4202 OpenSearch: Group single uid clauses into a single term
---
 .../query/DefaultCriterionConverter.java           | 25 +++++++++++++++++++--
 .../opensearch/OpenSearchIntegrationTest.java      | 26 ++++++++++++++++++++++
 2 files changed, 49 insertions(+), 2 deletions(-)

diff --git 
a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/DefaultCriterionConverter.java
 
b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/DefaultCriterionConverter.java
index 8a7df4fb59..e65c18fc93 100644
--- 
a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/DefaultCriterionConverter.java
+++ 
b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/DefaultCriterionConverter.java
@@ -50,6 +50,8 @@ import 
org.opensearch.client.opensearch._types.query_dsl.Query;
 import org.opensearch.client.opensearch._types.query_dsl.RangeQuery;
 import 
org.opensearch.client.opensearch._types.query_dsl.SimpleQueryStringQuery;
 import org.opensearch.client.opensearch._types.query_dsl.TermQuery;
+import org.opensearch.client.opensearch._types.query_dsl.TermsQuery;
+import org.opensearch.client.opensearch._types.query_dsl.TermsQueryField;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.CharMatcher;
@@ -518,10 +520,29 @@ public class DefaultCriterionConverter implements 
CriterionConverter {
         if (uidCriterion.getOperator().getRange().length == 0) {
             return new BoolQuery.Builder().build().toQuery();
         }
+        SearchQuery.UidRange[] ranges = uidCriterion.getOperator().getRange();
+
+        ImmutableList<FieldValue> singleUids = Arrays.stream(ranges)
+            .filter(r -> r.getLowValue().equals(r.getHighValue()))
+            .map(r -> new 
FieldValue.Builder().longValue(r.getLowValue().asLong()).build())
+            .collect(ImmutableList.toImmutableList());
+
+        Stream<Query> rangeQueries = Arrays.stream(ranges)
+            .filter(r -> !r.getLowValue().equals(r.getHighValue()))
+            .map(this::uidRangeFilter);
+
+        Stream<Query> termsQuery = singleUids.isEmpty() ? Stream.empty() :
+            Stream.of(new TermsQuery.Builder()
+                .field(JsonMessageConstants.UID)
+                .terms(new TermsQueryField.Builder()
+                    .value(singleUids)
+                    .build())
+                .build()
+                .toQuery());
+
         return new BoolQuery.Builder()
             .filter(convertToBoolQuery(
-                Arrays.stream(uidCriterion.getOperator().getRange())
-                    .map(this::uidRangeFilter), BoolQuery.Builder::should))
+                Stream.concat(rangeQueries, termsQuery), 
BoolQuery.Builder::should))
             .build()
             .toQuery();
     }
diff --git 
a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/OpenSearchIntegrationTest.java
 
b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/OpenSearchIntegrationTest.java
index 870e35b9bb..87f5613b9c 100644
--- 
a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/OpenSearchIntegrationTest.java
+++ 
b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/OpenSearchIntegrationTest.java
@@ -821,6 +821,32 @@ class OpenSearchIntegrationTest extends 
AbstractMessageSearchIndexTest {
                 .isEqualTo(expectedCountResult));
     }
 
+    @Test
+    void uidSearchShouldSupportMoreThan1024IndividualUids() throws Exception {
+        MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, 
"largeUidMailbox");
+        MailboxId mailboxId = storeMailboxManager.createMailbox(mailboxPath, 
session).get();
+        MessageManager messageManager = 
storeMailboxManager.getMailbox(mailboxId, session);
+
+        int messageCount = 1100;
+        ImmutableList.Builder<MessageUid> uidBuilder = ImmutableList.builder();
+        for (int i = 0; i < messageCount; i++) {
+            ComposedMessageId id = messageManager.appendMessage(
+                MessageManager.AppendCommand.from(
+                    Message.Builder.of().setBody("message " + i, 
StandardCharsets.UTF_8)), session).getId();
+            uidBuilder.add(id.getUid());
+        }
+        List<MessageUid> appendedUids = uidBuilder.build();
+
+        awaitMessageCount(List.of(mailboxId), SearchQuery.matchAll(), 
messageCount);
+
+        SearchQuery.UidRange[] ranges = appendedUids.stream()
+            .map(uid -> new SearchQuery.UidRange(uid, uid))
+            .toArray(SearchQuery.UidRange[]::new);
+
+        
assertThat(Flux.from(messageManager.search(SearchQuery.of(SearchQuery.uid(ranges)),
 session)).toStream())
+            .hasSize(messageCount);
+    }
+
     @Override
     protected boolean supportsCollapseThreads() {
         return true;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to