Skip to content

Commit

Permalink
loads more tests
Browse files Browse the repository at this point in the history
support for FindOptions on queries for projections and such
  • Loading branch information
evanchooly committed Jun 14, 2024
1 parent 396a9b5 commit 914bd65
Show file tree
Hide file tree
Showing 106 changed files with 650 additions and 157 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ private void encodeFilter(BsonWriter writer, NearFilter near, EncoderContext con
document(writer, near.getName(), () -> {
writer.writeName("$geometry");
CodecHelper.unnamedValue(writer, datastore, near.getValue(datastore), context);
value(writer, "$maxDistance", near.maxDistance());
value(writer, "$minDistance", near.minDistance());
value(writer, "$maxDistance", near.maxDistance());
value(datastore.getCodecRegistry(), writer, "crs", near.crs(), context);
});
}
Expand Down
14 changes: 14 additions & 0 deletions core/src/main/java/dev/morphia/query/FindOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
public final class FindOptions implements ReadConfigurable<FindOptions>, CollectionConfigurable<FindOptions> {
private Boolean allowDiskUse;
private int batchSize;

private boolean disableValidation = false;

private int limit;
private long maxTimeMS;
private long maxAwaitTimeMS;
Expand Down Expand Up @@ -92,6 +95,7 @@ public <T> FindIterable<T> apply(FindIterable<T> iterable, Mapper mapper, Class<
logQuery(); // reset to a new ID
}
if (projection != null) {
projection.disableValidation(disableValidation);
iterable.projection(projection.map(mapper, type));
}

Expand Down Expand Up @@ -251,6 +255,16 @@ public FindOptions cursorType(CursorType cursorType) {
return this;
}

/**
* @param disable
* @hidden
* @morphia.internal
*/
@MorphiaInternal
public void disableValidation(boolean disable) {
this.disableValidation = disable;
}

/**
* @hidden
* @morphia.internal
Expand Down
5 changes: 3 additions & 2 deletions core/src/main/java/dev/morphia/query/MorphiaQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ public boolean isValidate() {
}

@Override
public MorphiaCursor<T> iterator(FindOptions options) {
return new MorphiaCursor<>(prepareCursor(options, collection));
public MorphiaCursor<T> iterator(@Nullable FindOptions options) {
return new MorphiaCursor<>(prepareCursor(options != null ? options : new FindOptions(), collection));
}

/**
Expand Down Expand Up @@ -317,6 +317,7 @@ private <E> MongoCursor<E> prepareCursor(FindOptions options, MongoCollection<E>
if (options.isLogQuery()) {
oldProfile = datastore.getDatabase().runCommand(new Document("profile", 2).append("slowms", 0));
}
options.disableValidation(!isValidate());
try {
return options
.apply(iterable(options, collection), mapper, type)
Expand Down
29 changes: 24 additions & 5 deletions core/src/main/java/dev/morphia/query/Projection.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import com.mongodb.lang.Nullable;

import dev.morphia.annotations.Entity;
import dev.morphia.annotations.internal.MorphiaInternal;
import dev.morphia.internal.PathTarget;
import dev.morphia.mapping.Mapper;
import dev.morphia.mapping.codec.pojo.EntityModel;
import dev.morphia.sofia.Sofia;

import org.bson.Document;
Expand All @@ -19,6 +19,9 @@
*/
public class Projection {
private final FindOptions options;

private boolean disableValidation;

private List<String> includes;
private List<String> excludes;
private String arrayField;
Expand All @@ -30,6 +33,17 @@ public class Projection {
this.options = options;
}

/**
* @param disableValidation
* @hidden
* @morphia.internal
*/
@MorphiaInternal
public void disableValidation(boolean disableValidation) {

this.disableValidation = disableValidation;
}

/**
* Adds a field to the projection clause. The _id field is always included unless explicitly suppressed.
*
Expand Down Expand Up @@ -112,7 +126,8 @@ private void iterate(Mapper mapper, Document projection, Class<?> clazz, @Nullab
int include) {
if (fields != null) {
for (String field : fields) {
projection.put(new PathTarget(mapper, mapper.getEntityModel(clazz), field).translatedPath(), include);
String key = disableValidation ? field : new PathTarget(mapper, mapper.getEntityModel(clazz), field).translatedPath();
projection.put(key, include);
}
}
}
Expand All @@ -137,8 +152,10 @@ private Document project(Mapper mapper, Class<?> clazz) {
iterate(mapper, projection, clazz, includes, 1);
iterate(mapper, projection, clazz, excludes, 0);

final EntityModel model = mapper.getEntityModel(clazz);
Entity entityAnnotation = model.getEntityAnnotation();
Entity entityAnnotation = null;
if (!clazz.equals(Document.class)) {
entityAnnotation = mapper.getEntityModel(clazz).getEntityAnnotation();
}

if (isIncluding() && entityAnnotation != null && entityAnnotation.useDiscriminator()) {
projection.put(mapper.getConfig().discriminatorKey(), 1);
Expand All @@ -148,7 +165,9 @@ private Document project(Mapper mapper, Class<?> clazz) {
}

private Document slice(Mapper mapper, Class<?> clazz) {
String fieldName = new PathTarget(mapper, mapper.getEntityModel(clazz), arrayField).translatedPath();
String fieldName = disableValidation
? arrayField
: new PathTarget(mapper, mapper.getEntityModel(clazz), arrayField).translatedPath();
return new Document(fieldName, slice.toDatabase());
}

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/dev/morphia/query/Query.java
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ default T modify(ModifyOptions options, UpdateOperator first, UpdateOperator...
* @return a MorphiaCursor
* @since 2.0
*/
MorphiaCursor<T> iterator(FindOptions options);
MorphiaCursor<T> iterator(@Nullable FindOptions options);

/**
* Provides a {@link Stream} representation of the results of this query.
Expand Down
14 changes: 14 additions & 0 deletions core/src/main/java/dev/morphia/query/filters/Filters.java
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,20 @@ public static Filter mod(String field, long divisor, long remainder) {
return new ModFilter(field, divisor, remainder);
}

/**
* Performs a modulo operation on the value of a field and selects documents with a specified result.
*
* @param field the field to check
* @param divisor the value to divide by
* @param remainder the remainder to check for
* @return the filter
* @query.filter $mod
* @since 3.0
*/
public static Filter mod(String field, double divisor, double remainder) {
return new ModFilter(field, divisor, remainder);
}

/**
* $ne selects the documents where the value of the field is not equal to the specified value. This includes documents that do not
* contain the field.
Expand Down
10 changes: 5 additions & 5 deletions core/src/main/java/dev/morphia/query/filters/ModFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
*/
@MorphiaInternal
public class ModFilter extends Filter {
private final long divisor;
private final Number divisor;

private final long remainder;
private final Number remainder;

public ModFilter(String field, long divisor, long remainder) {
public ModFilter(String field, Number divisor, Number remainder) {
super("$mod", field, null);
this.divisor = divisor;
this.remainder = remainder;
Expand All @@ -24,7 +24,7 @@ public ModFilter(String field, long divisor, long remainder) {
* @return the divisor
*/
@MorphiaInternal
public long divisor() {
public Number divisor() {
return divisor;
}

Expand All @@ -34,7 +34,7 @@ public long divisor() {
* @return the remainder
*/
@MorphiaInternal
public long remainder() {
public Number remainder() {
return remainder;
}
}
131 changes: 0 additions & 131 deletions core/src/test/java/dev/morphia/test/query/FiltersTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@
import dev.morphia.annotations.Id;
import dev.morphia.query.FindOptions;
import dev.morphia.query.Meta;
import dev.morphia.query.MorphiaQuery;
import dev.morphia.query.Query;
import dev.morphia.query.Type;
import dev.morphia.test.TemplatedTestBase;
import dev.morphia.test.aggregation.model.Inventory;
import dev.morphia.test.models.Budget;
import dev.morphia.test.models.User;

Expand All @@ -30,19 +28,10 @@
import static dev.morphia.aggregation.expressions.Miscellaneous.rand;
import static dev.morphia.aggregation.expressions.Miscellaneous.sampleRate;
import static dev.morphia.aggregation.stages.Match.match;
import static dev.morphia.query.filters.Filters.and;
import static dev.morphia.query.filters.Filters.bitsAllClear;
import static dev.morphia.query.filters.Filters.bitsAllSet;
import static dev.morphia.query.filters.Filters.bitsAnyClear;
import static dev.morphia.query.filters.Filters.bitsAnySet;
import static dev.morphia.query.filters.Filters.expr;
import static dev.morphia.query.filters.Filters.gt;
import static dev.morphia.query.filters.Filters.gte;
import static dev.morphia.query.filters.Filters.in;
import static dev.morphia.query.filters.Filters.jsonSchema;
import static dev.morphia.query.filters.Filters.lt;
import static dev.morphia.query.filters.Filters.lte;
import static dev.morphia.query.filters.Filters.mod;
import static dev.morphia.query.filters.Filters.nin;
import static dev.morphia.query.filters.Filters.nor;
import static dev.morphia.query.filters.Filters.or;
Expand All @@ -65,16 +54,6 @@ public class FiltersTest extends TemplatedTestBase {
public void testCoverage() {
}

@Test
public void testAnd() {
getDs().find(Budget.class)
.filter(and(lt("budget", 10000), gt("budget", 12)))
.iterator();
getDs().find(Budget.class)
.filter(and(lte("budget", 10000), gte("budget", 12)))
.iterator();
}

@Test
public void testType() {
User entity = new User();
Expand All @@ -88,100 +67,6 @@ public void testType() {
Assert.assertTrue(query.count() > 0);
}

@Test
public void testBitsAllClear() {
MongoCollection<Document> collection = getDatabase().getCollection("users");

String discriminator = User.class.getName();
collection.insertMany(asList(
new Document("a", 54).append("binaryValueofA", "00110110").append("_t", discriminator),
new Document("a", 20).append("binaryValueofA", "00010100").append("_t", discriminator),
new Document("a", 20.0).append("binaryValueofA", "00010100").append("_t", discriminator)));

FindOptions options = new FindOptions().logQuery();

Query<User> query = getDs().find(User.class)
.disableValidation()
.filter(bitsAllClear("a", 35));
assertEquals(query.iterator(options).toList().size(), 2, query.getLoggedQuery());

query = getDs().find(User.class)
.disableValidation()
.filter(bitsAllClear("a", new int[] { 1, 5 }));
assertEquals(query.iterator(options).toList().size(), 2, query.getLoggedQuery());
}

@Test
public void testBitsAllSet() {
MongoCollection<Document> collection = getDatabase().getCollection("users");

String discriminator = User.class.getName();
collection.insertMany(asList(
new Document("a", 54).append("binaryValueofA", "00110110").append("_t", discriminator),
new Document("a", 20).append("binaryValueofA", "00010100").append("_t", discriminator),
new Document("a", 20.0).append("binaryValueofA", "00010100").append("_t", discriminator)));

final FindOptions options = new FindOptions().logQuery();

Query<User> query = getDs().find(User.class)
.disableValidation()
.filter(bitsAllSet("a", 50));
assertEquals(query.iterator(options).toList().size(), 1, query.getLoggedQuery());

query = getDs().find(User.class)
.disableValidation()
.filter(bitsAllSet("a", new int[] { 1, 5 }));
assertEquals(query.iterator(options)
.toList().size(), 1, query.getLoggedQuery());
}

@Test
public void testBitsAnyClear() {
MongoCollection<Document> collection = getDatabase().getCollection("users");

String discriminator = User.class.getName();
collection.insertMany(asList(
new Document("a", 54).append("binaryValueofA", "00110110").append("_t", discriminator),
new Document("a", 20).append("binaryValueofA", "00010100").append("_t", discriminator),
new Document("a", 20.0).append("binaryValueofA", "00010100").append("_t", discriminator)));

FindOptions options = new FindOptions().logQuery();

Query<User> query = getDs().find(User.class)
.disableValidation()
.filter(bitsAnyClear("a", 35));
assertEquals(query.iterator(options).toList().size(), 3, query.getLoggedQuery());

query = getDs().find(User.class)
.disableValidation()
.filter(bitsAnyClear("a", new int[] { 1, 5 }));
assertEquals(query.iterator(options)
.toList().size(), 2, query.getLoggedQuery());
}

@Test
public void testBitsAnySet() {
MongoCollection<Document> collection = getDatabase().getCollection("users");

String discriminator = User.class.getName();
collection.insertMany(asList(
new Document("a", 54).append("binaryValueofA", "00110110").append("_t", discriminator),
new Document("a", 20).append("binaryValueofA", "00010100").append("_t", discriminator),
new Document("a", 20.0).append("binaryValueofA", "00010100").append("_t", discriminator)));

FindOptions options = new FindOptions().logQuery();

Query<User> query = getDs().find(User.class)
.disableValidation()
.filter(bitsAnySet("a", 35));
assertEquals(query.iterator(options).toList().size(), 1, query.getLoggedQuery());

assertEquals(getDs().find(User.class)
.disableValidation()
.filter(bitsAnySet("a", new int[] { 1, 5 })).iterator(options)
.toList().size(), 1, query.getLoggedQuery());
}

@Test
public void testExpr() {
insert("budget", asList(
Expand All @@ -198,13 +83,6 @@ public void testExpr() {
assertEquals(budgets.size(), 3);
}

@Test
public void testIn() {
getDs().find(Budget.class)
.filter(in("budget", asList(123, 234)))
.iterator();
}

@Test
public void testJsonSchema() {
insert("inventory", List.of(
Expand Down Expand Up @@ -270,15 +148,6 @@ public void testMeta() {

}

@Test
public void testMod() {
var query = getDs().find(Inventory.class)
.disableValidation()
.filter(mod("qty", 4, 0));
testQuery((MorphiaQuery<?>) query, new FindOptions(), true);

}

@Test
public void testNin() {
getDs().find(Budget.class)
Expand Down
Loading

0 comments on commit 914bd65

Please sign in to comment.