You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2023/01/06 03:02:41 UTC
[james-project] 02/12: JAMES-3771 Migrate mailbox opensearch to new java client
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 092c357b18b325c457f4d1529208cb013c4055a7
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Tue Jun 21 16:19:16 2022 +0700
JAMES-3771 Migrate mailbox opensearch to new java client
---
.../opensearch/DockerOpenSearchExtension.java | 7 +-
.../mailbox/opensearch/MailboxMappingFactory.java | 518 ++++++++++-----------
.../OpenSearchListeningMessageSearchIndex.java | 61 +--
.../opensearch/query/CriterionConverter.java | 384 +++++++++++----
.../mailbox/opensearch/query/QueryConverter.java | 37 +-
.../mailbox/opensearch/query/SortConverter.java | 42 +-
.../opensearch/search/OpenSearchSearcher.java | 42 +-
.../opensearch/OpenSearchIntegrationTest.java | 46 +-
.../OpenSearchListeningMessageSearchIndexTest.java | 64 +--
.../opensearch/search/OpenSearchSearcherTest.java | 21 +-
10 files changed, 690 insertions(+), 532 deletions(-)
diff --git a/backends-common/opensearch/src/test/java/org/apache/james/backends/opensearch/DockerOpenSearchExtension.java b/backends-common/opensearch/src/test/java/org/apache/james/backends/opensearch/DockerOpenSearchExtension.java
index 021a60d790..aee8790003 100644
--- a/backends-common/opensearch/src/test/java/org/apache/james/backends/opensearch/DockerOpenSearchExtension.java
+++ b/backends-common/opensearch/src/test/java/org/apache/james/backends/opensearch/DockerOpenSearchExtension.java
@@ -35,13 +35,13 @@ public class DockerOpenSearchExtension implements AfterEachCallback, BeforeEachC
interface CleanupStrategy {
CleanupStrategy NONE = any -> {};
- void clean(DockerOpenSearch elasticSearch);
+ void clean(DockerOpenSearch openSearch);
}
public static class DefaultCleanupStrategy implements CleanupStrategy {
@Override
- public void clean(DockerOpenSearch elasticSearch) {
- elasticSearch.cleanUpData();
+ public void clean(DockerOpenSearch openSearch) {
+ openSearch.cleanUpData();
}
}
@@ -55,6 +55,7 @@ public class DockerOpenSearchExtension implements AfterEachCallback, BeforeEachC
@Override
public void clean(DockerOpenSearch openSearch) {
Awaitility.await()
+ .ignoreExceptions()
.until(() -> {
openSearch.flushIndices();
ReactorOpenSearchClient client = openSearch.clientProvider().get();
diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/MailboxMappingFactory.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/MailboxMappingFactory.java
index d9813d738c..2964a8738f 100644
--- a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/MailboxMappingFactory.java
+++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/MailboxMappingFactory.java
@@ -19,298 +19,256 @@
package org.apache.james.mailbox.opensearch;
-import static org.apache.james.backends.opensearch.IndexCreationFactory.ANALYZER;
-import static org.apache.james.backends.opensearch.IndexCreationFactory.BOOLEAN;
import static org.apache.james.backends.opensearch.IndexCreationFactory.CASE_INSENSITIVE;
-import static org.apache.james.backends.opensearch.IndexCreationFactory.FIELDS;
-import static org.apache.james.backends.opensearch.IndexCreationFactory.FORMAT;
import static org.apache.james.backends.opensearch.IndexCreationFactory.KEEP_MAIL_AND_URL;
import static org.apache.james.backends.opensearch.IndexCreationFactory.KEYWORD;
-import static org.apache.james.backends.opensearch.IndexCreationFactory.LONG;
-import static org.apache.james.backends.opensearch.IndexCreationFactory.NESTED;
-import static org.apache.james.backends.opensearch.IndexCreationFactory.NORMALIZER;
-import static org.apache.james.backends.opensearch.IndexCreationFactory.PROPERTIES;
import static org.apache.james.backends.opensearch.IndexCreationFactory.RAW;
-import static org.apache.james.backends.opensearch.IndexCreationFactory.REQUIRED;
-import static org.apache.james.backends.opensearch.IndexCreationFactory.ROUTING;
-import static org.apache.james.backends.opensearch.IndexCreationFactory.SEARCH_ANALYZER;
-import static org.apache.james.backends.opensearch.IndexCreationFactory.TYPE;
-import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder;
-import java.io.IOException;
+import java.util.Map;
-import org.apache.james.backends.opensearch.IndexCreationFactory;
import org.apache.james.mailbox.opensearch.json.JsonMessageConstants;
-import org.opensearch.common.xcontent.XContentBuilder;
+import org.opensearch.client.opensearch._types.mapping.BooleanProperty;
+import org.opensearch.client.opensearch._types.mapping.DateProperty;
+import org.opensearch.client.opensearch._types.mapping.DynamicMapping;
+import org.opensearch.client.opensearch._types.mapping.KeywordProperty;
+import org.opensearch.client.opensearch._types.mapping.LongNumberProperty;
+import org.opensearch.client.opensearch._types.mapping.NestedProperty;
+import org.opensearch.client.opensearch._types.mapping.ObjectProperty;
+import org.opensearch.client.opensearch._types.mapping.Property;
+import org.opensearch.client.opensearch._types.mapping.RoutingField;
+import org.opensearch.client.opensearch._types.mapping.TextProperty;
+import org.opensearch.client.opensearch._types.mapping.TypeMapping;
+
+import com.google.common.collect.ImmutableMap;
public class MailboxMappingFactory {
private static final String STANDARD = "standard";
private static final String SIMPLE = "simple";
- private static final String STORE = "store";
- public static XContentBuilder getMappingContent() {
- try {
- return jsonBuilder()
- .startObject()
-
- .field("dynamic", "strict")
-
- .startObject(ROUTING)
- .field(REQUIRED, true)
- .endObject()
-
- .startObject(PROPERTIES)
-
- .startObject(JsonMessageConstants.MESSAGE_ID)
- .field(TYPE, KEYWORD)
- .field(STORE, true)
- .endObject()
-
- .startObject(JsonMessageConstants.THREAD_ID)
- .field(TYPE, KEYWORD)
- .endObject()
-
- .startObject(JsonMessageConstants.UID)
- .field(TYPE, LONG)
- .field(STORE, true)
- .endObject()
-
- .startObject(JsonMessageConstants.MODSEQ)
- .field(TYPE, LONG)
- .endObject()
-
- .startObject(JsonMessageConstants.SIZE)
- .field(TYPE, LONG)
- .endObject()
-
- .startObject(JsonMessageConstants.IS_ANSWERED)
- .field(TYPE, BOOLEAN)
- .endObject()
-
- .startObject(JsonMessageConstants.IS_DELETED)
- .field(TYPE, BOOLEAN)
- .endObject()
-
- .startObject(JsonMessageConstants.IS_DRAFT)
- .field(TYPE, BOOLEAN)
- .endObject()
-
- .startObject(JsonMessageConstants.IS_FLAGGED)
- .field(TYPE, BOOLEAN)
- .endObject()
-
- .startObject(JsonMessageConstants.IS_RECENT)
- .field(TYPE, BOOLEAN)
- .endObject()
-
- .startObject(JsonMessageConstants.IS_UNREAD)
- .field(TYPE, BOOLEAN)
- .endObject()
-
- .startObject(JsonMessageConstants.DATE)
- .field(TYPE, IndexCreationFactory.DATE)
- .field(FORMAT, "uuuu-MM-dd'T'HH:mm:ssX||uuuu-MM-dd'T'HH:mm:ssXXX||uuuu-MM-dd'T'HH:mm:ssXXXXX")
- .endObject()
-
- .startObject(JsonMessageConstants.SENT_DATE)
- .field(TYPE, IndexCreationFactory.DATE)
- .field(FORMAT, "uuuu-MM-dd'T'HH:mm:ssX||uuuu-MM-dd'T'HH:mm:ssXXX||uuuu-MM-dd'T'HH:mm:ssXXXXX")
- .endObject()
-
- .startObject(JsonMessageConstants.SAVE_DATE)
- .field(TYPE, IndexCreationFactory.DATE)
- .field(FORMAT, "uuuu-MM-dd'T'HH:mm:ssX||uuuu-MM-dd'T'HH:mm:ssXXX||uuuu-MM-dd'T'HH:mm:ssXXXXX")
- .endObject()
-
- .startObject(JsonMessageConstants.USER_FLAGS)
- .field(TYPE, KEYWORD)
- .field(NORMALIZER, CASE_INSENSITIVE)
- .endObject()
-
- .startObject(JsonMessageConstants.MEDIA_TYPE)
- .field(TYPE, KEYWORD)
- .endObject()
-
- .startObject(JsonMessageConstants.SUBTYPE)
- .field(TYPE, KEYWORD)
- .endObject()
-
- .startObject(JsonMessageConstants.FROM)
- .startObject(PROPERTIES)
- .startObject(JsonMessageConstants.EMailer.NAME)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, KEEP_MAIL_AND_URL)
- .endObject()
- .startObject(JsonMessageConstants.EMailer.DOMAIN)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, SIMPLE)
- .field(SEARCH_ANALYZER, KEYWORD)
- .endObject()
- .startObject(JsonMessageConstants.EMailer.ADDRESS)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, STANDARD)
- .field(SEARCH_ANALYZER, KEEP_MAIL_AND_URL)
- .startObject(FIELDS)
- .startObject(RAW)
- .field(TYPE, KEYWORD)
- .field(NORMALIZER, CASE_INSENSITIVE)
- .endObject()
- .endObject()
- .endObject()
- .endObject()
- .endObject()
-
- .startObject(JsonMessageConstants.HEADERS)
- .field(TYPE, NESTED)
- .startObject(PROPERTIES)
- .startObject(JsonMessageConstants.HEADER.NAME)
- .field(TYPE, KEYWORD)
- .endObject()
- .startObject(JsonMessageConstants.HEADER.VALUE)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, KEEP_MAIL_AND_URL)
- .endObject()
- .endObject()
- .endObject()
-
- .startObject(JsonMessageConstants.SUBJECT)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, KEEP_MAIL_AND_URL)
- .startObject(FIELDS)
- .startObject(RAW)
- .field(TYPE, KEYWORD)
- .field(NORMALIZER, CASE_INSENSITIVE)
- .endObject()
- .endObject()
- .endObject()
-
- .startObject(JsonMessageConstants.TO)
- .startObject(PROPERTIES)
- .startObject(JsonMessageConstants.EMailer.NAME)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, KEEP_MAIL_AND_URL)
- .endObject()
- .startObject(JsonMessageConstants.EMailer.DOMAIN)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, SIMPLE)
- .field(SEARCH_ANALYZER, KEYWORD)
- .endObject()
- .startObject(JsonMessageConstants.EMailer.ADDRESS)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, STANDARD)
- .field(SEARCH_ANALYZER, KEEP_MAIL_AND_URL)
- .startObject(FIELDS)
- .startObject(RAW)
- .field(TYPE, KEYWORD)
- .field(NORMALIZER, CASE_INSENSITIVE)
- .endObject()
- .endObject()
- .endObject()
- .endObject()
- .endObject()
-
- .startObject(JsonMessageConstants.CC)
- .startObject(PROPERTIES)
- .startObject(JsonMessageConstants.EMailer.NAME)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, KEEP_MAIL_AND_URL)
- .endObject()
- .startObject(JsonMessageConstants.EMailer.DOMAIN)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, SIMPLE)
- .field(SEARCH_ANALYZER, KEYWORD)
- .endObject()
- .startObject(JsonMessageConstants.EMailer.ADDRESS)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, STANDARD)
- .field(SEARCH_ANALYZER, KEEP_MAIL_AND_URL)
- .startObject(FIELDS)
- .startObject(RAW)
- .field(TYPE, KEYWORD)
- .field(NORMALIZER, CASE_INSENSITIVE)
- .endObject()
- .endObject()
- .endObject()
- .endObject()
- .endObject()
-
- .startObject(JsonMessageConstants.BCC)
- .startObject(PROPERTIES)
- .startObject(JsonMessageConstants.EMailer.NAME)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, KEEP_MAIL_AND_URL)
- .endObject()
- .startObject(JsonMessageConstants.EMailer.DOMAIN)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, SIMPLE)
- .field(SEARCH_ANALYZER, KEYWORD)
- .endObject()
- .startObject(JsonMessageConstants.EMailer.ADDRESS)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, STANDARD)
- .field(SEARCH_ANALYZER, KEEP_MAIL_AND_URL)
- .startObject(FIELDS)
- .startObject(RAW)
- .field(TYPE, KEYWORD)
- .field(NORMALIZER, CASE_INSENSITIVE)
- .endObject()
- .endObject()
- .endObject()
- .endObject()
- .endObject()
-
- .startObject(JsonMessageConstants.MAILBOX_ID)
- .field(TYPE, KEYWORD)
- .field(STORE, true)
- .endObject()
-
- .startObject(JsonMessageConstants.MIME_MESSAGE_ID)
- .field(TYPE, KEYWORD)
- .endObject()
-
- .startObject(JsonMessageConstants.TEXT_BODY)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, STANDARD)
- .endObject()
-
- .startObject(JsonMessageConstants.HTML_BODY)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, STANDARD)
- .endObject()
-
- .startObject(JsonMessageConstants.HAS_ATTACHMENT)
- .field(TYPE, BOOLEAN)
- .endObject()
-
- .startObject(JsonMessageConstants.ATTACHMENTS)
- .startObject(PROPERTIES)
- .startObject(JsonMessageConstants.Attachment.FILENAME)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, STANDARD)
- .endObject()
- .startObject(JsonMessageConstants.Attachment.TEXT_CONTENT)
- .field(TYPE, JsonMessageConstants.TEXT)
- .field(ANALYZER, STANDARD)
- .endObject()
- .startObject(JsonMessageConstants.Attachment.MEDIA_TYPE)
- .field(TYPE, KEYWORD)
- .endObject()
- .startObject(JsonMessageConstants.Attachment.SUBTYPE)
- .field(TYPE, KEYWORD)
- .endObject()
- .startObject(JsonMessageConstants.Attachment.FILE_EXTENSION)
- .field(TYPE, KEYWORD)
- .endObject()
- .startObject(JsonMessageConstants.Attachment.CONTENT_DISPOSITION)
- .field(TYPE, KEYWORD)
- .endObject()
- .endObject()
- .endObject()
+ public static TypeMapping getMappingContent() {
+ return new TypeMapping.Builder()
+ .dynamic(DynamicMapping.Strict)
+ .routing(new RoutingField.Builder()
+ .required(true)
+ .build())
+ .properties(generateProperties())
+ .build();
+ }
- .endObject()
- .endObject();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ private static Map<String, Property> generateProperties() {
+ return new ImmutableMap.Builder<String, Property>()
+ .put(JsonMessageConstants.MESSAGE_ID, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().store(true).build())
+ .build())
+ .put(JsonMessageConstants.THREAD_ID, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().build())
+ .build())
+ .put(JsonMessageConstants.UID, new Property.Builder()
+ .long_(new LongNumberProperty.Builder().store(true).build())
+ .build())
+ .put(JsonMessageConstants.MODSEQ, new Property.Builder()
+ .long_(new LongNumberProperty.Builder().build())
+ .build())
+ .put(JsonMessageConstants.SIZE, new Property.Builder()
+ .long_(new LongNumberProperty.Builder().build())
+ .build())
+ .put(JsonMessageConstants.IS_ANSWERED, new Property.Builder()
+ .boolean_(new BooleanProperty.Builder().build())
+ .build())
+ .put(JsonMessageConstants.IS_DELETED, new Property.Builder()
+ .boolean_(new BooleanProperty.Builder().build())
+ .build())
+ .put(JsonMessageConstants.IS_DRAFT, new Property.Builder()
+ .boolean_(new BooleanProperty.Builder().build())
+ .build())
+ .put(JsonMessageConstants.IS_FLAGGED, new Property.Builder()
+ .boolean_(new BooleanProperty.Builder().build())
+ .build())
+ .put(JsonMessageConstants.IS_RECENT, new Property.Builder()
+ .boolean_(new BooleanProperty.Builder().build())
+ .build())
+ .put(JsonMessageConstants.IS_UNREAD, new Property.Builder()
+ .boolean_(new BooleanProperty.Builder().build())
+ .build())
+ .put(JsonMessageConstants.DATE, new Property.Builder()
+ .date(new DateProperty.Builder()
+ .format("uuuu-MM-dd'T'HH:mm:ssX||uuuu-MM-dd'T'HH:mm:ssXXX||uuuu-MM-dd'T'HH:mm:ssXXXXX")
+ .build())
+ .build())
+ .put(JsonMessageConstants.SENT_DATE, new Property.Builder()
+ .date(new DateProperty.Builder()
+ .format("uuuu-MM-dd'T'HH:mm:ssX||uuuu-MM-dd'T'HH:mm:ssXXX||uuuu-MM-dd'T'HH:mm:ssXXXXX")
+ .build())
+ .build())
+ .put(JsonMessageConstants.SAVE_DATE, new Property.Builder()
+ .date(new DateProperty.Builder()
+ .format("uuuu-MM-dd'T'HH:mm:ssX||uuuu-MM-dd'T'HH:mm:ssXXX||uuuu-MM-dd'T'HH:mm:ssXXXXX")
+ .build())
+ .build())
+ .put(JsonMessageConstants.USER_FLAGS, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().normalizer(CASE_INSENSITIVE).build())
+ .build())
+ .put(JsonMessageConstants.MEDIA_TYPE, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().build())
+ .build())
+ .put(JsonMessageConstants.SUBTYPE, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().build())
+ .build())
+ .put(JsonMessageConstants.FROM, new Property.Builder()
+ .object(new ObjectProperty.Builder()
+ .properties(ImmutableMap.of(
+ JsonMessageConstants.EMailer.NAME, new Property.Builder()
+ .text(new TextProperty.Builder().analyzer(KEEP_MAIL_AND_URL).build())
+ .build(),
+ JsonMessageConstants.EMailer.DOMAIN, new Property.Builder()
+ .text(new TextProperty.Builder()
+ .analyzer(SIMPLE)
+ .searchAnalyzer(KEYWORD)
+ .build())
+ .build(),
+ JsonMessageConstants.EMailer.ADDRESS, new Property.Builder()
+ .text(new TextProperty.Builder()
+ .analyzer(STANDARD)
+ .searchAnalyzer(KEEP_MAIL_AND_URL)
+ .fields(RAW, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().normalizer(CASE_INSENSITIVE).build())
+ .build())
+ .build())
+ .build()
+ ))
+ .build())
+ .build())
+ .put(JsonMessageConstants.HEADERS, new Property.Builder()
+ .nested(new NestedProperty.Builder()
+ .properties(ImmutableMap.of(
+ JsonMessageConstants.HEADER.NAME, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().build())
+ .build(),
+ JsonMessageConstants.HEADER.VALUE, new Property.Builder()
+ .text(new TextProperty.Builder().analyzer(KEEP_MAIL_AND_URL).build())
+ .build()
+ ))
+ .build())
+ .build())
+ .put(JsonMessageConstants.SUBJECT, new Property.Builder()
+ .text(new TextProperty.Builder()
+ .analyzer(KEEP_MAIL_AND_URL)
+ .fields(RAW, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().normalizer(CASE_INSENSITIVE).build())
+ .build())
+ .build())
+ .build())
+ .put(JsonMessageConstants.TO, new Property.Builder()
+ .object(new ObjectProperty.Builder()
+ .properties(ImmutableMap.of(
+ JsonMessageConstants.EMailer.NAME, new Property.Builder()
+ .text(new TextProperty.Builder().analyzer(KEEP_MAIL_AND_URL).build())
+ .build(),
+ JsonMessageConstants.EMailer.DOMAIN, new Property.Builder()
+ .text(new TextProperty.Builder()
+ .analyzer(SIMPLE)
+ .searchAnalyzer(KEYWORD)
+ .build())
+ .build(),
+ JsonMessageConstants.EMailer.ADDRESS, new Property.Builder()
+ .text(new TextProperty.Builder()
+ .analyzer(STANDARD)
+ .searchAnalyzer(KEEP_MAIL_AND_URL)
+ .fields(RAW, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().normalizer(CASE_INSENSITIVE).build())
+ .build())
+ .build())
+ .build()
+ ))
+ .build())
+ .build())
+ .put(JsonMessageConstants.CC, new Property.Builder()
+ .object(new ObjectProperty.Builder()
+ .properties(ImmutableMap.of(
+ JsonMessageConstants.EMailer.NAME, new Property.Builder()
+ .text(new TextProperty.Builder().analyzer(KEEP_MAIL_AND_URL).build())
+ .build(),
+ JsonMessageConstants.EMailer.DOMAIN, new Property.Builder()
+ .text(new TextProperty.Builder()
+ .analyzer(SIMPLE)
+ .searchAnalyzer(KEYWORD)
+ .build())
+ .build(),
+ JsonMessageConstants.EMailer.ADDRESS, new Property.Builder()
+ .text(new TextProperty.Builder()
+ .analyzer(STANDARD)
+ .searchAnalyzer(KEEP_MAIL_AND_URL)
+ .fields(RAW, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().normalizer(CASE_INSENSITIVE).build())
+ .build())
+ .build())
+ .build()
+ ))
+ .build())
+ .build())
+ .put(JsonMessageConstants.BCC, new Property.Builder()
+ .object(new ObjectProperty.Builder()
+ .properties(ImmutableMap.of(
+ JsonMessageConstants.EMailer.NAME, new Property.Builder()
+ .text(new TextProperty.Builder().analyzer(KEEP_MAIL_AND_URL).build())
+ .build(),
+ JsonMessageConstants.EMailer.DOMAIN, new Property.Builder()
+ .text(new TextProperty.Builder()
+ .analyzer(SIMPLE)
+ .searchAnalyzer(KEYWORD)
+ .build())
+ .build(),
+ JsonMessageConstants.EMailer.ADDRESS, new Property.Builder()
+ .text(new TextProperty.Builder()
+ .analyzer(STANDARD)
+ .searchAnalyzer(KEEP_MAIL_AND_URL)
+ .fields(RAW, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().normalizer(CASE_INSENSITIVE).build())
+ .build())
+ .build())
+ .build()
+ ))
+ .build())
+ .build())
+ .put(JsonMessageConstants.MAILBOX_ID, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().store(true).build())
+ .build())
+ .put(JsonMessageConstants.MIME_MESSAGE_ID, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().build())
+ .build())
+ .put(JsonMessageConstants.TEXT_BODY, new Property.Builder()
+ .text(new TextProperty.Builder().analyzer(STANDARD).build())
+ .build())
+ .put(JsonMessageConstants.HTML_BODY, new Property.Builder()
+ .text(new TextProperty.Builder().analyzer(STANDARD).build())
+ .build())
+ .put(JsonMessageConstants.HAS_ATTACHMENT, new Property.Builder()
+ .boolean_(new BooleanProperty.Builder().build())
+ .build())
+ .put(JsonMessageConstants.ATTACHMENTS, new Property.Builder()
+ .object(new ObjectProperty.Builder()
+ .properties(ImmutableMap.of(
+ JsonMessageConstants.Attachment.FILENAME, new Property.Builder()
+ .text(new TextProperty.Builder().analyzer(STANDARD).build())
+ .build(),
+ JsonMessageConstants.Attachment.TEXT_CONTENT, new Property.Builder()
+ .text(new TextProperty.Builder().analyzer(STANDARD).build())
+ .build(),
+ JsonMessageConstants.Attachment.MEDIA_TYPE, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().build())
+ .build(),
+ JsonMessageConstants.Attachment.SUBTYPE, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().build())
+ .build(),
+ JsonMessageConstants.Attachment.FILE_EXTENSION, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().build())
+ .build(),
+ JsonMessageConstants.Attachment.CONTENT_DISPOSITION, new Property.Builder()
+ .keyword(new KeywordProperty.Builder().build())
+ .build()
+ ))
+ .build())
+ .build())
+ .build();
}
}
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 6b78c920d3..420d734d31 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
@@ -28,12 +28,10 @@ import static org.apache.james.mailbox.opensearch.json.JsonMessageConstants.IS_U
import static org.apache.james.mailbox.opensearch.json.JsonMessageConstants.MAILBOX_ID;
import static org.apache.james.mailbox.opensearch.json.JsonMessageConstants.MESSAGE_ID;
import static org.apache.james.mailbox.opensearch.json.JsonMessageConstants.UID;
-import static org.opensearch.index.query.QueryBuilders.termQuery;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
-import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -63,14 +61,20 @@ import org.apache.james.mailbox.opensearch.search.OpenSearchSearcher;
import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
import org.apache.james.mailbox.store.mail.model.MailboxMessage;
import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
-import org.opensearch.action.get.GetResponse;
-import org.opensearch.common.document.DocumentField;
-import org.opensearch.index.query.TermQueryBuilder;
-import org.opensearch.search.SearchHit;
+import org.opensearch.client.json.JsonData;
+import org.opensearch.client.json.JsonpDeserializer;
+import org.opensearch.client.opensearch._types.FieldValue;
+import org.opensearch.client.opensearch._types.query_dsl.Query;
+import org.opensearch.client.opensearch._types.query_dsl.TermQuery;
+import org.opensearch.client.opensearch.core.GetResponse;
+import org.opensearch.client.opensearch.core.search.Hit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.fge.lambdas.Throwing;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -193,12 +197,12 @@ public class OpenSearchListeningMessageSearchIndex extends ListeningMessageSearc
@Override
public Mono<Void> deleteAll(MailboxSession session, MailboxId mailboxId) {
- TermQueryBuilder queryBuilder = termQuery(
- MAILBOX_ID,
- mailboxId.serialize());
+ Query query = TermQuery.of(t -> t
+ .field(MAILBOX_ID)
+ .value(new FieldValue.Builder().stringValue(mailboxId.serialize()).build()))._toQuery();
return openSearchIndexer
- .deleteAllMatchingQuery(queryBuilder, routingKeyFactory.from(mailboxId));
+ .deleteAllMatchingQuery(query, routingKeyFactory.from(mailboxId));
}
@Override
@@ -237,12 +241,12 @@ public class OpenSearchListeningMessageSearchIndex extends ListeningMessageSearc
RoutingKey routingKey = routingKeyFactory.from(mailbox.getMailboxId());
return openSearchIndexer.get(indexIdFor(mailbox.getMailboxId(), uid), routingKey)
- .filter(GetResponse::isExists)
- .map(GetResponse::getSourceAsMap)
+ .filter(GetResponse::found)
+ .map(GetResponse::source)
.map(this::extractFlags);
}
- private Flags extractFlags(Map<String, Object> source) {
+ private Flags extractFlags(ObjectNode source) {
FlagsBuilder flagsBuilder = FlagsBuilder.builder()
.isAnswered(extractFlag(source, IS_ANSWERED))
.isDeleted(extractFlag(source, IS_DELETED))
@@ -251,37 +255,38 @@ public class OpenSearchListeningMessageSearchIndex extends ListeningMessageSearc
.isRecent(extractFlag(source, IS_RECENT))
.isSeen(!extractFlag(source, IS_UNREAD));
- for (String userFlag : extractUserFlags(source)) {
- flagsBuilder.add(userFlag);
+ for (JsonNode userFlag : extractUserFlags(source)) {
+ flagsBuilder.add(userFlag.textValue());
}
return flagsBuilder.build();
}
- private boolean extractFlag(Map<String, Object> source, String flag) {
- return (Boolean) source.get(flag);
+ private boolean extractFlag(ObjectNode source, String flag) {
+ return source.get(flag).asBoolean();
}
- private List<String> extractUserFlags(Map<String, Object> source) {
- return (List<String>) source.get("userFlags");
+ private ArrayNode extractUserFlags(ObjectNode source) {
+ return source.withArray("userFlags");
}
- private void extractMessageIdFromHit(SearchHit hit, SynchronousSink<MessageId> sink) {
- DocumentField messageId = hit.field(MESSAGE_ID);
+ private void extractMessageIdFromHit(Hit<ObjectNode> hit, SynchronousSink<MessageId> sink) {
+ JsonData messageId = hit.fields().get(MESSAGE_ID);
if (messageId != null) {
- sink.next(messageIdFactory.fromString(messageId.getValue()));
+ List<String> extractMessageId = messageId.deserialize(JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()));
+ sink.next(messageIdFactory.fromString(extractMessageId.get(0)));
} else {
- LOGGER.warn("Can not extract UID, MessageID and/or MailboxId for search result {}", hit.getId());
+ LOGGER.warn("Can not extract UID, MessageID and/or MailboxId for search result {}", hit.id());
}
}
- private void extractUidFromHit(SearchHit hit, SynchronousSink<MessageUid> sink) {
- DocumentField uid = hit.field(UID);
+ private void extractUidFromHit(Hit<ObjectNode> hit, SynchronousSink<MessageUid> sink) {
+ JsonData uid = hit.fields().get(UID);
if (uid != null) {
- Number uidAsNumber = uid.getValue();
- sink.next(MessageUid.of(uidAsNumber.longValue()));
+ List<Number> uidAsNumber = uid.deserialize(JsonpDeserializer.arrayDeserializer(JsonpDeserializer.numberDeserializer()));
+ sink.next(MessageUid.of(uidAsNumber.get(0).longValue()));
} else {
- LOGGER.warn("Can not extract UID, MessageID and/or MailboxId for search result {}", hit.getId());
+ LOGGER.warn("Can not extract UID, MessageID and/or MailboxId for search result {}", hit.id());
}
}
}
diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/CriterionConverter.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/CriterionConverter.java
index 7513fda265..d7b019c8ce 100644
--- a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/CriterionConverter.java
+++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/CriterionConverter.java
@@ -20,12 +20,6 @@
package org.apache.james.mailbox.opensearch.query;
import static org.apache.james.backends.opensearch.IndexCreationFactory.RAW;
-import static org.opensearch.index.query.QueryBuilders.boolQuery;
-import static org.opensearch.index.query.QueryBuilders.matchAllQuery;
-import static org.opensearch.index.query.QueryBuilders.matchQuery;
-import static org.opensearch.index.query.QueryBuilders.nestedQuery;
-import static org.opensearch.index.query.QueryBuilders.rangeQuery;
-import static org.opensearch.index.query.QueryBuilders.termQuery;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
@@ -34,7 +28,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
-import java.util.stream.Collector;
import java.util.stream.Stream;
import javax.mail.Flags;
@@ -44,15 +37,21 @@ import org.apache.james.mailbox.model.SearchQuery.Criterion;
import org.apache.james.mailbox.model.SearchQuery.HeaderOperator;
import org.apache.james.mailbox.opensearch.json.HeaderCollection;
import org.apache.james.mailbox.opensearch.json.JsonMessageConstants;
-import org.apache.lucene.search.join.ScoreMode;
-import org.opensearch.index.query.BoolQueryBuilder;
-import org.opensearch.index.query.QueryBuilder;
-import org.opensearch.index.query.QueryBuilders;
+import org.opensearch.client.json.JsonData;
+import org.opensearch.client.opensearch._types.FieldValue;
+import org.opensearch.client.opensearch._types.query_dsl.BoolQuery;
+import org.opensearch.client.opensearch._types.query_dsl.ChildScoreMode;
+import org.opensearch.client.opensearch._types.query_dsl.MatchAllQuery;
+import org.opensearch.client.opensearch._types.query_dsl.MatchQuery;
+import org.opensearch.client.opensearch._types.query_dsl.NestedQuery;
+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.TermQuery;
public class CriterionConverter {
- private final Map<Class<?>, Function<Criterion, QueryBuilder>> criterionConverterMap;
- private final Map<Class<?>, BiFunction<String, HeaderOperator, QueryBuilder>> headerOperatorConverterMap;
+ private final Map<Class<?>, Function<Criterion, Query>> criterionConverterMap;
+ private final Map<Class<?>, BiFunction<String, HeaderOperator, Query>> headerOperatorConverterMap;
public CriterionConverter() {
criterionConverterMap = new HashMap<>();
@@ -72,7 +71,7 @@ public class CriterionConverter {
registerCriterionConverter(SearchQuery.CustomFlagCriterion.class, this::convertCustomFlagCriterion);
registerCriterionConverter(SearchQuery.AllCriterion.class,
- criterion -> matchAllQuery());
+ criterion -> new MatchAllQuery.Builder().build()._toQuery());
registerCriterionConverter(SearchQuery.ModSeqCriterion.class,
criterion -> createNumericFilter(JsonMessageConstants.MODSEQ, criterion.getOperator()));
@@ -92,17 +91,23 @@ public class CriterionConverter {
}
@SuppressWarnings("unchecked")
- private <T extends Criterion> void registerCriterionConverter(Class<T> type, Function<T, QueryBuilder> f) {
- criterionConverterMap.put(type, (Function<Criterion, QueryBuilder>) f);
+ private <T extends Criterion> void registerCriterionConverter(Class<T> type, Function<T, Query> f) {
+ criterionConverterMap.put(type, (Function<Criterion, Query>) f);
}
private void registerHeaderOperatorConverters() {
registerHeaderOperatorConverter(
SearchQuery.ExistsOperator.class,
- (headerName, operator) ->
- nestedQuery(JsonMessageConstants.HEADERS,
- termQuery(JsonMessageConstants.HEADERS + "." + JsonMessageConstants.HEADER.NAME, headerName),
- ScoreMode.Avg));
+ (headerName, operator) -> new NestedQuery.Builder()
+ .path(JsonMessageConstants.HEADERS)
+ .query(new TermQuery.Builder()
+ .field(JsonMessageConstants.HEADERS + "." + JsonMessageConstants.HEADER.NAME)
+ .value(new FieldValue.Builder().stringValue(headerName).build())
+ .build()
+ ._toQuery())
+ .scoreMode(ChildScoreMode.Avg)
+ .build()
+ ._toQuery());
registerHeaderOperatorConverter(
SearchQuery.AddressOperator.class,
@@ -114,71 +119,136 @@ public class CriterionConverter {
registerHeaderOperatorConverter(
SearchQuery.ContainsOperator.class,
- (headerName, operator) ->
- nestedQuery(JsonMessageConstants.HEADERS,
- boolQuery()
- .must(termQuery(JsonMessageConstants.HEADERS + "." + JsonMessageConstants.HEADER.NAME, headerName))
- .must(matchQuery(JsonMessageConstants.HEADERS + "." + JsonMessageConstants.HEADER.VALUE, operator.getValue())),
- ScoreMode.Avg));
+ (headerName, operator) -> new NestedQuery.Builder()
+ .path(JsonMessageConstants.HEADERS)
+ .query(new BoolQuery.Builder()
+ .must(new TermQuery.Builder()
+ .field(JsonMessageConstants.HEADERS + "." + JsonMessageConstants.HEADER.NAME)
+ .value(new FieldValue.Builder().stringValue(headerName).build())
+ .build()
+ ._toQuery())
+ .must(new MatchQuery.Builder()
+ .field(JsonMessageConstants.HEADERS + "." + JsonMessageConstants.HEADER.VALUE)
+ .query(new FieldValue.Builder().stringValue(operator.getValue()).build())
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery())
+ .scoreMode(ChildScoreMode.Avg)
+ .build()
+ ._toQuery());
}
@SuppressWarnings("unchecked")
- private <T extends HeaderOperator> void registerHeaderOperatorConverter(Class<T> type, BiFunction<String, T, QueryBuilder> f) {
- headerOperatorConverterMap.put(type, (BiFunction<String, HeaderOperator, QueryBuilder>) f);
+ private <T extends HeaderOperator> void registerHeaderOperatorConverter(Class<T> type, BiFunction<String, T, Query> f) {
+ headerOperatorConverterMap.put(type, (BiFunction<String, HeaderOperator, Query>) f);
}
- public QueryBuilder convertCriterion(Criterion criterion) {
+ public Query convertCriterion(Criterion criterion) {
return criterionConverterMap.get(criterion.getClass()).apply(criterion);
}
- private QueryBuilder convertAttachmentCriterion(SearchQuery.AttachmentCriterion criterion) {
- return termQuery(JsonMessageConstants.HAS_ATTACHMENT, criterion.getOperator().isSet());
+ private Query convertAttachmentCriterion(SearchQuery.AttachmentCriterion criterion) {
+ return new TermQuery.Builder()
+ .field(JsonMessageConstants.HAS_ATTACHMENT)
+ .value(new FieldValue.Builder().booleanValue(criterion.getOperator().isSet()).build())
+ .build()
+ ._toQuery();
}
- private QueryBuilder convertMimeMessageIDCriterion(SearchQuery.MimeMessageIDCriterion criterion) {
- return termQuery(JsonMessageConstants.MIME_MESSAGE_ID, criterion.getMessageID());
+ private Query convertMimeMessageIDCriterion(SearchQuery.MimeMessageIDCriterion criterion) {
+ return new TermQuery.Builder()
+ .field(JsonMessageConstants.MIME_MESSAGE_ID)
+ .value(new FieldValue.Builder().stringValue(criterion.getMessageID()).build())
+ .build()
+ ._toQuery();
}
- private QueryBuilder convertThreadIdCriterion(SearchQuery.ThreadIdCriterion criterion) {
- return termQuery(JsonMessageConstants.THREAD_ID, criterion.getThreadId().serialize());
+ private Query convertThreadIdCriterion(SearchQuery.ThreadIdCriterion criterion) {
+ return new TermQuery.Builder()
+ .field(JsonMessageConstants.THREAD_ID)
+ .value(new FieldValue.Builder().stringValue(criterion.getThreadId().serialize()).build())
+ .build()
+ ._toQuery();
}
- private QueryBuilder convertCustomFlagCriterion(SearchQuery.CustomFlagCriterion criterion) {
- QueryBuilder termQueryBuilder = termQuery(JsonMessageConstants.USER_FLAGS, criterion.getFlag());
+ private Query convertCustomFlagCriterion(SearchQuery.CustomFlagCriterion criterion) {
+ Query termQuery = new TermQuery.Builder()
+ .field(JsonMessageConstants.USER_FLAGS)
+ .value(new FieldValue.Builder().stringValue(criterion.getFlag()).build())
+ .build()
+ ._toQuery();
if (criterion.getOperator().isSet()) {
- return termQueryBuilder;
+ return termQuery;
} else {
- return boolQuery().mustNot(termQueryBuilder);
+ return new BoolQuery.Builder()
+ .mustNot(termQuery)
+ .build()
+ ._toQuery();
}
}
- private QueryBuilder convertTextCriterion(SearchQuery.TextCriterion textCriterion) {
+ private Query convertTextCriterion(SearchQuery.TextCriterion textCriterion) {
switch (textCriterion.getType()) {
case BODY:
- return boolQuery()
- .should(matchQuery(JsonMessageConstants.TEXT_BODY, textCriterion.getOperator().getValue()))
- .should(matchQuery(JsonMessageConstants.HTML_BODY, textCriterion.getOperator().getValue()));
+ return new BoolQuery.Builder()
+ .should(new MatchQuery.Builder()
+ .field(JsonMessageConstants.TEXT_BODY)
+ .query(new FieldValue.Builder().stringValue(textCriterion.getOperator().getValue()).build())
+ .build()
+ ._toQuery())
+ .should(new MatchQuery.Builder()
+ .field(JsonMessageConstants.HTML_BODY)
+ .query(new FieldValue.Builder().stringValue(textCriterion.getOperator().getValue()).build())
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
case FULL:
- return boolQuery()
- .should(matchQuery(JsonMessageConstants.TEXT_BODY, textCriterion.getOperator().getValue()))
- .should(matchQuery(JsonMessageConstants.HTML_BODY, textCriterion.getOperator().getValue()))
- .should(matchQuery(JsonMessageConstants.ATTACHMENTS + "." + JsonMessageConstants.Attachment.TEXT_CONTENT,
- textCriterion.getOperator().getValue()));
+ return new BoolQuery.Builder()
+ .should(new MatchQuery.Builder()
+ .field(JsonMessageConstants.TEXT_BODY)
+ .query(new FieldValue.Builder().stringValue(textCriterion.getOperator().getValue()).build())
+ .build()
+ ._toQuery())
+ .should(new MatchQuery.Builder()
+ .field(JsonMessageConstants.HTML_BODY)
+ .query(new FieldValue.Builder().stringValue(textCriterion.getOperator().getValue()).build())
+ .build()
+ ._toQuery())
+ .should(new MatchQuery.Builder()
+ .field(JsonMessageConstants.ATTACHMENTS + "." + JsonMessageConstants.Attachment.TEXT_CONTENT)
+ .query(new FieldValue.Builder().stringValue(textCriterion.getOperator().getValue()).build())
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
case ATTACHMENTS:
- return boolQuery()
- .should(matchQuery(JsonMessageConstants.ATTACHMENTS + "." + JsonMessageConstants.Attachment.TEXT_CONTENT,
- textCriterion.getOperator().getValue()));
+ return new BoolQuery.Builder()
+ .should(new MatchQuery.Builder()
+ .field(JsonMessageConstants.ATTACHMENTS + "." + JsonMessageConstants.Attachment.TEXT_CONTENT)
+ .query(new FieldValue.Builder().stringValue(textCriterion.getOperator().getValue()).build())
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
case ATTACHMENT_FILE_NAME:
- return boolQuery()
- .should(termQuery(JsonMessageConstants.ATTACHMENTS + "." + JsonMessageConstants.Attachment.FILENAME,
- textCriterion.getOperator().getValue()));
+ return new BoolQuery.Builder()
+ .should(new MatchQuery.Builder()
+ .field(JsonMessageConstants.ATTACHMENTS + "." + JsonMessageConstants.Attachment.FILENAME)
+ .query(new FieldValue.Builder().stringValue(textCriterion.getOperator().getValue()).build())
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
+ default:
+ throw new RuntimeException("Unknown SCOPE for text criterion");
}
- throw new RuntimeException("Unknown SCOPE for text criterion");
}
- private QueryBuilder dateRangeFilter(String field, SearchQuery.DateOperator dateOperator) {
- return boolQuery().filter(
- convertDateOperator(field,
+ private Query dateRangeFilter(String field, SearchQuery.DateOperator dateOperator) {
+ return new BoolQuery.Builder()
+ .filter(convertDateOperator(field,
dateOperator.getType(),
DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(
DateResolutionFormatter.computeLowerDate(
@@ -187,104 +257,197 @@ public class CriterionConverter {
DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(
DateResolutionFormatter.computeUpperDate(
DateResolutionFormatter.convertDateToZonedDateTime(dateOperator.getDate()),
- dateOperator.getDateResultion()))));
+ dateOperator.getDateResultion()))))
+ .build()
+ ._toQuery();
}
- private BoolQueryBuilder convertConjunction(SearchQuery.ConjunctionCriterion criterion) {
+ private Query convertConjunction(SearchQuery.ConjunctionCriterion criterion) {
return convertToBoolQuery(criterion.getCriteria().stream().map(this::convertCriterion),
convertConjunctionType(criterion.getType()));
}
- private BiFunction<BoolQueryBuilder, QueryBuilder, BoolQueryBuilder> convertConjunctionType(SearchQuery.Conjunction type) {
+ private BiFunction<BoolQuery.Builder, Query, BoolQuery.Builder> convertConjunctionType(SearchQuery.Conjunction type) {
switch (type) {
case AND:
- return BoolQueryBuilder::must;
+ return BoolQuery.Builder::must;
case OR:
- return BoolQueryBuilder::should;
+ return BoolQuery.Builder::should;
case NOR:
- return BoolQueryBuilder::mustNot;
+ return BoolQuery.Builder::mustNot;
default:
throw new RuntimeException("Unexpected conjunction criteria " + type);
}
}
@SuppressWarnings("ReturnValueIgnored")
- private BoolQueryBuilder convertToBoolQuery(Stream<QueryBuilder> stream, BiFunction<BoolQueryBuilder, QueryBuilder, BoolQueryBuilder> addCriterionToBoolQuery) {
- return stream.collect(Collector.of(QueryBuilders::boolQuery,
- addCriterionToBoolQuery::apply,
- addCriterionToBoolQuery::apply));
+ private Query convertToBoolQuery(Stream<Query> stream, BiFunction<BoolQuery.Builder, Query, BoolQuery.Builder> addCriterionToBoolQuery) {
+ BoolQuery.Builder builder = new BoolQuery.Builder();
+ stream.forEach(query -> addCriterionToBoolQuery.apply(builder, query));
+ return builder.build()._toQuery();
}
- private QueryBuilder convertFlag(SearchQuery.FlagCriterion flagCriterion) {
+ private Query convertFlag(SearchQuery.FlagCriterion flagCriterion) {
SearchQuery.BooleanOperator operator = flagCriterion.getOperator();
Flags.Flag flag = flagCriterion.getFlag();
if (flag.equals(Flags.Flag.DELETED)) {
- return boolQuery().filter(termQuery(JsonMessageConstants.IS_DELETED, operator.isSet()));
+ return new BoolQuery.Builder()
+ .filter(new TermQuery.Builder()
+ .field(JsonMessageConstants.IS_DELETED)
+ .value(new FieldValue.Builder().booleanValue(operator.isSet()).build())
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
}
if (flag.equals(Flags.Flag.ANSWERED)) {
- return boolQuery().filter(termQuery(JsonMessageConstants.IS_ANSWERED, operator.isSet()));
+ return new BoolQuery.Builder()
+ .filter(new TermQuery.Builder()
+ .field(JsonMessageConstants.IS_ANSWERED)
+ .value(new FieldValue.Builder().booleanValue(operator.isSet()).build())
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
}
if (flag.equals(Flags.Flag.DRAFT)) {
- return boolQuery().filter(termQuery(JsonMessageConstants.IS_DRAFT, operator.isSet()));
+ return new BoolQuery.Builder()
+ .filter(new TermQuery.Builder()
+ .field(JsonMessageConstants.IS_DRAFT)
+ .value(new FieldValue.Builder().booleanValue(operator.isSet()).build())
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
}
if (flag.equals(Flags.Flag.SEEN)) {
- return boolQuery().filter(termQuery(JsonMessageConstants.IS_UNREAD, !operator.isSet()));
+ return new BoolQuery.Builder()
+ .filter(new TermQuery.Builder()
+ .field(JsonMessageConstants.IS_UNREAD)
+ .value(new FieldValue.Builder().booleanValue(!operator.isSet()).build())
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
}
if (flag.equals(Flags.Flag.RECENT)) {
- return boolQuery().filter(termQuery(JsonMessageConstants.IS_RECENT, operator.isSet()));
+ return new BoolQuery.Builder()
+ .filter(new TermQuery.Builder()
+ .field(JsonMessageConstants.IS_RECENT)
+ .value(new FieldValue.Builder().booleanValue(operator.isSet()).build())
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
}
if (flag.equals(Flags.Flag.FLAGGED)) {
- return boolQuery().filter(termQuery(JsonMessageConstants.IS_FLAGGED, operator.isSet()));
+ return new BoolQuery.Builder()
+ .filter(new TermQuery.Builder()
+ .field(JsonMessageConstants.IS_FLAGGED)
+ .value(new FieldValue.Builder().booleanValue(operator.isSet()).build())
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
}
throw new RuntimeException("Unknown flag used in Flag search criterion");
}
- private QueryBuilder createNumericFilter(String fieldName, SearchQuery.NumericOperator operator) {
+ private Query createNumericFilter(String fieldName, SearchQuery.NumericOperator operator) {
switch (operator.getType()) {
case EQUALS:
- return boolQuery().filter(rangeQuery(fieldName).gte(operator.getValue()).lte(operator.getValue()));
+ return new BoolQuery.Builder()
+ .filter(new RangeQuery.Builder()
+ .field(fieldName)
+ .gte(JsonData.of(operator.getValue()))
+ .lte(JsonData.of(operator.getValue()))
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
case GREATER_THAN:
- return boolQuery().filter(rangeQuery(fieldName).gt(operator.getValue()));
+ return new BoolQuery.Builder()
+ .filter(new RangeQuery.Builder()
+ .field(fieldName)
+ .gt(JsonData.of(operator.getValue()))
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
case LESS_THAN:
- return boolQuery().filter(rangeQuery(fieldName).lt(operator.getValue()));
+ return new BoolQuery.Builder()
+ .filter(new RangeQuery.Builder()
+ .field(fieldName)
+ .lt(JsonData.of(operator.getValue()))
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
default:
throw new RuntimeException("A non existing numeric operator was triggered");
}
}
- private BoolQueryBuilder convertUid(SearchQuery.UidCriterion uidCriterion) {
+ private Query convertUid(SearchQuery.UidCriterion uidCriterion) {
if (uidCriterion.getOperator().getRange().length == 0) {
- return boolQuery();
+ return new BoolQuery.Builder().build()._toQuery();
}
- return boolQuery().filter(
- convertToBoolQuery(
+ return new BoolQuery.Builder()
+ .filter(convertToBoolQuery(
Arrays.stream(uidCriterion.getOperator().getRange())
- .map(this::uidRangeFilter), BoolQueryBuilder::should));
+ .map(this::uidRangeFilter), BoolQuery.Builder::should))
+ .build()
+ ._toQuery();
}
- private QueryBuilder convertMessageId(SearchQuery.MessageIdCriterion messageIdCriterion) {
- return termQuery(JsonMessageConstants.MESSAGE_ID, messageIdCriterion.getMessageId().serialize());
+ private Query convertMessageId(SearchQuery.MessageIdCriterion messageIdCriterion) {
+ return new TermQuery.Builder()
+ .field(JsonMessageConstants.MESSAGE_ID)
+ .value(new FieldValue.Builder().stringValue(messageIdCriterion.getMessageId().serialize()).build())
+ .build()
+ ._toQuery();
}
- private QueryBuilder uidRangeFilter(SearchQuery.UidRange numericRange) {
- return rangeQuery(JsonMessageConstants.UID)
- .lte(numericRange.getHighValue().asLong())
- .gte(numericRange.getLowValue().asLong());
+ private Query uidRangeFilter(SearchQuery.UidRange numericRange) {
+ return new RangeQuery.Builder()
+ .field(JsonMessageConstants.UID)
+ .lte(JsonData.of(numericRange.getHighValue().asLong()))
+ .gte(JsonData.of(numericRange.getLowValue().asLong()))
+ .build()
+ ._toQuery();
}
- private QueryBuilder convertHeader(SearchQuery.HeaderCriterion headerCriterion) {
+ private Query convertHeader(SearchQuery.HeaderCriterion headerCriterion) {
return headerOperatorConverterMap.get(headerCriterion.getOperator().getClass())
.apply(
headerCriterion.getHeaderName().toLowerCase(Locale.US),
headerCriterion.getOperator());
}
- private QueryBuilder manageAddressFields(String headerName, String value) {
- return boolQuery()
- .should(matchQuery(getFieldNameFromHeaderName(headerName) + "." + JsonMessageConstants.EMailer.NAME, value))
- .should(matchQuery(getFieldNameFromHeaderName(headerName) + "." + JsonMessageConstants.EMailer.ADDRESS, value))
- .should(matchQuery(getFieldNameFromHeaderName(headerName) + "." + JsonMessageConstants.EMailer.DOMAIN, value))
- .should(matchQuery(getFieldNameFromHeaderName(headerName) + "." + JsonMessageConstants.EMailer.ADDRESS + "." + RAW, value));
+ private Query manageAddressFields(String headerName, String value) {
+ return new BoolQuery.Builder()
+ .should(new MatchQuery.Builder()
+ .field(getFieldNameFromHeaderName(headerName) + "." + JsonMessageConstants.EMailer.NAME)
+ .query(new FieldValue.Builder().stringValue(value).build())
+ .build()
+ ._toQuery())
+ .should(new MatchQuery.Builder()
+ .field(getFieldNameFromHeaderName(headerName) + "." + JsonMessageConstants.EMailer.ADDRESS)
+ .query(new FieldValue.Builder().stringValue(value).build())
+ .build()
+ ._toQuery())
+ .should(new MatchQuery.Builder()
+ .field(getFieldNameFromHeaderName(headerName) + "." + JsonMessageConstants.EMailer.DOMAIN)
+ .query(new FieldValue.Builder().stringValue(value).build())
+ .build()
+ ._toQuery())
+ .should(new MatchQuery.Builder()
+ .field(getFieldNameFromHeaderName(headerName) + "." + JsonMessageConstants.EMailer.ADDRESS + "." + RAW)
+ .query(new FieldValue.Builder().stringValue(value).build())
+ .build()
+ ._toQuery())
+ .build()
+ ._toQuery();
}
private String getFieldNameFromHeaderName(String headerName) {
@@ -297,20 +460,35 @@ public class CriterionConverter {
return JsonMessageConstants.BCC;
case HeaderCollection.FROM:
return JsonMessageConstants.FROM;
+ default:
+ throw new RuntimeException("Header not recognized as Addess Header : " + headerName);
}
- throw new RuntimeException("Header not recognized as Addess Header : " + headerName);
}
- private QueryBuilder convertDateOperator(String field, SearchQuery.DateComparator dateComparator, String lowDateString, String upDateString) {
+ private Query convertDateOperator(String field, SearchQuery.DateComparator dateComparator, String lowDateString, String upDateString) {
switch (dateComparator) {
case BEFORE:
- return rangeQuery(field).lt(lowDateString); // less than start of the current day
+ return new RangeQuery.Builder()
+ .field(field)
+ .lt(JsonData.of(upDateString))
+ .build()
+ ._toQuery();
case AFTER:
- return rangeQuery(field).gte(upDateString); // start of next day + greater than that
+ return new RangeQuery.Builder()
+ .field(field)
+ .gte(JsonData.of(lowDateString))
+ .build()
+ ._toQuery();
case ON:
- return rangeQuery(field).lt(upDateString).gte(lowDateString);
+ return new RangeQuery.Builder()
+ .field(field)
+ .lt(JsonData.of(upDateString))
+ .gte(JsonData.of(lowDateString))
+ .build()
+ ._toQuery();
+ default:
+ throw new RuntimeException("Unknown date operator");
}
- throw new RuntimeException("Unknown date operator");
}
}
diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/QueryConverter.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/QueryConverter.java
index 1f6a34cf7e..e2d451a469 100644
--- a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/QueryConverter.java
+++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/QueryConverter.java
@@ -19,9 +19,6 @@
package org.apache.james.mailbox.opensearch.query;
-import static org.opensearch.index.query.QueryBuilders.boolQuery;
-import static org.opensearch.index.query.QueryBuilders.termsQuery;
-
import java.util.Collection;
import java.util.List;
import java.util.Optional;
@@ -31,14 +28,15 @@ import javax.inject.Inject;
import org.apache.james.mailbox.model.MailboxId;
import org.apache.james.mailbox.model.SearchQuery;
import org.apache.james.mailbox.opensearch.json.JsonMessageConstants;
-import org.opensearch.index.query.BoolQueryBuilder;
-import org.opensearch.index.query.QueryBuilder;
+import org.opensearch.client.opensearch._types.FieldValue;
+import org.opensearch.client.opensearch._types.query_dsl.BoolQuery;
+import org.opensearch.client.opensearch._types.query_dsl.Query;
+import org.opensearch.client.opensearch._types.query_dsl.TermsQuery;
+import org.opensearch.client.opensearch._types.query_dsl.TermsQueryField;
import com.google.common.collect.ImmutableList;
public class QueryConverter {
-
-
private final CriterionConverter criterionConverter;
@Inject
@@ -46,15 +44,15 @@ public class QueryConverter {
this.criterionConverter = criterionConverter;
}
- public QueryBuilder from(Collection<MailboxId> mailboxIds, SearchQuery query) {
- BoolQueryBuilder boolQueryBuilder = boolQuery()
+ public Query from(Collection<MailboxId> mailboxIds, SearchQuery query) {
+ BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder()
.must(generateQueryBuilder(query));
mailboxesQuery(mailboxIds).map(boolQueryBuilder::filter);
- return boolQueryBuilder;
+ return boolQueryBuilder.build()._toQuery();
}
- private QueryBuilder generateQueryBuilder(SearchQuery searchQuery) {
+ private Query generateQueryBuilder(SearchQuery searchQuery) {
List<SearchQuery.Criterion> criteria = searchQuery.getCriteria();
if (criteria.isEmpty()) {
return criterionConverter.convertCriterion(SearchQuery.all());
@@ -65,14 +63,21 @@ public class QueryConverter {
}
}
- private Optional<QueryBuilder> mailboxesQuery(Collection<MailboxId> mailboxIds) {
+ private Optional<Query> mailboxesQuery(Collection<MailboxId> mailboxIds) {
if (mailboxIds.isEmpty()) {
return Optional.empty();
}
- ImmutableList<String> ids = mailboxIds.stream()
- .map(MailboxId::serialize)
- .collect(ImmutableList.toImmutableList());
- return Optional.of(termsQuery(JsonMessageConstants.MAILBOX_ID, ids));
+ ImmutableList<FieldValue> ids = mailboxIds.stream()
+ .map(MailboxId::serialize)
+ .map(id -> new FieldValue.Builder().stringValue(id).build())
+ .collect(ImmutableList.toImmutableList());
+ return Optional.of(new TermsQuery.Builder()
+ .field(JsonMessageConstants.MAILBOX_ID)
+ .terms(new TermsQueryField.Builder()
+ .value(ids)
+ .build())
+ .build()
+ ._toQuery());
}
}
diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/SortConverter.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/SortConverter.java
index e1216a951f..cf4bb8d91e 100644
--- a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/SortConverter.java
+++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/query/SortConverter.java
@@ -22,44 +22,44 @@ package org.apache.james.mailbox.opensearch.query;
import org.apache.james.backends.opensearch.IndexCreationFactory;
import org.apache.james.mailbox.model.SearchQuery;
import org.apache.james.mailbox.opensearch.json.JsonMessageConstants;
-import org.opensearch.search.sort.FieldSortBuilder;
-import org.opensearch.search.sort.SortBuilders;
-import org.opensearch.search.sort.SortMode;
-import org.opensearch.search.sort.SortOrder;
+import org.opensearch.client.opensearch._types.FieldSort;
+import org.opensearch.client.opensearch._types.SortMode;
+import org.opensearch.client.opensearch._types.SortOrder;
public class SortConverter {
private static final String PATH_SEPARATOR = ".";
- public static FieldSortBuilder convertSort(SearchQuery.Sort sort) {
+ public static FieldSort convertSort(SearchQuery.Sort sort) {
return getSortClause(sort.getSortClause())
.order(getOrder(sort))
- .sortMode(SortMode.MIN);
+ .mode(SortMode.Min)
+ .build();
}
- private static FieldSortBuilder getSortClause(SearchQuery.Sort.SortClause clause) {
+ private static FieldSort.Builder getSortClause(SearchQuery.Sort.SortClause clause) {
switch (clause) {
case Arrival :
- return SortBuilders.fieldSort(JsonMessageConstants.DATE);
+ return new FieldSort.Builder().field(JsonMessageConstants.DATE);
case MailboxCc :
- return SortBuilders.fieldSort(JsonMessageConstants.CC + PATH_SEPARATOR + JsonMessageConstants.EMailer.ADDRESS
- + PATH_SEPARATOR + IndexCreationFactory.RAW);
+ return new FieldSort.Builder().field(JsonMessageConstants.CC + PATH_SEPARATOR
+ + JsonMessageConstants.EMailer.ADDRESS + PATH_SEPARATOR + IndexCreationFactory.RAW);
case MailboxFrom :
- return SortBuilders.fieldSort(JsonMessageConstants.FROM + PATH_SEPARATOR + JsonMessageConstants.EMailer.ADDRESS
- + PATH_SEPARATOR + IndexCreationFactory.RAW);
+ return new FieldSort.Builder().field(JsonMessageConstants.FROM + PATH_SEPARATOR
+ + JsonMessageConstants.EMailer.ADDRESS + PATH_SEPARATOR + IndexCreationFactory.RAW);
case MailboxTo :
- return SortBuilders.fieldSort(JsonMessageConstants.TO + PATH_SEPARATOR + JsonMessageConstants.EMailer.ADDRESS
- + PATH_SEPARATOR + IndexCreationFactory.RAW);
+ return new FieldSort.Builder().field(JsonMessageConstants.TO + PATH_SEPARATOR
+ + JsonMessageConstants.EMailer.ADDRESS + PATH_SEPARATOR + IndexCreationFactory.RAW);
case BaseSubject :
- return SortBuilders.fieldSort(JsonMessageConstants.SUBJECT + PATH_SEPARATOR + IndexCreationFactory.RAW);
+ return new FieldSort.Builder().field(JsonMessageConstants.SUBJECT + PATH_SEPARATOR + IndexCreationFactory.RAW);
case Size :
- return SortBuilders.fieldSort(JsonMessageConstants.SIZE);
+ return new FieldSort.Builder().field(JsonMessageConstants.SIZE);
case SentDate :
- return SortBuilders.fieldSort(JsonMessageConstants.SENT_DATE);
+ return new FieldSort.Builder().field(JsonMessageConstants.SENT_DATE);
case Uid :
- return SortBuilders.fieldSort(JsonMessageConstants.UID);
+ return new FieldSort.Builder().field(JsonMessageConstants.UID);
case Id:
- return SortBuilders.fieldSort(JsonMessageConstants.MESSAGE_ID);
+ return new FieldSort.Builder().field(JsonMessageConstants.MESSAGE_ID);
default:
throw new RuntimeException("Sort is not implemented");
}
@@ -67,9 +67,9 @@ public class SortConverter {
private static SortOrder getOrder(SearchQuery.Sort sort) {
if (sort.isReverse()) {
- return SortOrder.DESC;
+ return SortOrder.Desc;
} else {
- return SortOrder.ASC;
+ return SortOrder.Asc;
}
}
}
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 f1bfcecfc6..7b7f4acd97 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
@@ -22,6 +22,7 @@ package org.apache.james.mailbox.opensearch.search;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
+import java.util.stream.Collectors;
import org.apache.james.backends.opensearch.AliasName;
import org.apache.james.backends.opensearch.ReactorOpenSearchClient;
@@ -32,16 +33,18 @@ import org.apache.james.mailbox.model.MailboxId;
import org.apache.james.mailbox.model.SearchQuery;
import org.apache.james.mailbox.opensearch.query.QueryConverter;
import org.apache.james.mailbox.opensearch.query.SortConverter;
-import org.opensearch.action.search.SearchRequest;
-import org.opensearch.common.unit.TimeValue;
-import org.opensearch.search.SearchHit;
-import org.opensearch.search.builder.SearchSourceBuilder;
+import org.opensearch.client.opensearch._types.SortOptions;
+import org.opensearch.client.opensearch._types.Time;
+import org.opensearch.client.opensearch.core.SearchRequest;
+import org.opensearch.client.opensearch.core.search.Hit;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
import reactor.core.publisher.Flux;
public class OpenSearchSearcher {
public static final int DEFAULT_SEARCH_SIZE = 100;
- private static final TimeValue TIMEOUT = TimeValue.timeValueMinutes(1);
+ private static final Time TIMEOUT = new Time.Builder().time("1m").build();
private static final int MAX_ROUTING_KEY = 5;
private final ReactorOpenSearchClient client;
@@ -59,39 +62,40 @@ public class OpenSearchSearcher {
this.routingKeyFactory = routingKeyFactory;
}
- public Flux<SearchHit> search(Collection<MailboxId> mailboxIds, SearchQuery query,
- Optional<Integer> limit, List<String> fields) {
+ public Flux<Hit<ObjectNode>> search(Collection<MailboxId> mailboxIds, SearchQuery query,
+ Optional<Integer> limit, List<String> fields) {
SearchRequest searchRequest = prepareSearch(mailboxIds, query, limit, fields);
return new ScrolledSearch(client, searchRequest)
.searchHits();
}
private SearchRequest prepareSearch(Collection<MailboxId> mailboxIds, SearchQuery query, Optional<Integer> limit, List<String> fields) {
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
- .query(queryConverter.from(mailboxIds, query))
- .size(computeRequiredSize(limit))
- .storedFields(fields);
-
- query.getSorts()
+ List<SortOptions> sorts = query.getSorts()
.stream()
.map(SortConverter::convertSort)
- .forEach(searchSourceBuilder::sort);
+ .map(fieldSort -> new SortOptions.Builder().field(fieldSort).build())
+ .collect(Collectors.toList());
- SearchRequest request = new SearchRequest(aliasName.getValue())
+ SearchRequest.Builder request = new SearchRequest.Builder()
+ .index(aliasName.getValue())
.scroll(TIMEOUT)
- .source(searchSourceBuilder);
+ .query(queryConverter.from(mailboxIds, query))
+ .size(computeRequiredSize(limit))
+ .storedFields(fields)
+ .sort(sorts);
return toRoutingKey(mailboxIds)
.map(request::routing)
- .orElse(request);
+ .orElse(request)
+ .build();
}
- private Optional<String[]> toRoutingKey(Collection<MailboxId> mailboxIds) {
+ private Optional<String> toRoutingKey(Collection<MailboxId> mailboxIds) {
if (mailboxIds.size() < MAX_ROUTING_KEY) {
return Optional.of(mailboxIds.stream()
.map(routingKeyFactory::from)
.map(RoutingKey::asString)
- .toArray(String[]::new));
+ .collect(Collectors.joining(",")));
}
return Optional.empty();
}
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 19f05f1c78..c87203b756 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
@@ -63,11 +63,9 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
-import org.opensearch.action.search.SearchRequest;
-import org.opensearch.client.RequestOptions;
-import org.opensearch.index.query.QueryBuilder;
-import org.opensearch.index.query.QueryBuilders;
-import org.opensearch.search.builder.SearchSourceBuilder;
+import org.opensearch.client.opensearch._types.query_dsl.Query;
+import org.opensearch.client.opensearch._types.query_dsl.QueryBuilders;
+import org.opensearch.client.opensearch.core.SearchRequest;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
@@ -172,7 +170,7 @@ class OpenSearchIntegrationTest extends AbstractMessageSearchIndexTest {
.setBody(Strings.repeat("0à2345678é", 3200), StandardCharsets.UTF_8)),
session).getId();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 14);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 14);
assertThat(Flux.from(messageManager.search(SearchQuery.of(SearchQuery.address(SearchQuery.AddressType.To, recipient)), session)).toStream())
.containsExactly(composedMessageId.getUid());
@@ -193,11 +191,12 @@ class OpenSearchIntegrationTest extends AbstractMessageSearchIndexTest {
CALMLY_AWAIT.atMost(Durations.TEN_SECONDS)
.untilAsserted(() -> assertThat(client.search(
- new SearchRequest(MailboxOpenSearchConstants.DEFAULT_MAILBOX_INDEX.getValue())
- .source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery())),
- RequestOptions.DEFAULT)
+ new SearchRequest.Builder()
+ .index(MailboxOpenSearchConstants.DEFAULT_MAILBOX_INDEX.getValue())
+ .query(QueryBuilders.matchAll().build()._toQuery())
+ .build())
.block()
- .getHits().getTotalHits().value).isGreaterThanOrEqualTo(14));
+ .hits().total().value()).isEqualTo(14));
assertThat(Flux.from(messageManager.search(SearchQuery.of(SearchQuery.address(SearchQuery.AddressType.To, recipient)), session)).toStream())
.containsExactly(composedMessageId.getUid());
@@ -216,7 +215,7 @@ class OpenSearchIntegrationTest extends AbstractMessageSearchIndexTest {
.setBody(Strings.repeat("0123456789 ", 5000), StandardCharsets.UTF_8)),
session).getId();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 14);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 14);
assertThat(Flux.from(messageManager.search(SearchQuery.of(SearchQuery.bodyContains("0123456789")), session)).toStream())
.containsExactly(composedMessageId.getUid());
@@ -235,7 +234,7 @@ class OpenSearchIntegrationTest extends AbstractMessageSearchIndexTest {
.setBody(Strings.repeat("0123456789 ", 5000) + " matchMe", StandardCharsets.UTF_8)),
session).getId();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 14);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 14);
assertThat(Flux.from(messageManager.search(SearchQuery.of(SearchQuery.bodyContains("matchMe")), session)).toStream())
.containsExactly(composedMessageId.getUid());
@@ -277,7 +276,7 @@ class OpenSearchIntegrationTest extends AbstractMessageSearchIndexTest {
.build(ClassLoaderUtils.getSystemResourceAsSharedStream("eml/mailCustomStringHeader.eml")),
session).getId();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 15);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 15);
assertThat(Flux.from(messageManager.search(SearchQuery.of(SearchQuery.headerExists("Custom-header")), session)).toStream())
.containsExactly(customDateHeaderMessageId.getUid(), customStringHeaderMessageId.getUid());
@@ -330,7 +329,7 @@ class OpenSearchIntegrationTest extends AbstractMessageSearchIndexTest {
.build()),
session).getId();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 15);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 15);
assertThat(Flux.from(messageManager.search(SearchQuery.of(SearchQuery.address(SearchQuery.AddressType.To, "bob@other.tld")), session)).toStream())
.containsOnly(messageId2.getUid());
@@ -361,13 +360,19 @@ class OpenSearchIntegrationTest extends AbstractMessageSearchIndexTest {
.build()),
session).getId();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 15);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 15);
Thread.sleep(500);
assertThat(Flux.from(messageManager.search(SearchQuery.of(SearchQuery.address(SearchQuery.AddressType.To, "other")), session)).toStream())
.containsOnly(messageId2.getUid());
}
+ @Disabled("JAMES-3771 Waiting for a fix on opensearch client to be merged: https://github.com/opensearch-project/opensearch-java/pull/169")
+ @Test
+ public void sortOnCcShouldWork() throws Exception {
+
+ }
+
@Disabled("MAILBOX-403 Relaxed the matching constraints for email addresses in text bodies to reduce OpenSearch disk space usage")
@Test
public void textShouldNotMatchOtherAddressesOfTheSameDomain() {
@@ -470,13 +475,14 @@ class OpenSearchIntegrationTest extends AbstractMessageSearchIndexTest {
.containsOnly(messageId1.getUid());
}
- private void awaitForOpenSearch(QueryBuilder query, long totalHits) {
+ private void awaitForOpenSearch(Query query, long totalHits) {
CALMLY_AWAIT.atMost(Durations.TEN_SECONDS)
.untilAsserted(() -> assertThat(client.search(
- new SearchRequest(MailboxOpenSearchConstants.DEFAULT_MAILBOX_INDEX.getValue())
- .source(new SearchSourceBuilder().query(query)),
- RequestOptions.DEFAULT)
+ new SearchRequest.Builder()
+ .index(MailboxOpenSearchConstants.DEFAULT_MAILBOX_INDEX.getValue())
+ .query(query)
+ .build())
.block()
- .getHits().getTotalHits().value).isEqualTo(totalHits));
+ .hits().total().value()).isEqualTo(totalHits));
}
}
\ No newline at end of file
diff --git a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndexTest.java b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndexTest.java
index ce34fbe26b..bf3025cbf2 100644
--- a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndexTest.java
+++ b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndexTest.java
@@ -86,11 +86,10 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
-import org.opensearch.action.search.SearchRequest;
-import org.opensearch.client.RequestOptions;
-import org.opensearch.index.query.QueryBuilder;
-import org.opensearch.index.query.QueryBuilders;
-import org.opensearch.search.builder.SearchSourceBuilder;
+import org.opensearch.client.opensearch._types.FieldValue;
+import org.opensearch.client.opensearch._types.query_dsl.Query;
+import org.opensearch.client.opensearch._types.query_dsl.QueryBuilders;
+import org.opensearch.client.opensearch.core.SearchRequest;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -219,7 +218,7 @@ class OpenSearchListeningMessageSearchIndexTest {
@Test
void addShouldIndexMessageWithoutAttachment() throws Exception {
testee.add(session, mailbox, MESSAGE_1).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 1L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 1L);
SearchQuery query = SearchQuery.of(SearchQuery.all());
assertThat(testee.search(session, mailbox, query).toStream())
@@ -229,7 +228,7 @@ class OpenSearchListeningMessageSearchIndexTest {
@Test
void addShouldIndexMessageWithAttachment() throws Exception {
testee.add(session, mailbox, MESSAGE_WITH_ATTACHMENT).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 1L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 1L);
SearchQuery query = SearchQuery.of(SearchQuery.all());
assertThat(testee.search(session, mailbox, query).toStream())
@@ -241,7 +240,7 @@ class OpenSearchListeningMessageSearchIndexTest {
testee.add(session, mailbox, MESSAGE_1).block();
testee.add(session, mailbox, MESSAGE_1).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 1L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 1L);
SearchQuery query = SearchQuery.of(SearchQuery.all());
assertThat(testee.search(session, mailbox, query).toStream())
@@ -253,7 +252,7 @@ class OpenSearchListeningMessageSearchIndexTest {
testee.add(session, mailbox, MESSAGE_1).block();
testee.add(session, mailbox, MESSAGE_2).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 2L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 2L);
SearchQuery query = SearchQuery.of(SearchQuery.all());
assertThat(testee.search(session, mailbox, query).toStream())
@@ -272,7 +271,7 @@ class OpenSearchListeningMessageSearchIndexTest {
messageToOpenSearchJson, sessionProvider, new MailboxIdRoutingKeyFactory(), new InMemoryMessageId.Factory());
testee.add(session, mailbox, MESSAGE_WITH_ATTACHMENT).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 1L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 1L);
SearchQuery query = SearchQuery.of(SearchQuery.all());
assertThat(testee.search(session, mailbox, query).toStream())
@@ -293,10 +292,10 @@ class OpenSearchListeningMessageSearchIndexTest {
@Test
void deleteShouldRemoveIndex() throws Exception {
testee.add(session, mailbox, MESSAGE_1).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 1L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 1L);
testee.delete(session, mailbox.getMailboxId(), Lists.newArrayList(MESSAGE_UID_1)).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 0L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 0L);
SearchQuery query = SearchQuery.of(SearchQuery.all());
assertThat(testee.search(session, mailbox, query).toStream())
@@ -307,10 +306,10 @@ class OpenSearchListeningMessageSearchIndexTest {
void deleteShouldOnlyRemoveIndexesPassedAsArguments() throws Exception {
testee.add(session, mailbox, MESSAGE_1).block();
testee.add(session, mailbox, MESSAGE_2).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 2L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 2L);
testee.delete(session, mailbox.getMailboxId(), Lists.newArrayList(MESSAGE_UID_1)).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 1L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 1L);
SearchQuery query = SearchQuery.of(SearchQuery.all());
assertThat(testee.search(session, mailbox, query).toStream())
@@ -321,10 +320,10 @@ class OpenSearchListeningMessageSearchIndexTest {
void deleteShouldRemoveMultipleIndexes() throws Exception {
testee.add(session, mailbox, MESSAGE_1).block();
testee.add(session, mailbox, MESSAGE_2).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 2L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 2L);
testee.delete(session, mailbox.getMailboxId(), Lists.newArrayList(MESSAGE_UID_1, MESSAGE_UID_2)).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 0L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 0L);
SearchQuery query = SearchQuery.of(SearchQuery.all());
assertThat(testee.search(session, mailbox, query).toStream())
@@ -334,11 +333,11 @@ class OpenSearchListeningMessageSearchIndexTest {
@Test
void deleteShouldBeIdempotent() throws Exception {
testee.add(session, mailbox, MESSAGE_1).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 1L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 1L);
testee.delete(session, mailbox.getMailboxId(), Lists.newArrayList(MESSAGE_UID_1)).block();
testee.delete(session, mailbox.getMailboxId(), Lists.newArrayList(MESSAGE_UID_1)).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 0L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 0L);
SearchQuery query = SearchQuery.of(SearchQuery.all());
assertThat(testee.search(session, mailbox, query).toStream())
@@ -365,7 +364,7 @@ class OpenSearchListeningMessageSearchIndexTest {
@Test
void updateShouldUpdateIndex() throws Exception {
testee.add(session, mailbox, MESSAGE_1).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 1L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 1L);
Flags newFlags = new Flags(Flags.Flag.ANSWERED);
UpdatedFlags updatedFlags = UpdatedFlags.builder()
@@ -376,7 +375,7 @@ class OpenSearchListeningMessageSearchIndexTest {
.build();
testee.update(session, mailbox.getMailboxId(), Lists.newArrayList(updatedFlags)).block();
- awaitForOpenSearch(QueryBuilders.termQuery("isAnswered", true), 1L);
+ awaitForOpenSearch(QueryBuilders.term().field("isAnswered").value(FieldValue.of(true)).build()._toQuery(), 1L);
SearchQuery query = SearchQuery.of(SearchQuery.flagIsSet(Flags.Flag.ANSWERED));
assertThat(testee.search(session, mailbox, query).toStream())
@@ -384,9 +383,9 @@ class OpenSearchListeningMessageSearchIndexTest {
}
@Test
- void updateShouldNotUpdateNorThrowOnUnknownMessageUid() throws Exception {
+ void updateShouldThrowOnUnknownMessageUid() throws Exception {
testee.add(session, mailbox, MESSAGE_1).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 1L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 1L);
Flags newFlags = new Flags(Flags.Flag.ANSWERED);
UpdatedFlags updatedFlags = UpdatedFlags.builder()
@@ -406,7 +405,7 @@ class OpenSearchListeningMessageSearchIndexTest {
@Test
void updateShouldBeIdempotent() throws Exception {
testee.add(session, mailbox, MESSAGE_1).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 1L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 1L);
Flags newFlags = new Flags(Flags.Flag.ANSWERED);
UpdatedFlags updatedFlags = UpdatedFlags.builder()
@@ -418,7 +417,7 @@ class OpenSearchListeningMessageSearchIndexTest {
testee.update(session, mailbox.getMailboxId(), Lists.newArrayList(updatedFlags)).block();
testee.update(session, mailbox.getMailboxId(), Lists.newArrayList(updatedFlags)).block();
- awaitForOpenSearch(QueryBuilders.termQuery("isAnswered", true), 1L);
+ awaitForOpenSearch(QueryBuilders.term().field("isAnswered").value(FieldValue.of(true)).build()._toQuery(), 1L);
SearchQuery query = SearchQuery.of(SearchQuery.flagIsSet(Flags.Flag.ANSWERED));
assertThat(testee.search(session, mailbox, query).toStream())
@@ -448,10 +447,10 @@ class OpenSearchListeningMessageSearchIndexTest {
void deleteAllShouldRemoveAllIndexes() throws Exception {
testee.add(session, mailbox, MESSAGE_1).block();
testee.add(session, mailbox, MESSAGE_2).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 2L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 2L);
testee.deleteAll(session, mailbox.getMailboxId()).block();
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), 0L);
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), 0L);
SearchQuery query = SearchQuery.of(SearchQuery.all());
assertThat(testee.search(session, mailbox, query).toStream())
@@ -483,18 +482,21 @@ class OpenSearchListeningMessageSearchIndexTest {
@Test
void retrieveIndexedFlagsShouldReturnEmptyWhenNotFound() {
+ testee.add(session, mailbox, MESSAGE_1).block();
+
assertThat(testee.retrieveIndexedFlags(mailbox, MESSAGE_UID_4).blockOptional())
.isEmpty();
}
}
- private void awaitForOpenSearch(QueryBuilder query, long totalHits) {
+ private void awaitForOpenSearch(Query query, long totalHits) {
CALMLY_AWAIT.atMost(Durations.TEN_SECONDS)
.untilAsserted(() -> assertThat(client.search(
- new SearchRequest(MailboxOpenSearchConstants.DEFAULT_MAILBOX_INDEX.getValue())
- .source(new SearchSourceBuilder().query(query)),
- RequestOptions.DEFAULT)
+ new SearchRequest.Builder()
+ .index(MailboxOpenSearchConstants.DEFAULT_MAILBOX_INDEX.getValue())
+ .query(query)
+ .build())
.block()
- .getHits().getTotalHits().value).isEqualTo(totalHits));
+ .hits().total().value()).isEqualTo(totalHits));
}
}
\ No newline at end of file
diff --git a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcherTest.java b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcherTest.java
index 9c24556392..70fbde8e8b 100644
--- a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcherTest.java
+++ b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcherTest.java
@@ -67,11 +67,9 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
-import org.opensearch.action.search.SearchRequest;
-import org.opensearch.client.RequestOptions;
-import org.opensearch.index.query.QueryBuilder;
-import org.opensearch.index.query.QueryBuilders;
-import org.opensearch.search.builder.SearchSourceBuilder;
+import org.opensearch.client.opensearch._types.query_dsl.Query;
+import org.opensearch.client.opensearch._types.query_dsl.QueryBuilders;
+import org.opensearch.client.opensearch.core.SearchRequest;
import com.github.fge.lambdas.Throwing;
import com.google.common.collect.ImmutableList;
@@ -157,7 +155,7 @@ class OpenSearchSearcherTest {
.map(Throwing.<MailboxPath, ComposedMessageId>function(mailboxPath -> addMessage(session, mailboxPath)).sneakyThrow())
.collect(ImmutableList.toImmutableList());
- awaitForOpenSearch(QueryBuilders.matchAllQuery(), composedMessageIds.size());
+ awaitForOpenSearch(QueryBuilders.matchAll().build()._toQuery(), composedMessageIds.size());
MultimailboxesSearchQuery multimailboxesSearchQuery = MultimailboxesSearchQuery
.from(SearchQuery.of(SearchQuery.all()))
@@ -184,13 +182,14 @@ class OpenSearchSearcherTest {
.getId();
}
- private void awaitForOpenSearch(QueryBuilder query, long totalHits) {
+ private void awaitForOpenSearch(Query query, long totalHits) {
CALMLY_AWAIT.atMost(Durations.TEN_SECONDS)
.untilAsserted(() -> assertThat(client.search(
- new SearchRequest(MailboxOpenSearchConstants.DEFAULT_MAILBOX_INDEX.getValue())
- .source(new SearchSourceBuilder().query(query)),
- RequestOptions.DEFAULT)
+ new SearchRequest.Builder()
+ .index(MailboxOpenSearchConstants.DEFAULT_MAILBOX_INDEX.getValue())
+ .query(query)
+ .build())
.block()
- .getHits().getTotalHits().value).isEqualTo(totalHits));
+ .hits().total().value()).isEqualTo(totalHits));
}
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org