Skip to content

Commit 470fc2e

Browse files
joykim1005stIncMalekatcharov
authored
Add in operator to Atlas Search (#1605)
JAVA-5744 --------- Co-authored-by: Valentin Kovalenko <[email protected]> Co-authored-by: Maxim Katcharov <[email protected]> Co-authored-by: Valentin Kovalenko <[email protected]>
1 parent d3e81d8 commit 470fc2e

File tree

9 files changed

+371
-36
lines changed

9 files changed

+371
-36
lines changed

bson/src/main/org/bson/codecs/BsonArrayCodec.java

+3-9
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@
2323
import org.bson.BsonWriter;
2424
import org.bson.codecs.configuration.CodecRegistry;
2525

26-
import java.util.ArrayList;
27-
import java.util.List;
28-
2926
import static org.bson.assertions.Assertions.notNull;
3027
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
3128

@@ -60,16 +57,13 @@ public BsonArrayCodec(final CodecRegistry codecRegistry) {
6057

6158
@Override
6259
public BsonArray decode(final BsonReader reader, final DecoderContext decoderContext) {
60+
BsonArray bsonArray = new BsonArray();
6361
reader.readStartArray();
64-
65-
List<BsonValue> list = new ArrayList<>();
6662
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
67-
list.add(readValue(reader, decoderContext));
63+
bsonArray.add(readValue(reader, decoderContext));
6864
}
69-
7065
reader.readEndArray();
71-
72-
return new BsonArray(list);
66+
return bsonArray;
7367
}
7468

7569
@Override

driver-core/src/main/com/mongodb/client/model/mql/MqlValues.java

+15-15
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ public static MqlBoolean of(final boolean of) {
7474
*/
7575
public static MqlArray<MqlBoolean> ofBooleanArray(final boolean... array) {
7676
Assertions.notNull("array", array);
77-
List<BsonValue> list = new ArrayList<>();
77+
BsonArray bsonArray = new BsonArray();
7878
for (boolean b : array) {
79-
list.add(new BsonBoolean(b));
79+
bsonArray.add(new BsonBoolean(b));
8080
}
81-
return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonArray(list)));
81+
return new MqlExpression<>((cr) -> new AstPlaceholder(bsonArray));
8282
}
8383

8484
/**
@@ -102,11 +102,11 @@ public static MqlInteger of(final int of) {
102102
*/
103103
public static MqlArray<MqlInteger> ofIntegerArray(final int... array) {
104104
Assertions.notNull("array", array);
105-
List<BsonValue> list = new ArrayList<>();
105+
BsonArray bsonArray = new BsonArray();
106106
for (int i : array) {
107-
list.add(new BsonInt32(i));
107+
bsonArray.add(new BsonInt32(i));
108108
}
109-
return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonArray(list)));
109+
return new MqlExpression<>((cr) -> new AstPlaceholder(bsonArray));
110110
}
111111

112112
/**
@@ -130,11 +130,11 @@ public static MqlInteger of(final long of) {
130130
*/
131131
public static MqlArray<MqlInteger> ofIntegerArray(final long... array) {
132132
Assertions.notNull("array", array);
133-
List<BsonValue> list = new ArrayList<>();
133+
BsonArray bsonArray = new BsonArray();
134134
for (long i : array) {
135-
list.add(new BsonInt64(i));
135+
bsonArray.add(new BsonInt64(i));
136136
}
137-
return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonArray(list)));
137+
return new MqlExpression<>((cr) -> new AstPlaceholder(bsonArray));
138138
}
139139

140140
/**
@@ -158,11 +158,11 @@ public static MqlNumber of(final double of) {
158158
*/
159159
public static MqlArray<MqlNumber> ofNumberArray(final double... array) {
160160
Assertions.notNull("array", array);
161-
List<BsonValue> list = new ArrayList<>();
161+
BsonArray bsonArray = new BsonArray();
162162
for (double n : array) {
163-
list.add(new BsonDouble(n));
163+
bsonArray.add(new BsonDouble(n));
164164
}
165-
return new MqlExpression<>((cr) -> new AstPlaceholder(new BsonArray(list)));
165+
return new MqlExpression<>((cr) -> new AstPlaceholder(bsonArray));
166166
}
167167

168168
/**
@@ -310,12 +310,12 @@ public static MqlDocument current() {
310310
public static <T extends MqlValue> MqlArray<T> ofArray(final T... array) {
311311
Assertions.notNull("array", array);
312312
return new MqlExpression<>((cr) -> {
313-
List<BsonValue> list = new ArrayList<>();
313+
BsonArray bsonArray = new BsonArray();
314314
for (T v : array) {
315315
Assertions.notNull("elements of array", v);
316-
list.add(((MqlExpression<?>) v).toBsonValue(cr));
316+
bsonArray.add(((MqlExpression<?>) v).toBsonValue(cr));
317317
}
318-
return new AstPlaceholder(new BsonArray(list));
318+
return new AstPlaceholder(bsonArray);
319319
});
320320
}
321321

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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.types.ObjectId;
22+
23+
import java.time.Instant;
24+
import java.util.UUID;
25+
26+
/**
27+
* @see SearchOperator#in(FieldSearchPath, boolean, boolean...)
28+
* @see SearchOperator#in(FieldSearchPath, ObjectId, ObjectId...)
29+
* @see SearchOperator#in(FieldSearchPath, Number, Number...)
30+
* @see SearchOperator#in(FieldSearchPath, Instant, Instant...)
31+
* @see SearchOperator#in(FieldSearchPath, UUID, UUID...)
32+
* @see SearchOperator#in(FieldSearchPath, String, String...)
33+
* @see SearchOperator#in(FieldSearchPath, Iterable)
34+
* @since 5.3
35+
*/
36+
@Sealed
37+
@Beta(Reason.CLIENT)
38+
public interface InSearchOperator extends SearchOperator {
39+
@Override
40+
InSearchOperator score(SearchScore modifier);
41+
}

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

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

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

+117-7
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,26 @@
2020
import com.mongodb.annotations.Sealed;
2121
import com.mongodb.client.model.Aggregates;
2222
import com.mongodb.client.model.geojson.Point;
23-
24-
import java.util.UUID;
25-
23+
import org.bson.BsonArray;
2624
import org.bson.BsonBinary;
27-
import org.bson.BsonNull;
25+
import org.bson.BsonBoolean;
2826
import org.bson.BsonDocument;
27+
import org.bson.BsonNull;
2928
import org.bson.BsonType;
3029
import org.bson.Document;
3130
import org.bson.conversions.Bson;
31+
import org.bson.types.ObjectId;
3232

3333
import java.time.Duration;
3434
import java.time.Instant;
3535
import java.util.Iterator;
36-
37-
import org.bson.types.ObjectId;
36+
import java.util.UUID;
3837

3938
import static com.mongodb.assertions.Assertions.isTrueArgument;
39+
import static com.mongodb.assertions.Assertions.notNull;
4040
import static com.mongodb.internal.Iterables.concat;
4141
import static com.mongodb.internal.client.model.Util.combineToBsonValue;
4242
import static java.util.Collections.singleton;
43-
import static com.mongodb.assertions.Assertions.notNull;
4443

4544
/**
4645
* The core part of the {@link Aggregates#search(SearchOperator, SearchOptions) $search} pipeline stage of an aggregation pipeline.
@@ -300,6 +299,117 @@ static GeoNearSearchOperator near(final Point origin, final Number pivot, final
300299
.append("pivot", notNull("pivot", pivot)));
301300
}
302301

302+
/**
303+
* Returns a {@link SearchOperator} that searches for documents where the
304+
* value or array of values at a given path contains any of the specified values
305+
*
306+
* @param path The indexed field to be searched.
307+
* @param value The boolean value to search for.
308+
* @param values More fields to be searched.
309+
* @return The requested {@link SearchOperator}.
310+
* @mongodb.atlas.manual atlas-search/in/ in operator
311+
*/
312+
static InSearchOperator in(final FieldSearchPath path, final boolean value, final boolean... values) {
313+
notNull("values", values);
314+
BsonArray bsonArray = new BsonArray();
315+
bsonArray.add(new BsonBoolean(value));
316+
for (boolean v : values) {
317+
bsonArray.add(new BsonBoolean(v));
318+
}
319+
return in(notNull("path", path), bsonArray);
320+
}
321+
322+
/**
323+
* Returns a {@link SearchOperator} that searches for documents where the
324+
* value or array of values at a given path contains any of the specified values
325+
*
326+
* @param path The indexed field to be searched.
327+
* @param value The objectId value to search for.
328+
* @param values More fields to be searched.
329+
* @return The requested {@link SearchOperator}.
330+
* @mongodb.atlas.manual atlas-search/in/ in operator
331+
*/
332+
static InSearchOperator in(final FieldSearchPath path, final ObjectId value, final ObjectId... values) {
333+
return in(notNull("path", path), concat(notNull("value", value), values));
334+
}
335+
336+
/**
337+
* Returns a {@link SearchOperator} that searches for documents where the
338+
* value or array of values at a given path contains any of the specified values
339+
*
340+
* @param path The indexed field to be searched.
341+
* @param value The number value to search for.
342+
* @param values More fields to be searched.
343+
* @return The requested {@link SearchOperator}.
344+
* @mongodb.atlas.manual atlas-search/in/ in operator
345+
*/
346+
static InSearchOperator in(final FieldSearchPath path, final Number value, final Number... values) {
347+
return in(notNull("path", path), concat(notNull("value", value), values));
348+
}
349+
350+
/**
351+
* Returns a {@link SearchOperator} that searches for documents where the
352+
* value or array of values at a given path contains any of the specified values
353+
*
354+
* @param path The indexed field to be searched.
355+
* @param value The instant date value to search for.
356+
* @param values More fields to be searched.
357+
* @return The requested {@link SearchOperator}.
358+
* @mongodb.atlas.manual atlas-search/in/ in operator
359+
*/
360+
static InSearchOperator in(final FieldSearchPath path, final Instant value, final Instant... values) {
361+
return in(notNull("path", path), concat(notNull("value", value), values));
362+
}
363+
364+
/**
365+
* Returns a {@link SearchOperator} that searches for documents where the
366+
* value or array of values at a given path contains any of the specified values
367+
*
368+
* @param path The indexed field to be searched.
369+
* @param value The uuid value to search for.
370+
* @param values More fields to be searched.
371+
* @return The requested {@link SearchOperator}.
372+
* @mongodb.atlas.manual atlas-search/in/ in operator
373+
*/
374+
static InSearchOperator in(final FieldSearchPath path, final UUID value, final UUID... values) {
375+
return in(notNull("path", path), concat(notNull("value", value), values));
376+
}
377+
378+
/**
379+
* Returns a {@link SearchOperator} that searches for documents where the
380+
* value or array of values at a given path contains any of the specified values
381+
*
382+
* @param path The indexed field to be searched.
383+
* @param value The string value to search for.
384+
* @param values More fields to be searched.
385+
* @return The requested {@link SearchOperator}.
386+
* @mongodb.atlas.manual atlas-search/in/ in operator
387+
*/
388+
static InSearchOperator in(final FieldSearchPath path, final String value, final String... values) {
389+
return in(notNull("path", path), concat(notNull("value", value), values));
390+
}
391+
392+
/**
393+
* Returns a {@link SearchOperator} that searches for documents where the
394+
* value or array of values at a given path contains any of the specified values
395+
*
396+
* @param path The indexed field to be searched.
397+
* @param values The non-empty values to search for. Value can be either a single value or an array of values of only one of the supported BSON types and can't be a mix of different types.
398+
* @param <T> the type of elements in {@code values}.
399+
* @return The requested {@link SearchOperator}.
400+
* @mongodb.atlas.manual atlas-search/in/ in operator
401+
*/
402+
static <T> InSearchOperator in(final FieldSearchPath path, final Iterable<? extends T> values) {
403+
notNull("path", path);
404+
Iterator<? extends T> valueIterator = notNull("values", values).iterator();
405+
isTrueArgument("values must not be empty", valueIterator.hasNext());
406+
T firstValue = valueIterator.next();
407+
boolean hasMore = valueIterator.hasNext();
408+
return new SearchConstructibleBsonElement("in", new Document()
409+
.append("path", path.toValue())
410+
.append("value", hasMore ? values : firstValue));
411+
}
412+
303413
/**
304414
* Returns a {@link SearchOperator} that searches for documents where a field matches the specified value.
305415
*

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

+3
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
import static com.mongodb.client.model.search.SearchOperator.dateRange;
8383
import static com.mongodb.client.model.search.SearchOperator.equalsNull;
8484
import static com.mongodb.client.model.search.SearchOperator.exists;
85+
import static com.mongodb.client.model.search.SearchOperator.in;
8586
import static com.mongodb.client.model.search.SearchOperator.moreLikeThis;
8687
import static com.mongodb.client.model.search.SearchOperator.near;
8788
import static com.mongodb.client.model.search.SearchOperator.numberRange;
@@ -617,6 +618,8 @@ private static Stream<Arguments> searchAndSearchMetaArgs() {
617618
near(0, 1.5, fieldPath("fieldName7"), fieldPath("fieldName8")),
618619
near(Instant.ofEpochMilli(1), Duration.ofMillis(3), fieldPath("fieldName9")),
619620
phrase(fieldPath("fieldName10"), "term6"),
621+
in(fieldPath("fieldName10"), true),
622+
in(fieldPath("fieldName11"), "term4", "term5"),
620623
regex(fieldPath("title").multi("keyword"), "term7"),
621624
queryString(fieldPath("fieldName12"), "term8"),
622625
moreLikeThis(new BsonDocument("like", new BsonDocument("fieldName10",

0 commit comments

Comments
 (0)