diff --git a/driver-core/src/main/com/mongodb/client/model/search/MoreLikeThisSearchOperator.java b/driver-core/src/main/com/mongodb/client/model/search/MoreLikeThisSearchOperator.java new file mode 100644 index 0000000000..b9f9826d85 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/search/MoreLikeThisSearchOperator.java @@ -0,0 +1,33 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.client.model.search; + +import com.mongodb.annotations.Beta; +import com.mongodb.annotations.Reason; +import com.mongodb.annotations.Sealed; +import org.bson.BsonDocument; + +/** + * @see SearchOperator#moreLikeThis(BsonDocument) + * @see SearchOperator#moreLikeThis(Iterable) + * @since 4.7 + */ +@Sealed +@Beta(Reason.CLIENT) +public interface MoreLikeThisSearchOperator extends SearchOperator { + @Override + TextSearchOperator score(SearchScore modifier); +} diff --git a/driver-core/src/main/com/mongodb/client/model/search/SearchConstructibleBsonElement.java b/driver-core/src/main/com/mongodb/client/model/search/SearchConstructibleBsonElement.java index b16f465157..6db68a7d6c 100644 --- a/driver-core/src/main/com/mongodb/client/model/search/SearchConstructibleBsonElement.java +++ b/driver-core/src/main/com/mongodb/client/model/search/SearchConstructibleBsonElement.java @@ -32,6 +32,7 @@ final class SearchConstructibleBsonElement extends AbstractConstructibleBsonElem MustCompoundSearchOperator, MustNotCompoundSearchOperator, ShouldCompoundSearchOperator, FilterCompoundSearchOperator, ExistsSearchOperator, TextSearchOperator, AutocompleteSearchOperator, NumberNearSearchOperator, DateNearSearchOperator, GeoNearSearchOperator, RegexSearchOperator, QueryStringSearchOperator, WildcardSearchOperator, + MoreLikeThisSearchOperator, ValueBoostSearchScore, PathBoostSearchScore, ConstantSearchScore, FunctionSearchScore, GaussSearchScoreExpression, PathSearchScoreExpression, FacetSearchCollector, diff --git a/driver-core/src/main/com/mongodb/client/model/search/SearchOperator.java b/driver-core/src/main/com/mongodb/client/model/search/SearchOperator.java index 7c0edeafd9..dada0331c4 100644 --- a/driver-core/src/main/com/mongodb/client/model/search/SearchOperator.java +++ b/driver-core/src/main/com/mongodb/client/model/search/SearchOperator.java @@ -20,6 +20,7 @@ import com.mongodb.annotations.Sealed; import com.mongodb.client.model.Aggregates; import com.mongodb.client.model.geojson.Point; +import org.bson.BsonDocument; import org.bson.BsonType; import org.bson.Document; import org.bson.conversions.Bson; @@ -292,6 +293,31 @@ static GeoNearSearchOperator near(final Point origin, final Number pivot, final .append("pivot", notNull("pivot", pivot))); } + /** + * Returns a {@link SearchOperator} that returns documents similar to input document. + * + * @param like The BSON document that is used to extract representative terms to query for. + * @return The requested {@link SearchOperator}. + * @mongodb.atlas.manual atlas-search/morelikethis/ moreLikeThis operator + */ + static MoreLikeThisSearchOperator moreLikeThis(final BsonDocument like) { + return moreLikeThis(singleton(notNull("like", like))); + } + + /** + * Returns a {@link SearchOperator} that returns documents similar to input documents. + * + * @param likes The BSON documents that are used to extract representative terms to query for. + * @return The requested {@link SearchOperator}. + * @mongodb.atlas.manual atlas-search/morelikethis/ moreLikeThis operator + */ + static MoreLikeThisSearchOperator moreLikeThis(final Iterable likes) { + Iterator likesIterator = notNull("likes", likes).iterator(); + isTrueArgument("likes must not be empty", likesIterator.hasNext()); + BsonDocument firstLike = likesIterator.next(); + return new SearchConstructibleBsonElement("moreLikeThis", new Document("like", likesIterator.hasNext() ? likes : firstLike)); + } + /** * Returns a {@link SearchOperator} that supports querying a combination of indexed fields and values. * diff --git a/driver-core/src/test/functional/com/mongodb/client/model/search/AggregatesSearchIntegrationTest.java b/driver-core/src/test/functional/com/mongodb/client/model/search/AggregatesSearchIntegrationTest.java index 91a0a9bd61..a8e0ad314b 100644 --- a/driver-core/src/test/functional/com/mongodb/client/model/search/AggregatesSearchIntegrationTest.java +++ b/driver-core/src/test/functional/com/mongodb/client/model/search/AggregatesSearchIntegrationTest.java @@ -23,6 +23,7 @@ import com.mongodb.client.model.geojson.Position; import com.mongodb.client.test.CollectionHelper; import org.bson.BsonDocument; +import org.bson.BsonString; import org.bson.codecs.BsonDocumentCodec; import org.bson.conversions.Bson; import org.bson.json.JsonWriterSettings; @@ -80,6 +81,7 @@ import static com.mongodb.client.model.search.SearchOperator.compound; import static com.mongodb.client.model.search.SearchOperator.dateRange; import static com.mongodb.client.model.search.SearchOperator.exists; +import static com.mongodb.client.model.search.SearchOperator.moreLikeThis; import static com.mongodb.client.model.search.SearchOperator.near; import static com.mongodb.client.model.search.SearchOperator.numberRange; import static com.mongodb.client.model.search.SearchOperator.queryString; @@ -616,6 +618,8 @@ private static Stream searchAndSearchMetaArgs() { phrase(fieldPath("fieldName10"), "term6"), regex(fieldPath("title").multi("keyword"), "term7"), queryString(fieldPath("fieldName12"), "term8"), + moreLikeThis(new BsonDocument("like", new BsonDocument("fieldName10", + new BsonString("term6")))), wildcard(asList("term10", "term11"), asList(wildcardPath("wildc*rd"), fieldPath("title").multi( "keyword"))) )) diff --git a/driver-core/src/test/unit/com/mongodb/client/model/search/SearchOperatorTest.java b/driver-core/src/test/unit/com/mongodb/client/model/search/SearchOperatorTest.java index a986b5a558..ef481ea03c 100644 --- a/driver-core/src/test/unit/com/mongodb/client/model/search/SearchOperatorTest.java +++ b/driver-core/src/test/unit/com/mongodb/client/model/search/SearchOperatorTest.java @@ -581,6 +581,46 @@ void near() { ); } + @Test + void moreLikeThis() { + assertAll( + () -> assertThrows(IllegalArgumentException.class, () -> + // likes must not be empty + SearchOperator.moreLikeThis(emptyList()) + ), + () -> assertEquals( + new BsonDocument("moreLikeThis", + new BsonDocument("like", new BsonDocument("fieldName", new BsonString("fieldValue"))) + ), + SearchOperator.moreLikeThis(new BsonDocument("fieldName", new BsonString("fieldValue"))) + .toBsonDocument() + ), + () -> assertEquals( + new BsonDocument("moreLikeThis", + new BsonDocument("like", new BsonDocument("fieldName", new BsonString("fieldValue")) + .append("fieldName2", new BsonString("fieldValue2"))) + ), + SearchOperator.moreLikeThis(new BsonDocument("fieldName", new BsonString("fieldValue")) + .append("fieldName2", new BsonString("fieldValue2"))) + .toBsonDocument() + ), + () -> assertEquals( + new BsonDocument("moreLikeThis", + new BsonDocument("like", new BsonArray(asList( + new BsonDocument("fieldName", new BsonString("fieldValue")) + .append("fieldName2", new BsonString("fieldValue2")), + new BsonDocument("fieldName3", new BsonString("fieldValue3")) + ))) + ), + SearchOperator.moreLikeThis(asList( + new BsonDocument("fieldName", new BsonString("fieldValue")) + .append("fieldName2", new BsonString("fieldValue2")), + new BsonDocument("fieldName3", new BsonString("fieldValue3")))) + .toBsonDocument() + ) + ); + } + @Test void wildcard() { assertAll( diff --git a/driver-scala/src/main/scala/org/mongodb/scala/model/search/SearchOperator.scala b/driver-scala/src/main/scala/org/mongodb/scala/model/search/SearchOperator.scala index bccb75b366..fc8f065b55 100644 --- a/driver-scala/src/main/scala/org/mongodb/scala/model/search/SearchOperator.scala +++ b/driver-scala/src/main/scala/org/mongodb/scala/model/search/SearchOperator.scala @@ -17,6 +17,7 @@ package org.mongodb.scala.model.search import com.mongodb.annotations.{ Beta, Reason } import com.mongodb.client.model.search.{ SearchOperator => JSearchOperator } +import org.mongodb.scala.bson.BsonDocument import org.mongodb.scala.bson.conversions.Bson import org.mongodb.scala.model.geojson.Point @@ -228,6 +229,25 @@ object SearchOperator { def near(origin: Point, pivot: Number, paths: Iterable[_ <: FieldSearchPath]): GeoNearSearchOperator = JSearchOperator.near(origin, pivot, paths.asJava) + /** + * Returns a `SearchOperator` that returns documents similar to input document. + * + * @param like The BSON document that is used to extract representative terms to query for. + * @return The requested `SearchOperator`. + * @see [[https://www.mongodb.com/docs/atlas/atlas-search/morelikethis/ moreLikeThis operator]] + */ + def moreLikeThis(like: BsonDocument): MoreLikeThisSearchOperator = JSearchOperator.moreLikeThis(like) + + /** + * Returns a `SearchOperator` that returns documents similar to input documents. + * + * @param likes The BSON documents that are used to extract representative terms to query for. + * @return The requested `SearchOperator`. + * @see [[https://www.mongodb.com/docs/atlas/atlas-search/morelikethis/ moreLikeThis operator]] + */ + def moreLikeThis(likes: Iterable[BsonDocument]): MoreLikeThisSearchOperator = + JSearchOperator.moreLikeThis(likes.asJava) + /** * Returns a `SearchOperator` that enables queries which use special characters in the search string that can match any character. * diff --git a/driver-scala/src/main/scala/org/mongodb/scala/model/search/package.scala b/driver-scala/src/main/scala/org/mongodb/scala/model/search/package.scala index 9fb3c9f4f4..135190347b 100644 --- a/driver-scala/src/main/scala/org/mongodb/scala/model/search/package.scala +++ b/driver-scala/src/main/scala/org/mongodb/scala/model/search/package.scala @@ -198,6 +198,13 @@ package object search { @Beta(Array(Reason.CLIENT)) type GeoNearSearchOperator = com.mongodb.client.model.search.GeoNearSearchOperator + /** + * @see `SearchOperator.moreLikeThis` + */ + @Sealed + @Beta(Array(Reason.CLIENT)) + type MoreLikeThisSearchOperator = com.mongodb.client.model.search.MoreLikeThisSearchOperator + /** * @see `SearchOperator.wildcard(String, SearchPath)` * @see `SearchOperator.wildcard(Iterable, Iterable)`