Skip to content

Commit 75cb0e6

Browse files
authored
Add moreLikeThis operator to Atlas Search (#1609)
Add moreLikeThis operator to Atlas Search There are several Atlas Search query operators that are not implemented with first class support in the Java driver. This PR adds the moreLikeThis operator to Atlas Search. JAVA-5740
1 parent 927c732 commit 75cb0e6

File tree

7 files changed

+131
-0
lines changed

7 files changed

+131
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.mongodb.client.model.search;
17+
18+
import com.mongodb.annotations.Beta;
19+
import com.mongodb.annotations.Reason;
20+
import com.mongodb.annotations.Sealed;
21+
import org.bson.BsonDocument;
22+
23+
/**
24+
* @see SearchOperator#moreLikeThis(BsonDocument)
25+
* @see SearchOperator#moreLikeThis(Iterable)
26+
* @since 4.7
27+
*/
28+
@Sealed
29+
@Beta(Reason.CLIENT)
30+
public interface MoreLikeThisSearchOperator extends SearchOperator {
31+
@Override
32+
TextSearchOperator score(SearchScore modifier);
33+
}

driver-core/src/main/com/mongodb/client/model/search/SearchConstructibleBsonElement.java

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ final class SearchConstructibleBsonElement extends AbstractConstructibleBsonElem
3232
MustCompoundSearchOperator, MustNotCompoundSearchOperator, ShouldCompoundSearchOperator, FilterCompoundSearchOperator,
3333
ExistsSearchOperator, TextSearchOperator, AutocompleteSearchOperator,
3434
NumberNearSearchOperator, DateNearSearchOperator, GeoNearSearchOperator, RegexSearchOperator, QueryStringSearchOperator, WildcardSearchOperator,
35+
MoreLikeThisSearchOperator,
3536
ValueBoostSearchScore, PathBoostSearchScore, ConstantSearchScore, FunctionSearchScore,
3637
GaussSearchScoreExpression, PathSearchScoreExpression,
3738
FacetSearchCollector,

driver-core/src/main/com/mongodb/client/model/search/SearchOperator.java

+26
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.mongodb.annotations.Sealed;
2121
import com.mongodb.client.model.Aggregates;
2222
import com.mongodb.client.model.geojson.Point;
23+
import org.bson.BsonDocument;
2324
import org.bson.BsonType;
2425
import org.bson.Document;
2526
import org.bson.conversions.Bson;
@@ -292,6 +293,31 @@ static GeoNearSearchOperator near(final Point origin, final Number pivot, final
292293
.append("pivot", notNull("pivot", pivot)));
293294
}
294295

296+
/**
297+
* Returns a {@link SearchOperator} that returns documents similar to input document.
298+
*
299+
* @param like The BSON document that is used to extract representative terms to query for.
300+
* @return The requested {@link SearchOperator}.
301+
* @mongodb.atlas.manual atlas-search/morelikethis/ moreLikeThis operator
302+
*/
303+
static MoreLikeThisSearchOperator moreLikeThis(final BsonDocument like) {
304+
return moreLikeThis(singleton(notNull("like", like)));
305+
}
306+
307+
/**
308+
* Returns a {@link SearchOperator} that returns documents similar to input documents.
309+
*
310+
* @param likes The BSON documents that are used to extract representative terms to query for.
311+
* @return The requested {@link SearchOperator}.
312+
* @mongodb.atlas.manual atlas-search/morelikethis/ moreLikeThis operator
313+
*/
314+
static MoreLikeThisSearchOperator moreLikeThis(final Iterable<BsonDocument> likes) {
315+
Iterator<? extends BsonDocument> likesIterator = notNull("likes", likes).iterator();
316+
isTrueArgument("likes must not be empty", likesIterator.hasNext());
317+
BsonDocument firstLike = likesIterator.next();
318+
return new SearchConstructibleBsonElement("moreLikeThis", new Document("like", likesIterator.hasNext() ? likes : firstLike));
319+
}
320+
295321
/**
296322
* Returns a {@link SearchOperator} that supports querying a combination of indexed fields and values.
297323
*

driver-core/src/test/functional/com/mongodb/client/model/search/AggregatesSearchIntegrationTest.java

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.mongodb.client.model.geojson.Position;
2424
import com.mongodb.client.test.CollectionHelper;
2525
import org.bson.BsonDocument;
26+
import org.bson.BsonString;
2627
import org.bson.codecs.BsonDocumentCodec;
2728
import org.bson.conversions.Bson;
2829
import org.bson.json.JsonWriterSettings;
@@ -80,6 +81,7 @@
8081
import static com.mongodb.client.model.search.SearchOperator.compound;
8182
import static com.mongodb.client.model.search.SearchOperator.dateRange;
8283
import static com.mongodb.client.model.search.SearchOperator.exists;
84+
import static com.mongodb.client.model.search.SearchOperator.moreLikeThis;
8385
import static com.mongodb.client.model.search.SearchOperator.near;
8486
import static com.mongodb.client.model.search.SearchOperator.numberRange;
8587
import static com.mongodb.client.model.search.SearchOperator.queryString;
@@ -616,6 +618,8 @@ private static Stream<Arguments> searchAndSearchMetaArgs() {
616618
phrase(fieldPath("fieldName10"), "term6"),
617619
regex(fieldPath("title").multi("keyword"), "term7"),
618620
queryString(fieldPath("fieldName12"), "term8"),
621+
moreLikeThis(new BsonDocument("like", new BsonDocument("fieldName10",
622+
new BsonString("term6")))),
619623
wildcard(asList("term10", "term11"), asList(wildcardPath("wildc*rd"), fieldPath("title").multi(
620624
"keyword")))
621625
))

driver-core/src/test/unit/com/mongodb/client/model/search/SearchOperatorTest.java

+40
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,46 @@ void near() {
581581
);
582582
}
583583

584+
@Test
585+
void moreLikeThis() {
586+
assertAll(
587+
() -> assertThrows(IllegalArgumentException.class, () ->
588+
// likes must not be empty
589+
SearchOperator.moreLikeThis(emptyList())
590+
),
591+
() -> assertEquals(
592+
new BsonDocument("moreLikeThis",
593+
new BsonDocument("like", new BsonDocument("fieldName", new BsonString("fieldValue")))
594+
),
595+
SearchOperator.moreLikeThis(new BsonDocument("fieldName", new BsonString("fieldValue")))
596+
.toBsonDocument()
597+
),
598+
() -> assertEquals(
599+
new BsonDocument("moreLikeThis",
600+
new BsonDocument("like", new BsonDocument("fieldName", new BsonString("fieldValue"))
601+
.append("fieldName2", new BsonString("fieldValue2")))
602+
),
603+
SearchOperator.moreLikeThis(new BsonDocument("fieldName", new BsonString("fieldValue"))
604+
.append("fieldName2", new BsonString("fieldValue2")))
605+
.toBsonDocument()
606+
),
607+
() -> assertEquals(
608+
new BsonDocument("moreLikeThis",
609+
new BsonDocument("like", new BsonArray(asList(
610+
new BsonDocument("fieldName", new BsonString("fieldValue"))
611+
.append("fieldName2", new BsonString("fieldValue2")),
612+
new BsonDocument("fieldName3", new BsonString("fieldValue3"))
613+
)))
614+
),
615+
SearchOperator.moreLikeThis(asList(
616+
new BsonDocument("fieldName", new BsonString("fieldValue"))
617+
.append("fieldName2", new BsonString("fieldValue2")),
618+
new BsonDocument("fieldName3", new BsonString("fieldValue3"))))
619+
.toBsonDocument()
620+
)
621+
);
622+
}
623+
584624
@Test
585625
void wildcard() {
586626
assertAll(

driver-scala/src/main/scala/org/mongodb/scala/model/search/SearchOperator.scala

+20
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package org.mongodb.scala.model.search
1717

1818
import com.mongodb.annotations.{ Beta, Reason }
1919
import com.mongodb.client.model.search.{ SearchOperator => JSearchOperator }
20+
import org.mongodb.scala.bson.BsonDocument
2021
import org.mongodb.scala.bson.conversions.Bson
2122
import org.mongodb.scala.model.geojson.Point
2223

@@ -228,6 +229,25 @@ object SearchOperator {
228229
def near(origin: Point, pivot: Number, paths: Iterable[_ <: FieldSearchPath]): GeoNearSearchOperator =
229230
JSearchOperator.near(origin, pivot, paths.asJava)
230231

232+
/**
233+
* Returns a `SearchOperator` that returns documents similar to input document.
234+
*
235+
* @param like The BSON document that is used to extract representative terms to query for.
236+
* @return The requested `SearchOperator`.
237+
* @see [[https://www.mongodb.com/docs/atlas/atlas-search/morelikethis/ moreLikeThis operator]]
238+
*/
239+
def moreLikeThis(like: BsonDocument): MoreLikeThisSearchOperator = JSearchOperator.moreLikeThis(like)
240+
241+
/**
242+
* Returns a `SearchOperator` that returns documents similar to input documents.
243+
*
244+
* @param likes The BSON documents that are used to extract representative terms to query for.
245+
* @return The requested `SearchOperator`.
246+
* @see [[https://www.mongodb.com/docs/atlas/atlas-search/morelikethis/ moreLikeThis operator]]
247+
*/
248+
def moreLikeThis(likes: Iterable[BsonDocument]): MoreLikeThisSearchOperator =
249+
JSearchOperator.moreLikeThis(likes.asJava)
250+
231251
/**
232252
* Returns a `SearchOperator` that enables queries which use special characters in the search string that can match any character.
233253
*

driver-scala/src/main/scala/org/mongodb/scala/model/search/package.scala

+7
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,13 @@ package object search {
198198
@Beta(Array(Reason.CLIENT))
199199
type GeoNearSearchOperator = com.mongodb.client.model.search.GeoNearSearchOperator
200200

201+
/**
202+
* @see `SearchOperator.moreLikeThis`
203+
*/
204+
@Sealed
205+
@Beta(Array(Reason.CLIENT))
206+
type MoreLikeThisSearchOperator = com.mongodb.client.model.search.MoreLikeThisSearchOperator
207+
201208
/**
202209
* @see `SearchOperator.wildcard(String, SearchPath)`
203210
* @see `SearchOperator.wildcard(Iterable, Iterable)`

0 commit comments

Comments
 (0)