de.bwaldvogel.mongo.backend.AbstractBackendTest Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mongo-java-server-test-common Show documentation
Show all versions of mongo-java-server-test-common Show documentation
Fake implementation of MongoDB in Java that speaks the wire protocol
package de.bwaldvogel.mongo.backend;
import static com.mongodb.client.model.Filters.and;
import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.Filters.exists;
import static com.mongodb.client.model.Filters.gt;
import static com.mongodb.client.model.Filters.in;
import static com.mongodb.client.model.Filters.lt;
import static com.mongodb.client.model.Filters.ne;
import static com.mongodb.client.model.Filters.nor;
import static com.mongodb.client.model.Filters.or;
import static com.mongodb.client.model.Updates.addEachToSet;
import static com.mongodb.client.model.Updates.pull;
import static com.mongodb.client.model.Updates.pullByFilter;
import static com.mongodb.client.model.Updates.set;
import static de.bwaldvogel.mongo.backend.TestUtils.date;
import static de.bwaldvogel.mongo.backend.TestUtils.getCollectionStatistics;
import static de.bwaldvogel.mongo.backend.TestUtils.instant;
import static de.bwaldvogel.mongo.backend.TestUtils.json;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.fail;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import org.bson.BsonInt32;
import org.bson.BsonJavaScript;
import org.bson.BsonObjectId;
import org.bson.BsonString;
import org.bson.BsonTimestamp;
import org.bson.Document;
import org.bson.codecs.DocumentCodec;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.conversions.Bson;
import org.bson.types.Binary;
import org.bson.types.Code;
import org.bson.types.ObjectId;
import org.junit.Test;
import org.mockito.AdditionalAnswers;
import org.mockito.Mockito;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mongodb.DBRef;
import com.mongodb.DuplicateKeyException;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCommandException;
import com.mongodb.MongoException;
import com.mongodb.MongoNamespace;
import com.mongodb.MongoQueryException;
import com.mongodb.MongoServerException;
import com.mongodb.MongoWriteException;
import com.mongodb.ReadPreference;
import com.mongodb.ServerAddress;
import com.mongodb.WriteConcern;
import com.mongodb.bulk.BulkWriteResult;
import com.mongodb.bulk.BulkWriteUpsert;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.BulkWriteOptions;
import com.mongodb.client.model.CountOptions;
import com.mongodb.client.model.CreateCollectionOptions;
import com.mongodb.client.model.DeleteManyModel;
import com.mongodb.client.model.EstimatedDocumentCountOptions;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.IndexOptions;
import com.mongodb.client.model.InsertOneModel;
import com.mongodb.client.model.RenameCollectionOptions;
import com.mongodb.client.model.ReplaceOneModel;
import com.mongodb.client.model.ReplaceOptions;
import com.mongodb.client.model.ReturnDocument;
import com.mongodb.client.model.UpdateManyModel;
import com.mongodb.client.model.UpdateOneModel;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.model.Updates;
import com.mongodb.client.model.WriteModel;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.mongodb.reactivestreams.client.Success;
public abstract class AbstractBackendTest extends AbstractTest {
private static final Logger log = LoggerFactory.getLogger(AbstractBackendTest.class);
protected static final String OTHER_TEST_DATABASE_NAME = "bar";
protected Document runCommand(String commandName) {
return runCommand(new Document(commandName, Integer.valueOf(1)));
}
private Document runCommand(Document command) {
return getAdminDb().runCommand(command);
}
protected MongoCollection getCollection(String collectionName) {
return db.getCollection(collectionName);
}
protected MongoDatabase getAdminDb() {
return syncClient.getDatabase("admin");
}
private String getCollectionName() {
return collection.getNamespace().getCollectionName();
}
@Test
public void testSimpleInsert() throws Exception {
collection.insertOne(json("_id: 1"));
}
@Test
public void testSimpleInsertDelete() throws Exception {
collection.insertOne(json("_id: 1"));
collection.deleteOne(json("_id: 1"));
}
@Test
public void testCreateCollection() throws Exception {
String newCollectionName = "some-collection";
assertThat(db.listCollectionNames()).doesNotContain(newCollectionName);
db.createCollection(newCollectionName, new CreateCollectionOptions());
assertThat(db.listCollectionNames()).contains(newCollectionName);
}
@Test
public void testCreateCollectionAlreadyExists() throws Exception {
db.createCollection("some-collection", new CreateCollectionOptions());
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> db.createCollection("some-collection", new CreateCollectionOptions()))
.withMessageContaining("Command failed with error 48 (NamespaceExists): 'a collection 'testdb.some-collection' already exists'");
}
@Test
public void testUnsupportedModifier() throws Exception {
collection.insertOne(json(""));
assertMongoWriteException(() -> collection.updateOne(json(""), json("$foo: {}")),
9, "FailedToParse", "Unknown modifier: $foo");
}
@Test
public void testUpsertWithInc() {
Document query = json("_id: {f: 'ca', '1': {l: 2}, t: {t: 11}}");
Document update = json("'$inc': {'n.!' : 1 , 'n.a.b:false' : 1}");
collection.updateOne(query, update, new UpdateOptions().upsert(true));
query.putAll(json("n: {'!': 1, a: {'b:false': 1}}"));
assertThat(collection.find().first()).isEqualTo(query);
}
@Test
public void testBasicUpdate() {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2, b: 5"));
collection.insertOne(json("_id: 3"));
collection.insertOne(json("_id: 4"));
collection.replaceOne(json("_id: 2"), json("_id: 2, a: 5"));
assertThat(collection.find(json("_id: 2")).first()).isEqualTo(json("_id: 2, a: 5"));
}
@Test
public void testCollectionStats() throws Exception {
db.createCollection("other-collection");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(this::getCollStats)
.withMessageContaining("Command failed with error -1: 'Collection [testdb.testcoll] not found.'");
collection.insertOne(json(""));
collection.insertOne(json("abc: 'foo'"));
Document stats = getCollStats();
assertThat(stats.getDouble("ok")).isEqualTo(1.0);
assertThat(stats.getInteger("count")).isEqualTo(2);
assertThat(stats.getInteger("size")).isEqualTo(57);
assertThat(stats.getInteger("avgObjSize")).isEqualTo(28);
}
private Document getCollStats() {
String collectionName = getCollectionName();
return getCollectionStatistics(db, collectionName);
}
@Test
public void testGetLogStartupWarnings() throws Exception {
Document startupWarnings = getAdminDb().runCommand(json("getLog: 'startupWarnings'"));
assertThat(startupWarnings.getDouble("ok")).isEqualTo(1.0);
assertThat(startupWarnings.get("totalLinesWritten")).isInstanceOf(Number.class);
assertThat(startupWarnings.get("log")).isEqualTo(Collections.emptyList());
}
@Test
public void testGetLogWhichDoesNotExist() throws Exception {
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> getAdminDb().runCommand(json("getLog: 'illegal'")))
.withMessageContaining("Command failed with error -1: 'no RamLog named: illegal'");
}
@Test
public void testCompoundDateIdUpserts() {
Document query = json("_id: {$lt: {n: 'a', t: 10}, $gte: {n: 'a', t: 1}}");
List toUpsert = Arrays.asList(
json("_id: {n: 'a', t: 1}"),
json("_id: {n: 'a', t: 2}"),
json("_id: {n: 'a', t: 3}"),
json("_id: {n: 'a', t: 11}"));
for (Document dbo : toUpsert) {
collection.replaceOne(dbo, new Document(dbo).append("foo", "bar"), new ReplaceOptions().upsert(true));
}
assertThat(collection.find(query))
.containsExactly(
json("_id: {n: 'a', t: 1}, foo: 'bar'"),
json("_id: {n: 'a', t: 2}, foo: 'bar'"),
json("_id: {n: 'a', t: 3}, foo: 'bar'")
);
}
@Test
public void testCompoundSort() {
collection.insertOne(json("a:1, _id: 1"));
collection.insertOne(json("a:2, _id: 5"));
collection.insertOne(json("a:1, _id: 2"));
collection.insertOne(json("a:2, _id: 4"));
collection.insertOne(json("a:1, _id: 3"));
assertThat(collection.find().sort(json("a:1, _id: -1")))
.containsExactly(
json("a: 1, _id: 3"),
json("a: 1, _id: 2"),
json("a: 1, _id: 1"),
json("a: 2, _id: 5"),
json("a: 2, _id: 4")
);
}
@Test
@SuppressWarnings("deprecation")
public void testCountCommand() {
assertThat(collection.count()).isZero();
}
@Test
public void testNonPrimaryCountCommand() {
assertThat(collection.withReadPreference(ReadPreference.nearest()).countDocuments()).isZero();
}
@Test
@SuppressWarnings("deprecation")
public void testCountCommandWithQuery() {
collection.insertOne(json("n:1"));
collection.insertOne(json("n:2"));
collection.insertOne(json("n:2"));
assertThat(collection.count(json("n:2"))).isEqualTo(2);
}
@Test
@SuppressWarnings("deprecation")
public void testCountCommandWithSkipAndLimit() {
collection.insertOne(json("x: 1"));
collection.insertOne(json("x: 1"));
collection.insertOne(json("x: 2"));
collection.insertOne(json("x: 1"));
collection.insertOne(json("x: 2"));
collection.insertOne(json("x: 1"));
assertThat(collection.count(json("x: 1"), new CountOptions().skip(4).limit(2))).isEqualTo(0);
assertThat(collection.count(json("x: 1"), new CountOptions().limit(3))).isEqualTo(3);
assertThat(collection.count(json("x: 1"), new CountOptions().limit(10))).isEqualTo(4);
assertThat(collection.count(json("x: 1"), new CountOptions().skip(1))).isEqualTo(3);
}
@Test
public void testCountDocuments() throws Exception {
assertThat(collection.countDocuments()).isZero();
}
@Test
public void testCountDocumentsWithQuery() {
collection.insertOne(json("n:1"));
collection.insertOne(json("n:2"));
collection.insertOne(json("n:2"));
assertThat(collection.countDocuments(json("n:2"))).isEqualTo(2);
}
@Test
public void testEstimatedDocumentCount() throws Exception {
assertThat(collection.estimatedDocumentCount()).isEqualTo(0);
collection.insertOne(json("n:1"));
collection.insertOne(json("n:2"));
collection.insertOne(json("n:2"));
assertThat(collection.estimatedDocumentCount()).isEqualTo(3);
assertThat(collection.estimatedDocumentCount(new EstimatedDocumentCountOptions().maxTime(1, TimeUnit.SECONDS))).isEqualTo(3);
}
@Test
public void testCreateIndexes() {
collection.createIndex(new Document("n", 1));
collection.createIndex(new Document("b", 1));
assertThat(collection.listIndexes())
.containsExactlyInAnyOrder(
json("key: {_id: 1}").append("ns", collection.getNamespace().getFullName()).append("name", "_id_").append("v", 2),
json("key: {n: 1}").append("ns", collection.getNamespace().getFullName()).append("name", "n_1").append("v", 2),
json("key: {b: 1}").append("ns", collection.getNamespace().getFullName()).append("name", "b_1").append("v", 2)
);
}
@Test
public void testDropAndRecreateIndex() throws Exception {
collection.createIndex(new Document("n", 1));
collection.createIndex(new Document("b", 1));
collection.createIndex(new Document("c", 1), new IndexOptions().unique(true));
collection.dropIndex(new Document("n", 1));
collection.insertOne(json("_id: 1, c: 10"));
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.dropIndex(new Document("n", 1)))
.withMessageContaining("Command failed with error 27 (IndexNotFound): 'can't find index with key: { n: 1 }'");
assertMongoWriteException(() -> collection.insertOne(json("_id: 2, c: 10")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: c_1 dup key: { : 10 }");
collection.dropIndex(new Document("c", 1));
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.dropIndex(new Document("c", 1)))
.withMessageContaining("Command failed with error 27 (IndexNotFound): 'can't find index with key: { c: 1 }'");
assertThat(collection.listIndexes())
.containsExactlyInAnyOrder(
json("key: {_id: 1}").append("ns", collection.getNamespace().getFullName()).append("name", "_id_").append("v", 2),
json("key: {b: 1}").append("ns", collection.getNamespace().getFullName()).append("name", "b_1").append("v", 2)
);
collection.insertOne(json("_id: 2, c: 10"));
assertThatExceptionOfType(DuplicateKeyException.class)
.isThrownBy(() -> collection.createIndex(new Document("c", 1), new IndexOptions().unique(true)))
.withMessageContaining("Write failed with error code 11000 and error message " +
"'E11000 duplicate key error collection: testdb.testcoll index: c_1 dup key:");
collection.deleteOne(json("_id: 1"));
collection.createIndex(new Document("c", 1), new IndexOptions().unique(true));
assertThat(collection.listIndexes())
.containsExactlyInAnyOrder(
json("key: {_id: 1}").append("ns", collection.getNamespace().getFullName()).append("name", "_id_").append("v", 2),
json("key: {b: 1}").append("ns", collection.getNamespace().getFullName()).append("name", "b_1").append("v", 2),
json("key: {c: 1}").append("ns", collection.getNamespace().getFullName()).append("name", "c_1").append("unique", true).append("v", 2)
);
}
@Test
public void testCurrentOperations() throws Exception {
Document currentOperations = getAdminDb().getCollection("$cmd.sys.inprog").find().first();
assertThat(currentOperations).isNotNull();
assertThat(currentOperations.get("inprog")).isInstanceOf(List.class);
}
@Test
public void testListCollectionsEmpty() throws Exception {
Document result = db.runCommand(json("listCollections: 1"));
assertThat(result.getDouble("ok")).isEqualTo(1.0);
Document cursor = (Document) result.get("cursor");
assertThat(cursor.keySet()).containsExactly("id", "ns", "firstBatch");
assertThat(cursor.get("id")).isEqualTo(Long.valueOf(0));
assertThat(cursor.get("ns")).isEqualTo(db.getName() + ".$cmd.listCollections");
List> firstBatch = (List>) cursor.get("firstBatch");
assertThat(firstBatch).isEmpty();
}
@Test
public void testListCollections() throws Exception {
List collections = Arrays.asList("coll1", "coll2", "coll3");
for (String collection : collections) {
getCollection(collection).insertOne(json("_id: 1"));
}
Document result = db.runCommand(json("listCollections: 1"));
assertThat(result.getDouble("ok")).isEqualTo(1.0);
Document cursor = (Document) result.get("cursor");
assertThat(cursor.keySet()).containsExactly("id", "ns", "firstBatch");
assertThat(cursor.get("id")).isEqualTo(Long.valueOf(0));
assertThat(cursor.get("ns")).isEqualTo(db.getName() + ".$cmd.listCollections");
assertThat(cursor.get("firstBatch")).isInstanceOf(List.class);
@SuppressWarnings("unchecked")
List firstBatch = (List) cursor.get("firstBatch");
assertThat(firstBatch).hasSameSizeAs(collections);
Set collectionNames = new HashSet<>();
for (Document collection : firstBatch) {
assertThat(collection).containsOnlyKeys("name", "options", "type", "idIndex", "info");
String name = (String) collection.get("name");
assertThat(collection.get("options")).isEqualTo(json(""));
assertThat(collection.get("name")).isInstanceOf(String.class);
assertThat(collection.get("type")).isEqualTo("collection");
assertThat(collection.get("idIndex")).isEqualTo(json("key: {_id: 1}, name: '_id_', ns: 'testdb." + name + "', v: 2"));
assertThat(collection.get("info")).isInstanceOf(Document.class);
collectionNames.add(name);
}
assertThat(collectionNames).containsExactlyInAnyOrderElementsOf(collections);
}
@Test
public void testGetCollectionNames() throws Exception {
getCollection("foo").insertOne(json(""));
getCollection("bar").insertOne(json(""));
assertThat(db.listCollectionNames())
.containsExactlyInAnyOrder("foo", "bar");
}
@Test
public void testSystemNamespaces() throws Exception {
getCollection("foo").insertOne(json(""));
getCollection("bar").insertOne(json(""));
MongoCollection namespaces = db.getCollection("system.namespaces");
assertThat(namespaces.find()).containsExactlyInAnyOrder(
json("name: 'testdb.foo'"),
json("name: 'testdb.bar'")
);
}
@Test
public void testDatabaseStats() throws Exception {
Document stats = db.runCommand(new Document("dbStats", 1).append("scale", 1));
assertThat(stats.getDouble("ok")).isEqualTo(1.0);
assertThat(stats.getInteger("objects")).isZero();
assertThat(stats.getInteger("collections")).isZero();
assertThat(stats.getInteger("indexes")).isZero();
assertThat(stats.getInteger("dataSize")).isZero();
getCollection("foo").insertOne(json(""));
getCollection("foo").insertOne(json(""));
getCollection("bar").insertOne(json(""));
stats = db.runCommand(new Document("dbStats", 1).append("scale", 1));
assertThat(stats.getDouble("ok")).isEqualTo(1.0);
assertThat(stats.getInteger("objects")).isEqualTo(3);
assertThat(stats.getInteger("collections")).isEqualTo(2);
assertThat(stats.getInteger("indexes")).isEqualTo(2);
assertThat(stats.getDouble("dataSize")).isEqualTo(66.0);
}
@Test
public void testDeleteDecrementsCount() {
collection.insertOne(json("key: 'value'"));
assertThat(collection.countDocuments()).isEqualTo(1);
collection.deleteOne(json(""));
assertThat(collection.countDocuments()).isZero();
}
@Test
public void testDeleteInSystemNamespace() throws Exception {
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> getCollection("system.foobar").deleteOne(json("")))
.withMessageContaining("Command failed with error 73 (InvalidNamespace): 'cannot write to 'testdb.system.foobar'");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> getCollection("system.namespaces").deleteOne(json("")))
.withMessageContaining("Command failed with error 73 (InvalidNamespace): 'cannot write to 'testdb.system.namespaces'");
}
@Test
public void testUpdateInSystemNamespace() throws Exception {
for (String collectionName : Arrays.asList("system.foobar", "system.namespaces")) {
MongoCollection collection = getCollection(collectionName);
assertMongoWriteException(() -> collection.updateMany(eq("some", "value"), set("field", "value")),
10156, "cannot update system collection");
}
}
@Test
public void testDistinctQuery() {
collection.insertOne(json("_id: 1, n: null"));
collection.insertOne(json("_id: 2, n: 3"));
collection.insertOne(json("_id: 3, n: 1"));
collection.insertOne(json("_id: 4, n: 2"));
collection.insertOne(json("_id: 5, n: 1.0"));
collection.insertOne(json("_id: 6, n: 1"));
collection.insertOne(json("_id: 7, n: -0.0"));
collection.insertOne(json("_id: 8, n: 0"));
assertThat(collection.distinct("n", Integer.class))
.containsExactly(null, 3, 1, 2, 0);
assertThat(collection.distinct("n", json("n: {$gt: 1}"), Integer.class))
.containsExactly(3, 2);
assertThat(collection.distinct("foobar", String.class)).isEmpty();
assertThat(collection.distinct("_id", Integer.class))
.hasSize((int) collection.countDocuments());
}
// https://github.com/bwaldvogel/mongo-java-server/issues/44
@Test
public void testDistinctUuids() throws Exception {
collection.insertOne(json("_id: 1, n: null"));
collection.insertOne(json("_id: 2").append("n", new UUID(0, 1)));
collection.insertOne(json("_id: 3").append("n", new UUID(1, 0)));
collection.insertOne(json("_id: 4").append("n", new UUID(0, 2)));
collection.insertOne(json("_id: 5").append("n", new UUID(1, 1)));
collection.insertOne(json("_id: 6").append("n", new UUID(1, 0)));
assertThat(collection.distinct("n", UUID.class))
.containsExactly(
null,
new UUID(0, 1),
new UUID(1, 0),
new UUID(0, 2),
new UUID(1, 1)
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/70
@Test
public void testDistinctArrayField() throws Exception {
collection.insertOne(json("_id: 1, n: null"));
collection.insertOne(json("_id: 2").append("n", Arrays.asList(1, 2, 3)));
collection.insertOne(json("_id: 3").append("n", Arrays.asList(3, 4, 5)));
collection.insertOne(json("_id: 4").append("n", 6));
assertThat(collection.distinct("n", Integer.class))
.containsExactly(null, 1, 2, 3, 4, 5, 6);
}
@Test
public void testDistinct_documentArray() throws Exception {
collection.insertOne(json("_id: 1, n: null"));
collection.insertOne(json("_id: 2, n: [{item: 1}, {item: 2}]"));
collection.insertOne(json("_id: 3, n: {item: 3}"));
collection.insertOne(json("_id: 4, n: {item: [4, 5]}"));
collection.insertOne(json("_id: 5, n: {}"));
assertThat(collection.distinct("n.item", Integer.class))
.containsExactly(1, 2, 3, 4, 5);
}
@Test
public void testInsertQueryAndSortBinaryTypes() throws Exception {
byte[] highBytes = new byte[16];
for (int i = 0; i < highBytes.length; i++) {
highBytes[i] = (byte) 0xFF;
}
collection.insertOne(json("_id: 1, n: null"));
collection.insertOne(json("_id: 2").append("n", new UUID(0, 1)));
collection.insertOne(json("_id: 3").append("n", new UUID(1, 0)));
collection.insertOne(json("_id: 4, n: 'abc'"));
collection.insertOne(json("_id: 5, n: 17"));
collection.insertOne(json("_id: 6, n: [1, 2, 3]"));
collection.insertOne(json("_id: 7").append("n", new byte[] { 0, 0, 0, 1 }));
collection.insertOne(json("_id: 8").append("n", highBytes));
collection.insertOne(json("_id: 9").append("n", new byte[0]));
assertThat(collection.find(json("n: {$type: 5}")).sort(json("n: 1")))
.containsExactly(
json("_id: 9").append("n", new Binary(new byte[0])),
json("_id: 7").append("n", new Binary(new byte[] { 0, 0, 0, 1 })),
json("_id: 8").append("n", new Binary(highBytes)),
json("_id: 2").append("n", new UUID(0, 1)),
json("_id: 3").append("n", new UUID(1, 0))
);
assertThat(collection.find(new Document("n", new UUID(1, 0))))
.containsExactly(
json("_id: 3").append("n", new UUID(1, 0))
);
assertThat(collection.find(json("")).sort(json("n: 1")))
.containsExactly(
json("_id: 1, n: null"),
json("_id: 6, n: [1, 2, 3]"),
json("_id: 5, n: 17"),
json("_id: 4, n: 'abc'"),
json("_id: 9").append("n", new Binary(new byte[0])),
json("_id: 7").append("n", new Binary(new byte[] { 0, 0, 0, 1 })),
json("_id: 8").append("n", new Binary(highBytes)),
json("_id: 2").append("n", new UUID(0, 1)),
json("_id: 3").append("n", new UUID(1, 0))
);
}
@Test
public void testUuidAsId() throws Exception {
collection.insertOne(new Document("_id", new UUID(0, 1)));
collection.insertOne(new Document("_id", new UUID(0, 2)));
collection.insertOne(new Document("_id", new UUID(999999, 128)));
assertMongoWriteException(() -> collection.insertOne(new Document("_id", new UUID(0, 1))),
11000, "DuplicateKey",
"E11000 duplicate key error collection: testdb.testcoll index: _id_ dup key: { : BinData(3, 00000000000000000100000000000000) }");
assertMongoWriteException(() -> collection.insertOne(new Document("_id", new UUID(999999, 128))),
11000, "DuplicateKey",
"E11000 duplicate key error collection: testdb.testcoll index: _id_ dup key: { : BinData(3, 3F420F00000000008000000000000000) }");
collection.deleteOne(new Document("_id", new UUID(0, 2)));
assertThat(collection.find(json("")))
.containsExactlyInAnyOrder(
new Document("_id", new UUID(0, 1)),
new Document("_id", new UUID(999999, 128))
);
}
@Test
public void testTypeMatching() throws Exception {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 'abc'"));
collection.insertOne(json("a: {b: {c: 123}}"));
collection.insertOne(json("_id: {'$numberDecimal': '2'}"));
assertThat(collection.find(json("_id: {$type: 2.0}")))
.containsExactly(json("_id: 'abc'"));
assertThat(collection.find(json("_id: {$type: [16, 'string']}")))
.containsExactlyInAnyOrder(
json("_id: 1"),
json("_id: 'abc'")
);
assertThat(collection.find(json("_id: {$type: 'number'}")))
.containsExactlyInAnyOrder(
json("_id: 1"),
json("_id: {'$numberDecimal': '2'}")
);
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("n: {$type: []}")).first())
.withMessageContaining("Query failed with error code 9 and error message 'n must match at least one type'");
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("'a.b.c': {$type: []}")).first())
.withMessageContaining("Query failed with error code 9 and error message 'a.b.c must match at least one type'");
assertThat(collection.find(json("a: {b: {$type: []}}"))).isEmpty();
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("n: {$type: 'abc'}")).first())
.withMessageContaining("Query failed with error code 2 and error message 'Unknown type name alias: abc'");
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("n: {$type: null}")).first())
.withMessageContaining("Query failed with error code 14 and error message 'type must be represented as a number or a string'");
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("_id: {$type: 16.3}")).first())
.withMessageContaining("Query failed with error code 2 and error message 'Invalid numerical type code: 16.3'");
}
@Test
public void testDistinctQueryWithDot() {
collection.insertOne(json("a: {b: 1}"));
collection.insertOne(json("a: {b: 1}"));
collection.insertOne(json("a: {b: 1}"));
collection.insertOne(json("a: {b: 2}"));
collection.insertOne(json("a: {b: 3}"));
collection.insertOne(json("a: {b: null}"));
collection.insertOne(json("a: null"));
assertThat(collection.distinct("a.b", Integer.class))
.containsExactly(1, 2, 3, null);
assertThat(collection.distinct("a.c", Integer.class)).isEmpty();
}
@Test
public void testDropCollection() throws Exception {
collection.createIndex(new Document("n", 1));
collection.createIndex(new Document("b", 1));
collection.insertOne(json(""));
assertThat(db.listCollectionNames()).contains(getCollectionName());
assertThat(collection.listIndexes())
.containsExactlyInAnyOrder(
json("key: {_id: 1}").append("ns", collection.getNamespace().getFullName()).append("name", "_id_").append("v", 2),
json("key: {n: 1}").append("ns", collection.getNamespace().getFullName()).append("name", "n_1").append("v", 2),
json("key: {b: 1}").append("ns", collection.getNamespace().getFullName()).append("name", "b_1").append("v", 2)
);
collection.drop();
assertThat(db.listCollectionNames()).doesNotContain(getCollectionName());
assertThat(collection.listIndexes()).isEmpty();
}
@Test
public void testDropCollectionAlsoDropsFromDB() throws Exception {
collection.insertOne(json(""));
collection.drop();
assertThat(collection.countDocuments()).isZero();
assertThat(db.listCollectionNames()).doesNotContain(getCollectionName());
}
@Test
public void testDropDatabaseAlsoDropsCollectionData() throws Exception {
collection.insertOne(json(""));
db.drop();
assertThat(collection.countDocuments()).isZero();
}
@Test
public void testDropDatabaseDropsAllData() throws Exception {
collection.insertOne(json("_id: 1"));
MongoCollection collection2 = getCollection("testcoll2");
collection2.insertOne(json("_id: 1"));
syncClient.dropDatabase(db.getName());
assertThat(listDatabaseNames()).doesNotContain(db.getName());
assertThat(collection.countDocuments()).isZero();
assertThat(db.listCollectionNames()).doesNotContain(getCollectionName(),
collection2.getNamespace().getCollectionName());
collection.insertOne(json("_id: 1"));
collection2.insertOne(json("_id: 1"));
}
// https://github.com/bwaldvogel/mongo-java-server/issues/107
@Test
public void testDropDatabaseAfterAddingIndexMultipleTimes() throws Exception {
collection.insertOne(json("_id: 1, a: 10"));
for (int i = 0; i < 3; i++) {
collection.createIndex(json("a: 1"), new IndexOptions().unique(true));
}
syncClient.dropDatabase(db.getName());
}
// https://github.com/bwaldvogel/mongo-java-server/issues/107
@Test
public void testAddIndexAgainWithDifferentOptions() throws Exception {
collection.insertOne(json("_id: 1, a: 10"));
collection.createIndex(json("a: 1"), new IndexOptions().unique(true));
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.createIndex(json("a: 1"), new IndexOptions().unique(true).sparse(true)))
.withMessageContaining("Command failed with error 85 (IndexOptionsConflict): 'Index with name: a_1 already exists with different options'");
}
@Test
public void testEmbeddedSort() {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2"));
collection.insertOne(json("_id: 3"));
collection.insertOne(json("_id: 4, counts: {done: 1}"));
collection.insertOne(json("_id: 5, counts: {done: 2}"));
assertThat(collection.find(ne("c", true)).sort(json("'counts.done': -1, _id: 1")))
.containsExactly(
json("_id: 5, counts: {done: 2}"),
json("_id: 4, counts: {done: 1}"),
json("_id: 1"),
json("_id: 2"),
json("_id: 3")
);
}
@Test
public void testEmbeddedSort_arrayOfDocuments() {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2, counts: {done: 1}"));
collection.insertOne(json("_id: 3, counts: {done: 2}"));
collection.insertOne(json("_id: 4, counts: [{done: 2}, {done: 1}]"));
collection.insertOne(json("_id: 5, counts: [{done: 4}, {done: 2}]"));
collection.insertOne(json("_id: 6, counts: {done: [3]}"));
collection.insertOne(json("_id: 7, counts: {done: [1, 2]}"));
collection.insertOne(json("_id: 8, counts: [1, 2]"));
assertThat(collection.find(json("")).sort(json("\"counts.done\": -1, _id: 1")))
.containsExactly(
json("_id: 5, counts: [{done: 4}, {done: 2}]"),
json("_id: 6, counts: {done: [3]}"),
json("_id: 3, counts: {done: 2}"),
json("_id: 4, counts: [{done: 2}, {done: 1}]"),
json("_id: 7, counts: {done: [1, 2]}"),
json("_id: 2, counts: {done: 1}"),
json("_id: 1"),
json("_id: 8, counts: [1, 2]")
);
}
@Test
public void testFindAndModifyCommandEmpty() throws Exception {
Document cmd = new Document("findandmodify", getCollectionName());
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> db.runCommand(cmd))
.withMessageContaining("Command failed with error 9 (FailedToParse): 'Either an update or remove=true must be specified'");
}
@Test
public void testFindAndModifyCommandIllegalOp() throws Exception {
collection.insertOne(json("_id: 1"));
Document cmd = new Document("findAndModify", getCollectionName());
cmd.put("query", json("_id: 1"));
cmd.put("update", new Document("$inc", json("_id: 1")));
assertThat(collection.find().first()).isEqualTo(json("_id: 1"));
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> db.runCommand(cmd))
.withMessageContaining("Command failed with error 66 (ImmutableField): 'Performing an update on the path '_id' would modify the immutable field '_id'");
}
@Test
public void testFindAndModifyCommandUpdate() throws Exception {
collection.insertOne(json("_id: 1"));
Document cmd = new Document("findAndModify", getCollectionName());
cmd.put("query", json("_id: 1"));
cmd.put("update", json("$inc: {a: 1}"));
Document result = db.runCommand(cmd);
assertThat(result.get("lastErrorObject")).isEqualTo(json("updatedExisting: true, n: 1"));
assertThat(result.getDouble("ok")).isEqualTo(1.0);
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: 1"));
}
// https://github.com/bwaldvogel/mongo-java-server/issues/75
@Test
public void testFindAndModifyCommand_UpdateSameFields() throws Exception {
collection.insertOne(json("_id: 1"));
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(json("_id: 1"), json("$inc: {x: 0, a: 1}, $set: {a: 2}")))
.withMessageContaining("Command failed with error 40 (ConflictingUpdateOperators): 'Updating the path 'a' would create a conflict at 'a'");
}
// https://github.com/bwaldvogel/mongo-java-server/issues/75
@Test
public void testFindAndModifyCommand_UpdateFieldAndItsSubfield() throws Exception {
collection.insertOne(json("_id: 1, a: {b: {c: 1}}"));
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(json("_id: 1"), json("$set: {'x': 1, 'a.b': {c: 1}}, $inc: {'a.b.c': 1}")))
.withMessageContaining("Command failed with error 40 (ConflictingUpdateOperators): 'Updating the path 'a.b.c' would create a conflict at 'a.b'");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(json("_id: 1"), json("$set: {'x': 1, 'a.b.c': 1}, $unset: {'a.b': 1}")))
.withMessageContaining("Command failed with error 40 (ConflictingUpdateOperators): 'Updating the path 'a.b' would create a conflict at 'a.b'");
}
@Test
public void testFindOneAndUpdateError() throws Exception {
collection.insertOne(json("_id: 1, a: 1"));
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(json("_id: 1"), json("$inc: {_id: 1}")))
.withMessageContaining("Command failed with error 66 (ImmutableField): 'Performing an update on the path '_id' would modify the immutable field '_id'");
}
@Test
public void testFindOneAndUpdateFields() throws Exception {
collection.insertOne(json("_id: 1, a: 1"));
Document result = collection.findOneAndUpdate(json("_id: 1"), json("$inc: {a: 1}"),
new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER));
assertThat(result).isEqualTo(json("_id: 1, a: 2"));
}
@Test
public void testFineOneAndUpdateNotFound() throws Exception {
collection.insertOne(json("_id: 1, a: 1"));
Document result = collection.findOneAndUpdate(json("_id: 2"), new Document("$inc", json("a: 1")));
assertThat(result).isNull();
assertThat(collection.countDocuments()).isEqualTo(1);
}
@Test
public void testFineOneAndUpdateRemove() {
collection.insertOne(json("_id: 1, a: 1"));
Document result = collection.findOneAndDelete(json("_id: 1"));
assertThat(result).isEqualTo(json("_id: 1, a: 1"));
assertThat(collection.countDocuments()).isZero();
}
// https://github.com/foursquare/fongo/issues/32
@Test
public void testFineOneAndUpdateReturnNew() {
collection.insertOne(json("_id: 1, a: 1, b: {c: 1}"));
Document query = json("_id: 1");
Document update = json("$inc: {a: 1, 'b.c': 1}");
Document result = collection.findOneAndUpdate(query, update,
new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER));
assertThat(result).isEqualTo(json("_id: 1, a: 2, b: {c: 2}"));
}
@Test
public void testFineOneAndUpdateMax() {
collection.insertOne(json("_id: 1, a: 1, b: {c: 1}"));
Document query = json("_id: 1");
Document update = json("$max: {a: 2, 'b.c': 2, d : 'd'}");
Document result = collection.findOneAndUpdate(query, update,
new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER));
assertThat(result).isEqualTo(json("_id: 1, a: 2, b: {c: 2}, d : 'd'"));
}
@Test
public void testFineOneAndUpdateMin() {
collection.insertOne(json("_id: 1, a: 2, b: {c: 1}"));
Document query = json("_id: 1");
Document update = json("$min: {a: 1, 'b.c': 2, d : 'd'}");
Document result = collection.findOneAndUpdate(query, update,
new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER));
assertThat(result).isEqualTo(json("_id: 1, a: 1, b: {c: 1}, d : 'd'"));
}
// https://github.com/foursquare/fongo/issues/32
@Test
public void testFindOneAndUpdateReturnOld() {
collection.insertOne(json("_id: 1, a: 1, b: {c: 1}"));
Document query = json("_id: 1");
Document update = json("$inc: {a: 1, 'b.c': 1}");
Document result = collection.findOneAndUpdate(query, update,
new FindOneAndUpdateOptions().returnDocument(ReturnDocument.BEFORE));
assertThat(result).isEqualTo(json("_id: 1, a: 1, b: {c: 1}"));
assertThat(collection.find(query).first()).isEqualTo(json("_id: 1, a: 2, b: {c: 2}"));
}
@Test
public void testFindOneAndUpdateSorted() throws Exception {
collection.insertOne(json("_id: 1, a: 15"));
collection.insertOne(json("_id: 2, a: 10"));
collection.insertOne(json("_id: 3, a: 20"));
Document order = json("a: 1");
Document result = collection.findOneAndUpdate(json(""), json("$inc: {a: 1}"),
new FindOneAndUpdateOptions().sort(order).returnDocument(ReturnDocument.AFTER));
assertThat(result).isEqualTo(json("_id: 2, a: 11"));
order = json("a: -1");
result = collection.findOneAndUpdate(json(""), json("$inc: {a: 1}"),
new FindOneAndUpdateOptions().sort(order).returnDocument(ReturnDocument.AFTER));
assertThat(result).isEqualTo(json("_id: 3, a: 21"));
}
@Test
public void testFindOneAndUpdateUpsert() {
Document result = collection.findOneAndUpdate(json("_id: 1"), json("$inc: {a: 1}"),
new FindOneAndUpdateOptions().upsert(true).returnDocument(ReturnDocument.AFTER));
assertThat(result).isEqualTo(json("_id: 1, a: 1"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: 1"));
}
@Test
public void testFindOneAndUpdateUpsertReturnBefore() {
Document result = collection.findOneAndUpdate(json("_id: 1"), json("$inc: {a: 1}"),
new FindOneAndUpdateOptions().upsert(true).returnDocument(ReturnDocument.BEFORE));
assertThat(result).isEqualTo(json(""));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: 1"));
}
// https://github.com/bwaldvogel/mongo-java-server/issues/60
@Test
public void testFindOneAndUpdateWithArrayFilters() {
collection.insertOne(json("_id: 1, grades: [95, 102, 90, 150]"));
collection.insertOne(json("_id: 2, values: [[1, 2, 3], 'other']"));
collection.insertOne(json("_id: 3, a: {b: [1, 2, 3]}"));
collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades.$[element]': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("element: {$gte: 100}"))));
assertThat(collection.find(json("_id: 1")).first()).isEqualTo(json("_id: 1, grades: [95, 'abc', 90, 'abc']"));
collection.findOneAndUpdate(
json("_id: 1"),
json("$unset: {'grades.$[element]': 1}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("element: 'abc'"))));
assertThat(collection.find(json("_id: 1")).first()).isEqualTo(json("_id: 1, grades: [95, null, 90, null]"));
collection.findOneAndUpdate(
json("_id: 1"),
json("$inc: {'grades.$[element]': 1}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("element: 90"))));
assertThat(collection.find(json("_id: 1")).first()).isEqualTo(json("_id: 1, grades: [95, null, 91, null]"));
collection.findOneAndUpdate(
json("_id: 2"),
json("$pull: {'values.$[element]': 2}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("element: {$type: 'array'}"))));
assertThat(collection.find(json("_id: 2")).first())
.isEqualTo(json("_id: 2, values: [[1, 3], 'other']"));
collection.findOneAndUpdate(
json("_id: 3"),
json("$mul: {'a.b.$[element]': 10}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("element: 2"))));
assertThat(collection.find(json("_id: 3")).first())
.isEqualTo(json("_id: 3, a: {b: [1, 20, 3]}"));
}
// https://github.com/bwaldvogel/mongo-java-server/issues/60
@Test
public void testUpdateManyWithArrayFilters() {
collection.insertOne(json("_id: 1, values: [9, 102, 90, 150]"));
collection.insertOne(json("_id: 2, values: [1, 2, 3, 50]"));
collection.updateMany(
json(""),
json("$set: {'values.$[x]': 20}"),
new UpdateOptions().arrayFilters(Arrays.asList(json("x: {$gt: 20}")))
);
assertThat(collection.find(json("")))
.containsExactly(
json("_id: 1, values: [9, 20, 20, 20]"),
json("_id: 2, values: [1, 2, 3, 20]")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/60
@Test
public void testUpdateOneWithArrayFilter() throws Exception {
collection.insertOne(json("_id: 1, values: [{name: 'A', active: false}, {name: 'B', active: false}]"));
collection.updateOne(json("_id: 1"),
json("$set: {'values.$[elem].active': true}"),
new UpdateOptions().arrayFilters(Arrays.asList(json("'elem.name': {$in: ['A']}")))
);
assertThat(collection.find(json("")))
.containsExactly(
json("_id: 1, values: [{name: 'A', active: true}, {name: 'B', active: false}]")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/60
@Test
public void testUpsertWithArrayFilters() {
collection.updateOne(
json("_id: 1, values: [0, 1]"),
json("$set: {'values.$[x]': 20}"),
new UpdateOptions()
.upsert(true)
.arrayFilters(Arrays.asList(json("x: 0")))
);
assertThat(collection.find(json("")))
.containsExactly(
json("_id: 1, values: [20, 1]")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/60
@Test
public void testUpdateWithMultipleArrayFilters() throws Exception {
collection.insertOne(json("_id: 1, values: [9, 102, 90, 150]"));
collection.insertOne(json("_id: 2, values: [1, 2, 30, 50]"));
collection.updateMany(
json(""),
json("$set: {'values.$[tooLow]': 10, 'values.$[tooHigh]': 40}"),
new UpdateOptions().arrayFilters(Arrays.asList(
json("tooLow: {$lte: 10}"),
json("tooHigh: {$gt: 40}")
))
);
assertThat(collection.find(json("")))
.containsExactly(
json("_id: 1, values: [10, 40, 40, 40]"),
json("_id: 2, values: [10, 10, 30, 40]")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/86
@Test
public void testUpdateWithMultipleComplexArrayFilters() throws Exception {
collection.insertOne(json("_id: 1, products: [" +
"{id: 1, charges: [" +
"{type: 'A', min: 0, max: 1}, " +
"{type: 'A', min: 0, max: 2}, " +
"{type: 'B', min: 0, max: 1}, " +
"]}, " +
"{id: 2, charges: [{type: 'A', min: 0, max: 1}, ]}, " +
"]"));
collection.updateMany(
json(""),
json("$set: {'products.$[product].charges.$[charge].amount': 10}"),
new UpdateOptions().arrayFilters(Arrays.asList(
json("'product.id': 1"),
json("'charge.type': 'A', 'charge.min': 0, 'charge.max': 2")
))
);
assertThat(collection.find(json("")))
.containsExactly(
json("_id: 1, products: [" +
"{id: 1, charges: [" +
"{type: 'A', min: 0, max: 1}, " +
"{type: 'A', min: 0, max: 2, amount: 10}, " +
"{type: 'B', min: 0, max: 1}, " +
"]}, " +
"{id: 2, charges: [{type: 'A', min: 0, max: 1}, ]}, " +
"]")
);
}
@Test
public void testFindOneAndUpdate_IllegalArrayFilters() {
collection.insertOne(json("_id: 1, grades: 'abc', a: {b: 123}"));
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("element: {$gte: 100}")))))
.withMessageContaining("Command failed with error 9 (FailedToParse): 'The array filter for identifier 'element' was not used in the update { $set: { grades: \"abc\" } }'");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(
json("element: {$gte: 100}"),
json("element: {$lt: 100}")
))))
.withMessageContaining("Command failed with error 9 (FailedToParse): 'Found multiple array filters with the same top-level field name element'");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades.$[element]': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("a: {$gte: 100}, b: {$gte: 100}, c: {$gte: 10}")))))
.withMessageContaining("Command failed with error 9 (FailedToParse): 'Error parsing array filter :: caused by :: Expected a single top-level field name, found 'a' and 'b'");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades.$[element]': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("")))))
.withMessageContaining("Command failed with error 9 (FailedToParse): 'Cannot use an expression without a top-level field name in arrayFilters'");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades.$[element]': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("element: {$gte: 100}")))))
.withMessageContaining("Command failed with error 2 (BadValue): 'Cannot apply array updates to non-array element grades: \"abc\"'");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'$[element]': 10}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("element: 2")))))
.withMessageContaining("Command failed with error 2 (BadValue): 'Cannot have array filter identifier (i.e. '$[]') element in the first position in path '$[element]'");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades.subGrades.$[element]': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("element: {$gte: 100}")))))
.withMessageContaining("Command failed with error 2 (BadValue): 'The path 'grades.subGrades' must exist in the document in order to apply array updates.'");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades.$[some value]': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("'some value': {$gte: 100}")))))
.withMessageContaining("Command failed with error 2 (BadValue): 'Error parsing array filter :: caused by :: The top-level field name must be an alphanumeric string beginning with a lowercase letter, found 'some value''");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'a.b.$[x]': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("x: {$gte: 100}")))))
.withMessageContaining("Command failed with error 2 (BadValue): 'Cannot apply array updates to non-array element b: 123'");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("'a.b': 10, b: 12")))))
.withMessageContaining("Command failed with error 9 (FailedToParse): 'Error parsing array filter :: caused by :: Expected a single top-level field name, found 'a' and 'b''");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(
json("'a.b': 10"),
json("'a.c': 10")
))))
.withMessageContaining("Command failed with error 9 (FailedToParse): 'Found multiple array filters with the same top-level field name a'");
}
@Test
public void testFindOneAndUpdate_IllegalArrayFiltersPaths() {
collection.insertOne(json("_id: 1, grades: 'abc', a: {b: [1, 2, 3]}"));
collection.insertOne(json("_id: 2, grades: 'abc', a: {b: [{c: 1}, {c: 2}, {c: 3}]}"));
collection.insertOne(json("_id: 3, grades: 'abc', a: {b: [[[1, 2], [3, 4]]]}"));
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'a.b.$[x].c': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("x: {$gt: 1}")))))
.withMessageContaining("Command failed with error 28 (PathNotViable): 'Cannot create field 'c' in element {1: 2}");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'a.b.$[x].c.d': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("x: {$gt: 1}")))))
.withMessageContaining("Command failed with error 28 (PathNotViable): 'Cannot create field 'c' in element {1: 2}");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 2"),
json("$set: {'a.b.$[].c.$[]': 'abc'}")))
.withMessageContaining("Command failed with error 2 (BadValue): 'Cannot apply array updates to non-array element c: 1");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 3"),
json("$set: {'a.b.$[].0.c': 'abc'}")))
.withMessageContaining("Command failed with error 28 (PathNotViable): 'Cannot create field 'c' in element {0: [ 1, 2 ]}");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 3"),
json("$set: {'a.b.$[].0.$[].c': 'abc'}")))
.withMessageContaining("Command failed with error 28 (PathNotViable): 'Cannot create field 'c' in element {0: 1}");
}
@Test
public void testFindAndRemoveFromEmbeddedList() {
collection.insertOne(json("_id: 1, a: [1]"));
Document result = collection.findOneAndDelete(json("_id: 1"));
assertThat(result).isEqualTo(json("_id: 1, a: [1]"));
assertThat(collection.countDocuments()).isZero();
}
@Test
public void testFindOne() {
collection.insertOne(json("key: 'value'"));
collection.insertOne(json("key: 'value'"));
Document result = collection.find().first();
assertThat(result).isNotNull();
assertThat(result.get("_id")).isNotNull();
}
@Test
public void testFindOneById() {
collection.insertOne(json("_id: 1"));
Document result = collection.find(json("_id: 1")).first();
assertThat(result).isEqualTo(json("_id: 1"));
assertThat(collection.find(json("_id: 2")).first()).isNull();
}
@Test
public void testFindOneIn() {
collection.insertOne(json("_id: 1"));
Document result = collection.find(json("_id: {$in: [1, 2]}")).first();
assertThat(result).isEqualTo(json("_id: 1"));
}
@Test
public void testFindWithLimit() {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2"));
collection.insertOne(json("_id: 3"));
collection.insertOne(json("_id: 4"));
assertThat(collection.find().sort(json("_id: 1")).limit(2))
.containsExactly(
json("_id: 1"),
json("_id: 2")
);
assertThat(collection.find().sort(json("_id: 1")).limit(-2))
.containsExactly(
json("_id: 1"),
json("_id: 2")
);
}
@Test
public void testFindInReverseNaturalOrder() {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2"));
assertThat(collection.find().sort(json("$natural: -1")))
.containsExactly(
json("_id: 2"),
json("_id: 1")
);
}
@Test
public void testFindWithPattern() {
collection.insertOne(json("_id: 'marta'"));
collection.insertOne(json("_id: 'john', foo: 'bar'"));
collection.insertOne(json("_id: 'jon', foo: 'ba'"));
collection.insertOne(json("_id: 'jo'"));
assertThat(collection.find(new Document("_id", Pattern.compile("mart"))))
.containsExactly(json("_id: 'marta'"));
assertThat(collection.find(new Document("foo", Pattern.compile("ba"))))
.containsExactly(json("_id: 'john', foo: 'bar'"), json("_id: 'jon', foo: 'ba'"));
assertThat(collection.find(new Document("foo", Pattern.compile("ba$"))))
.containsExactly(json("_id: 'jon', foo: 'ba'"));
}
@Test
public void testFindWithQuery() {
collection.insertOne(json("name: 'jon'"));
collection.insertOne(json("name: 'leo'"));
collection.insertOne(json("name: 'neil'"));
collection.insertOne(json("name: 'neil'"));
assertThat(collection.find(json("name: 'neil'"))).hasSize(2);
}
@Test
public void testFindWithSkipLimit() {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2"));
collection.insertOne(json("_id: 3"));
collection.insertOne(json("_id: 4"));
assertThat(collection.find().sort(json("_id: 1")).limit(2).skip(2))
.containsExactly(json("_id: 3"), json("_id: 4"));
}
@Test
public void testFindWithSkipLimitInReverseOrder() {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2"));
collection.insertOne(json("_id: 3"));
collection.insertOne(json("_id: 4"));
assertThat(collection.find().sort(json("_id: -1")).limit(2).skip(2))
.containsExactly(json("_id: 2"), json("_id: 1"));
}
@Test
public void testFindWithSkipLimitAfterDelete() {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2"));
collection.insertOne(json("_id: 3"));
collection.insertOne(json("_id: 4"));
collection.insertOne(json("_id: 5"));
collection.deleteOne(json("_id: 1"));
collection.deleteOne(json("_id: 3"));
assertThat(collection.find().sort(json("_id: 1")).limit(2).skip(2))
.containsExactly(json("_id: 5"));
}
@Test
public void testFullUpdateWithSameId() throws Exception {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2, b: 5"));
collection.insertOne(json("_id: 3"));
collection.insertOne(json("_id: 4"));
collection.replaceOne(json("_id: 2, b: 5"), json("_id: 2, a: 5"));
assertThat(collection.find(json("_id: 2")).first()).isEqualTo(json("_id: 2, a: 5"));
}
@Test
public void testGetCollection() {
MongoCollection collection = getCollection("coll");
getCollection("coll").insertOne(json(""));
assertThat(collection).isNotNull();
assertThat(db.listCollectionNames()).contains("coll");
}
@Test
public void testNullId() throws Exception {
collection.insertOne(json("_id: null, name: 'test'"));
Document result = collection.find(json("name: 'test'")).first();
assertThat(result).isNotNull();
assertThat(result.getObjectId(Constants.ID_FIELD)).isNull();
assertMongoWriteException(() -> collection.insertOne(json("_id: null")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: _id_ dup key: { : null }");
assertThat(collection.countDocuments()).isEqualTo(1);
assertThat(collection.find(json("_id: null")).first()).isEqualTo(json("_id: null, name: 'test'"));
collection.deleteOne(json("_id: null"));
assertThat(collection.countDocuments()).isZero();
}
@Test
public void testIdInQueryResultsInIndexOrder() {
collection.insertOne(json("_id: 4"));
collection.insertOne(json("_id: 3"));
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2"));
assertThat(collection.find(json("_id: {$in: [3, 2, 1]}")))
.containsExactlyInAnyOrder(
json("_id: 1"),
json("_id: 2"),
json("_id: 3")
);
// https://github.com/bwaldvogel/mongo-java-server/issues/57
assertThat(collection.find(json("_id: {$in: [[1, 2, 3]]}")))
.isEmpty();
}
@Test
public void testInQuery_Arrays() throws Exception {
collection.insertOne(json("_id: 1, v: [1, 2, 3]"));
collection.insertOne(json("_id: 2, v: [1, 2]"));
collection.insertOne(json("_id: 3, v: 50"));
collection.insertOne(json("_id: 4, v: null"));
collection.insertOne(json("_id: 5"));
assertThat(collection.find(json("v: {$in: [[1, 2, 3], 50]}")))
.containsExactly(
json("_id: 1, v: [1, 2, 3]"),
json("_id: 3, v: 50")
);
assertThat(collection.find(json("v: {$not: {$in: [[1, 2, 3], 50]}}")))
.containsExactlyInAnyOrder(
json("_id: 2, v: [1, 2]"),
json("_id: 4, v: null"),
json("_id: 5")
);
assertThat(collection.find(json("v: {$not: {$in: [2, 50]}}")))
.containsExactlyInAnyOrder(
json("_id: 4, v: null"),
json("_id: 5")
);
assertThat(collection.find(json("v: {$not: {$in: [[1, 2], 50, null]}}")))
.containsExactly(
json("_id: 1, v: [1, 2, 3]")
);
}
@Test
public void testIdNotAllowedToBeUpdated() {
collection.insertOne(json("_id: 1"));
assertMongoWriteException(() -> collection.replaceOne(json("_id: 1"), json("_id: 2, a: 4")),
66, "ImmutableField", "After applying the update, the (immutable) field '_id' was found to have been altered to _id: 2");
// test with $set
assertMongoWriteException(() -> collection.updateOne(json("_id: 1"), new Document("$set", json("_id: 2"))),
66, "ImmutableField", "Performing an update on the path '_id' would modify the immutable field '_id'");
}
@Test
public void testIllegalCommand() throws Exception {
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> db.runCommand(json("foo: 1")))
.withMessageContaining("Command failed with error 59 (CommandNotFound): 'no such command: 'foo'");
}
@Test
public void testInsert() throws Exception {
assertThat(collection.countDocuments()).isEqualTo(0);
for (int i = 0; i < 3; i++) {
collection.insertOne(new Document("_id", Integer.valueOf(i)));
}
assertThat(collection.countDocuments()).isEqualTo(3);
collection.insertOne(json("foo: [1, 2, 3]"));
collection.insertOne(new Document("foo", new byte[10]));
Document insertedObject = new Document("foo", UUID.randomUUID());
collection.insertOne(insertedObject);
Document document = collection.find(insertedObject).first();
assertThat(document).isEqualTo(insertedObject);
}
@Test
public void testInsertDuplicate() throws Exception {
assertThat(collection.countDocuments()).isEqualTo(0);
collection.insertOne(json("_id: 1"));
assertThat(collection.countDocuments()).isEqualTo(1);
assertMongoWriteException(() -> collection.insertOne(json("_id: 1.0")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: _id_ dup key: { : 1.0 }");
assertThat(collection.countDocuments()).isEqualTo(1);
}
@Test(expected = MongoException.class)
public void testInsertDuplicateThrows() {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 1"));
}
@Test(expected = MongoException.class)
public void testInsertDuplicateWithConcernThrows() {
collection.insertOne(json("_id: 1"));
collection.withWriteConcern(WriteConcern.ACKNOWLEDGED).insertOne(json("_id: 1"));
}
@Test
public void testInsertIncrementsCount() {
assertThat(collection.countDocuments()).isZero();
collection.insertOne(json("key: 'value'"));
assertThat(collection.countDocuments()).isEqualTo(1);
}
@Test
public void testInsertQuery() throws Exception {
assertThat(collection.countDocuments()).isEqualTo(0);
Document insertedObject = json("_id: 1");
insertedObject.put("foo", "bar");
collection.insertOne(insertedObject);
assertThat(collection.find(insertedObject).first()).isEqualTo(insertedObject);
assertThat(collection.find(new Document("_id", Long.valueOf(1))).first()).isEqualTo(insertedObject);
assertThat(collection.find(new Document("_id", Double.valueOf(1.0))).first()).isEqualTo(insertedObject);
assertThat(collection.find(new Document("_id", Float.valueOf(1.0001f))).first()).isNull();
assertThat(collection.find(json("foo: 'bar'")).first()).isEqualTo(insertedObject);
}
@Test
public void testInsertRemove() throws Exception {
for (int i = 0; i < 10; i++) {
collection.insertOne(json("_id: 1"));
assertThat(collection.countDocuments()).isEqualTo(1);
collection.deleteOne(json("_id: 1"));
assertThat(collection.countDocuments()).isZero();
collection.insertOne(new Document("_id", i));
collection.deleteOne(new Document("_id", i));
}
assertThat(collection.countDocuments()).isZero();
collection.deleteOne(json("'doesnt exist': 1"));
assertThat(collection.countDocuments()).isZero();
}
@Test
public void testInsertInSystemNamespace() throws Exception {
assertMongoWriteException(() -> getCollection("system.foobar").insertOne(json("")),
16459, "attempt to insert in system namespace");
assertMongoWriteException(() -> getCollection("system.namespaces").insertOne(json("")),
16459, "attempt to insert in system namespace");
}
@Test
public void testListDatabaseNames() throws Exception {
assertThat(listDatabaseNames()).isEmpty();
collection.insertOne(json(""));
assertThat(listDatabaseNames()).containsExactly(db.getName());
getDatabase().getCollection("some-collection").insertOne(json(""));
assertThat(listDatabaseNames()).containsExactly("bar", db.getName());
}
private MongoDatabase getDatabase() {
return syncClient.getDatabase(OTHER_TEST_DATABASE_NAME);
}
private List listDatabaseNames() {
List databaseNames = new ArrayList<>();
for (String databaseName : syncClient.listDatabaseNames()) {
databaseNames.add(databaseName);
}
return databaseNames;
}
@Test
public void testQuery() throws Exception {
Document obj = collection.find(json("_id: 1")).first();
assertThat(obj).isNull();
assertThat(collection.countDocuments()).isEqualTo(0);
}
@Test
public void testQueryAll() throws Exception {
List inserted = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Document obj = new Document("_id", i);
collection.insertOne(obj);
inserted.add(obj);
}
assertThat(collection.countDocuments()).isEqualTo(10);
assertThat(collection.find().sort(json("_id: 1")))
.containsExactlyElementsOf(inserted);
}
@Test
public void testQueryCount() throws Exception {
for (int i = 0; i < 100; i++) {
collection.insertOne(json(""));
}
assertThat(collection.countDocuments()).isEqualTo(100);
Document obj = json("_id: 1");
assertThat(collection.countDocuments(obj)).isEqualTo(0);
collection.insertOne(obj);
assertThat(collection.countDocuments(obj)).isEqualTo(1);
}
@Test
public void testQueryLimitEmptyQuery() throws Exception {
for (int i = 0; i < 5; i++) {
collection.insertOne(json(""));
}
assertThat(collection.countDocuments(json(""), new CountOptions().limit(1))).isEqualTo(1);
assertThat(collection.countDocuments(json(""), new CountOptions().limit(-1))).isEqualTo(5);
assertThat(collection.countDocuments(json(""))).isEqualTo(5);
}
@Test
public void testQueryLimitSimpleQuery() throws Exception {
for (int i = 0; i < 5; i++) {
collection.insertOne(json("a: 1"));
}
assertThat(collection.countDocuments(json("a: 1"), new CountOptions().limit(1))).isEqualTo(1);
assertThat(collection.countDocuments(json("a: 1"), new CountOptions().limit(-1))).isEqualTo(5);
assertThat(collection.countDocuments(json("a: 1"))).isEqualTo(5);
}
@Test
public void testQueryNull() throws Exception {
Document object = json("_id: 1");
collection.insertOne(object);
assertThat(collection.find(json("foo: null")).first()).isEqualTo(object);
}
@Test
public void testQuerySkipLimitEmptyQuery() throws Exception {
assertThat(collection.countDocuments(json(""), new CountOptions().skip(3))).isEqualTo(0);
for (int i = 0; i < 10; i++) {
collection.insertOne(json(""));
}
assertThat(collection.countDocuments(json(""), new CountOptions().skip(3))).isEqualTo(7);
assertThat(collection.countDocuments(json(""), new CountOptions().skip(15))).isEqualTo(0);
assertThat(collection.countDocuments(json(""), new CountOptions().skip(3).limit(5))).isEqualTo(5);
}
@Test
public void testQuerySkipLimitSimpleQuery() throws Exception {
assertThat(collection.countDocuments(json("a: 1"), new CountOptions().skip(3))).isEqualTo(0);
for (int i = 0; i < 10; i++) {
collection.insertOne(json("a: 1"));
}
assertThat(collection.countDocuments(json("a: 1"), new CountOptions().skip(3))).isEqualTo(7);
assertThat(collection.countDocuments(json("a: 1"), new CountOptions().skip(3).limit(5))).isEqualTo(5);
assertThat(collection.countDocuments(json("a: 1"), new CountOptions().skip(15).limit(5))).isEqualTo(0);
}
@Test
public void testQuerySort() throws Exception {
Random random = new Random(4711);
for (int i = 0; i < 10; i++) {
collection.insertOne(new Document("_id", Double.valueOf(random.nextDouble())));
}
assertThat(collection.find().sort(json("_id: 1")))
.extracting(d -> d.getDouble("_id"))
.isSorted();
assertThat(collection.find().sort(json("_id: -1")))
.extracting(d -> d.getDouble("_id"))
.isSortedAccordingTo(Comparator.comparingDouble(Double::doubleValue).reversed());
}
@Test
public void testQueryWithFieldSelector() throws Exception {
collection.insertOne(json("foo: 'bar'"));
collection.insertOne(json("foo: null"));
Document obj = collection.find(json("")).projection(json("foo: 1")).first();
assertThat(obj).containsOnlyKeys("_id", "foo");
obj = collection.find(json("foo: 'bar'")).projection(json("_id: 1")).first();
assertThat(obj).containsOnlyKeys("_id");
obj = collection.find(json("foo: null")).projection(json("_id: 0, foo: 1")).first();
assertThat(obj).isEqualTo(json("foo: null"));
obj = collection.find(json("foo: 'bar'")).projection(json("_id: 0, foo: 1")).first();
assertThat(obj).containsOnlyKeys("foo");
}
@Test
public void testQueryWithDotNotationFieldSelector() throws Exception {
collection.insertOne(json("_id: 1, index: false, foo: {a: 'a1', b: 0}"));
collection.insertOne(json("_id: 2, foo: {a: null, b: null}"));
Document obj = collection.find(json("_id: 1")).projection(json("'foo.a': 1, 'foo.b': 1")).first();
assertThat(obj).isEqualTo(json("_id: 1, foo: {a: 'a1', b: 0}"));
obj = collection.find(json("_id: 1")).projection(json("'foo.a': 1")).first();
assertThat(obj).isEqualTo(json("_id: 1, foo: {a: 'a1'}"));
obj = collection.find(json("_id: 1")).projection(json("'foo.a': 1, index: 1, _id: 0")).first();
assertThat(obj).isEqualTo(json("foo: {a: 'a1'}, index: false"));
obj = collection.find(json("_id: 1")).projection(json("foo: 1, _id: 0")).first();
assertThat(obj).isEqualTo(json("foo: {a: 'a1', b: 0}"));
obj = collection.find(json("_id: 1")).projection(json("'foo.a.b.c.d': 1")).first();
assertThat(obj).isEqualTo(json("_id: 1, foo: {}"));
obj = collection.find(json("_id: 1")).projection(json("'foo..': 1")).first();
assertThat(obj).isEqualTo(json("_id: 1, foo: {}"));
obj = collection.find(json("_id: 2")).projection(json("'foo.a.b': 1, 'foo.b': 1, 'foo.c': 1, 'foo.c.d': 1")).first();
assertThat(obj).isEqualTo(json("_id: 2, foo: {b: null}"));
obj = collection.find(json("_id: 2")).projection(json("'foo.a': 1")).first();
assertThat(obj).isEqualTo(json("_id: 2, foo: {a: null}"));
obj = collection.find(json("_id: 2")).projection(json("'foo.c': 1")).first();
assertThat(obj).isEqualTo(json("_id: 2, foo: {}"));
}
@Test
public void testQueryWithDotNotationFieldSelector_Array() throws Exception {
collection.insertOne(json("_id: 1, values: [1, 2, {x: 100, y: 10}, {x: 200}]"));
Document obj = collection.find(json("_id: 1")).projection(json("'values.0': 1, 'values.x': 1")).first();
assertThat(obj).isEqualTo(json("_id: 1, values: [{x: 100}, {x: 200}]"));
obj = collection.find(json("_id: 1")).projection(json("'values.y': 1")).first();
assertThat(obj).isEqualTo(json("_id: 1, values: [{y: 10}, {}]"));
obj = collection.find(json("_id: 1")).projection(json("'values.x': 1, 'values.y': 1")).first();
assertThat(obj).isEqualTo(json("_id: 1, values: [{x: 100, y: 10}, {x: 200}]"));
}
@Test
public void testQueryWithIllegalFieldSelection() throws Exception {
collection.insertOne(json("_id: 1"));
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("_id: 1")).projection(json("values: {x: 1, y: 1}")).first())
.withMessageContaining("Query failed with error code 2 and error message '>1 field in obj: { x: 1, y: 1 }'");
}
@Test
public void testQuerySystemNamespace() throws Exception {
assertThat(getCollection("system.foobar").find().first()).isNull();
assertThat(db.listCollectionNames()).isEmpty();
collection.insertOne(json(""));
Document expectedObj = new Document("name", collection.getNamespace().getFullName());
Document coll = getCollection("system.namespaces").find(expectedObj).first();
assertThat(coll).isEqualTo(expectedObj);
}
@Test
public void testQueryAllExpression() throws Exception {
collection.insertOne(json("a: [{x: 1}, {x: 2}]"));
collection.insertOne(json("a: [{x: 2}, {x: 3}]"));
assertThat(collection.countDocuments(json("'a.x': {$all: [1, 2]}"))).isEqualTo(1);
assertThat(collection.countDocuments(json("'a.x': {$all: [2, 3]}"))).isEqualTo(1);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/36
@Test
public void testAndQueryWithAllAndNin() throws Exception {
collection.insertOne(json("_id: 1, tags: ['A', 'B']"));
collection.insertOne(json("_id: 2, tags: ['A', 'D']"));
collection.insertOne(json("_id: 3, tags: ['A', 'C']"));
collection.insertOne(json("_id: 4, tags: ['C', 'D']"));
assertThat(collection.find(json("$and: [{'tags': {$all: ['A']}}, {'tags': {$nin: ['B', 'C']}}]")))
.containsExactly(json("_id: 2, tags: ['A', 'D']"));
}
// https://github.com/bwaldvogel/mongo-java-server/issues/96
@Test
public void testAndQueryWithAllAndSize() throws Exception {
collection.insertOne(json("_id: 1, list: ['A', 'B']"));
collection.insertOne(json("_id: 2, list: ['A', 'B', 'C']"));
assertThat(collection.find(json("$and: [{list: {$size: 2}}, {list: {$all: ['A', 'B']}}]}")))
.containsExactly(json("_id: 1, list: ['A', 'B']"));
assertThat(collection.find(json("list: {$all: ['A', 'B'], $size: 2}")))
.containsExactly(json("_id: 1, list: ['A', 'B']"));
}
// https://github.com/bwaldvogel/mongo-java-server/issues/36
@Test
public void testMatchesAllWithEmptyCollection() throws Exception {
collection.insertOne(json("_id: 1, text: 'TextA', tags: []"));
collection.insertOne(json("_id: 2, text: 'TextB', tags: []"));
collection.insertOne(json("_id: 3, text: 'TextA', tags: ['A']"));
assertThat(collection.find(json("$and: [{'text': 'TextA'}, {'tags': {$all: []}}]"))).isEmpty();
}
@Test
public void testQueryWithSubdocumentIndex() throws Exception {
collection.createIndex(json("action: {actionId: 1}"), new IndexOptions().unique(true));
collection.insertOne(json("action: {actionId: 1}, value: 'a'"));
collection.insertOne(json("action: {actionId: 2}, value: 'b'"));
collection.insertOne(json("action: {actionId: 3}, value: 'c'"));
Document foundWithNestedDocument = collection.find(json("action: {actionId: 2}")).first();
assertThat(foundWithNestedDocument.get("value")).isEqualTo("b");
Document foundWithDotNotation = collection.find(json("'action.actionId': 2")).first();
assertThat(foundWithDotNotation.get("value")).isEqualTo("b");
}
// see https://github.com/bwaldvogel/mongo-java-server/issues/12
@Test
public void testQueryBinaryData() throws Exception {
byte[] firstBytes = new byte[] { 0x01, 0x02, 0x03 };
byte[] secondBytes = new byte[] { 0x03, 0x02, 0x01 };
collection.insertOne(new Document("_id", 1).append("test", firstBytes));
collection.insertOne(new Document("_id", 2).append("test", secondBytes));
Document first = collection.find(new Document("test", firstBytes)).first();
assertThat(first).isNotNull();
assertThat(first.get("_id")).isEqualTo(1);
Document second = collection.find(new Document("test", secondBytes)).first();
assertThat(second).isNotNull();
assertThat(second.get("_id")).isEqualTo(2);
}
@Test
public void testRemove() {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2"));
collection.insertOne(json("_id: 3"));
collection.insertOne(json("_id: 4"));
collection.deleteOne(json("_id: 2"));
assertThat(collection.find(json("_id: 2")).first()).isNull();
assertThat(collection.countDocuments()).isEqualTo(3);
collection.deleteMany(json("_id: {$gte: 3}"));
assertThat(collection.countDocuments()).isEqualTo(1);
assertThat(collection.find().first()).isEqualTo(json("_id: 1"));
}
@Test
public void testRemoveSingle() throws Exception {
Document obj = new Document("_id", ObjectId.get());
collection.insertOne(obj);
collection.deleteOne(obj);
}
@Test
public void testRemoveReturnsModifiedDocumentCount() {
collection.insertOne(json(""));
collection.insertOne(json(""));
DeleteResult result = collection.deleteMany(json(""));
assertThat(result.getDeletedCount()).isEqualTo(2);
result = collection.deleteMany(json(""));
assertThat(result.getDeletedCount()).isEqualTo(0);
}
@Test
public void testReservedCollectionNames() throws Exception {
assertMongoWriteException(() -> getCollection("foo$bar").insertOne(json("")),
10093, "cannot insert into reserved $ collection");
String veryLongString = repeat("verylongstring", 5);
assertMongoWriteException(() -> getCollection(veryLongString).insertOne(json("")),
10080, "ns name too long, max size is 128");
}
private static String repeat(String str, int num) {
String repeated = str;
for (int i = 0; i < num; i++) {
repeated += repeated;
}
return repeated;
}
@Test
public void testServerStatus() throws Exception {
Document serverStatus = runCommand("serverStatus");
assertThat(serverStatus.getDouble("ok")).isEqualTo(1);
assertThat(serverStatus.get("uptime")).isInstanceOf(Number.class);
assertThat(serverStatus.get("uptimeMillis")).isInstanceOf(Long.class);
Instant serverTime = ((Date) serverStatus.get("localTime")).toInstant();
assertThat(serverTime).isEqualTo(TEST_CLOCK.instant());
Document connections = (Document) serverStatus.get("connections");
assertThat(connections.get("current")).isNotNull();
}
@Test
public void testPing() throws Exception {
assertThat(runCommand("ping").getDouble("ok")).isEqualTo(1.0);
assertThat(runCommand(json("ping: true")).getDouble("ok")).isEqualTo(1.0);
assertThat(runCommand(json("ping: 2.0")).getDouble("ok")).isEqualTo(1.0);
}
@Test
public void testReplSetGetStatus() throws Exception {
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> runCommand("replSetGetStatus"))
.withMessageContaining("Command failed with error 76 (NoReplicationEnabled): 'not running with --replSet'");
}
@Test
public void testWhatsMyUri() throws Exception {
for (String dbName : new String[] { "admin", "local", "test" }) {
Document result = syncClient.getDatabase(dbName).runCommand(new Document("whatsmyuri", 1));
assertThat(result.get("you")).isNotNull();
assertThat(result.get("you").toString()).startsWith("127.0.0.1:");
}
}
@Test
public void testSortDocuments() throws Exception {
collection.insertOne(json("_id: 1, a: {b: 1}"));
collection.insertOne(json("_id: 2, a: {b: 2}"));
collection.insertOne(json("_id: 3, a: 3"));
collection.insertOne(json("_id: 4, a: {c: 1}"));
assertThat(collection.find().sort(json("a: 1")))
.containsExactly(
json("_id: 3, a: 3"),
json("_id: 1, a: {b: 1}"),
json("_id: 2, a: {b: 2}"),
json("_id: 4, a: {c: 1}")
);
assertThat(collection.find().sort(json("a: -1")))
.containsExactly(
json("_id: 4, a: {c: 1}"),
json("_id: 2, a: {b: 2}"),
json("_id: 1, a: {b: 1}"),
json("_id: 3, a: 3")
);
}
@Test
public void testSort() {
collection.insertOne(json("_id: 1, a: null"));
collection.insertOne(json("_id: 2, a: 1"));
collection.insertOne(json("_id: 3, a: 2"));
collection.insertOne(json("_id: 4"));
collection.insertOne(json("_id: 5, a: 3"));
collection.insertOne(json("_id: 6, a: 4"));
collection.insertOne(json("_id: 7, a: 'abc'"));
collection.insertOne(json("_id: 8, a: 'zzz'"));
collection.insertOne(json("_id: 9, a: 1.0"));
assertThat(collection.find().sort(json("a: 1, _id: 1")))
.containsExactly(
json("_id: 1, a: null"),
json("_id: 4"),
json("_id: 2, a: 1"),
json("_id: 9, a: 1.0"),
json("_id: 3, a: 2"),
json("_id: 5, a: 3"),
json("_id: 6, a: 4"),
json("_id: 7, a: 'abc'"),
json("_id: 8, a: 'zzz'")
);
assertThat(collection.find().sort(json("a: -1, _id: 1")))
.containsExactly(
json("_id: 8, a: 'zzz'"),
json("_id: 7, a: 'abc'"),
json("_id: 6, a: 4"),
json("_id: 5, a: 3"),
json("_id: 3, a: 2"),
json("_id: 2, a: 1"),
json("_id: 9, a: 1.0"),
json("_id: 1, a: null"),
json("_id: 4")
);
}
@Test
public void testSortByEmbeddedKey() {
collection.insertOne(json("_id: 1, a: {b: 1}"));
collection.insertOne(json("_id: 2, a: {b: 2}"));
collection.insertOne(json("_id: 3, a: {b: 3}"));
assertThat(collection.find().sort(json("'a.b': -1")))
.containsExactly(
json("_id: 3, a: {b: 3}"),
json("_id: 2, a: {b: 2}"),
json("_id: 1, a: {b: 1}")
);
}
@Test
public void testUpdate() throws Exception {
Document object = json("_id: 1");
Document newObject = json("_id: 1, foo: 'bar'");
collection.insertOne(object);
UpdateResult result = collection.replaceOne(object, newObject);
assertThat(result.getModifiedCount()).isEqualTo(1);
assertThat(result.getUpsertedId()).isNull();
assertThat(collection.find(object).first()).isEqualTo(newObject);
}
@Test
public void testUpdateNothing() throws Exception {
Document object = json("_id: 1");
UpdateResult result = collection.replaceOne(object, object);
assertThat(result.getModifiedCount()).isEqualTo(0);
assertThat(result.getMatchedCount()).isEqualTo(0);
assertThat(result.getUpsertedId()).isNull();
}
@Test
public void testUpdateBlank() throws Exception {
Document document = json("'': 1, _id: 2, a: 3, b: 4");
collection.insertOne(document);
collection.updateOne(json(""), json("$set: {c: 5}"));
assertThat(collection.find().first()).isEqualTo(json("'': 1, _id: 2, a: 3, b: 4, c: 5"));
}
@Test
public void testUpdateEmptyPositional() throws Exception {
collection.insertOne(json(""));
assertMongoWriteException(() -> collection.updateOne(json(""), json("$set: {'a.$.b': 1}")),
2, "BadValue", "The positional operator did not find the match needed from the query.");
}
@Test
public void testUpdateMultiplePositional() throws Exception {
collection.insertOne(json("a: {b: {c: 1}}"));
assertMongoWriteException(() -> collection.updateOne(json("'a.b.c': 1"), json("$set: {'a.$.b.$.c': 1}")),
2, "BadValue", "Too many positional (i.e. '$') elements found in path 'a.$.b.$.c'");
}
@Test
public void testUpdateIllegalFieldName() throws Exception {
// Disallow $ in field names - SERVER-3730
collection.insertOne(json("x: 1"));
collection.updateOne(json("x: 1"), json("$set: {y: 1}")); // ok
assertMongoWriteException(() -> collection.updateOne(json("x: 1"), json("$set: {$z: 1}")),
15896, "Modified field name may not start with $");
// unset ok to remove bad fields
collection.updateOne(json("x: 1"), json("$unset: {$z: 1}"));
assertMongoWriteException(() -> collection.updateOne(json("x: 1"), json("$inc: {$z: 1}")),
15896, "Modified field name may not start with $");
assertMongoWriteException(() -> collection.updateOne(json("x: 1"), json("$pushAll: {$z: [1, 2, 3]}")),
15896, "Modified field name may not start with $");
}
@Test
public void testUpdateSubdocument() throws Exception {
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> collection.updateOne(json(""), json("'a.b.c': 123")))
.withMessage("Invalid BSON field name a.b.c");
}
@Test
public void testInsertWithIllegalFieldNames() throws Exception {
for (String illegalFieldName : Arrays.asList("a.", "a.b.", "a.....111", "a.b")) {
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> collection.insertOne(new Document(illegalFieldName, 1)))
.withMessage("Invalid BSON field name " + illegalFieldName);
}
}
@Test
public void testUpdateIdNoChange() {
collection.insertOne(json("_id: 1"));
collection.replaceOne(json("_id: 1"), json("_id: 1, a: 5"));
assertThat(collection.find(json("_id: 1")).first()).isEqualTo(json("_id: 1, a: 5"));
collection.updateOne(json("_id: 1"), json("$set: {_id: 1, b: 3}"));
assertThat(collection.find(json("_id: 1")).first()).isEqualTo(json("_id: 1, a: 5, b: 3"));
// test with $set
collection.updateOne(json("_id: 1"), json("$set: {_id: 1, a: 7}"));
assertThat(collection.find(json("_id: 1")).first()).isEqualTo(json("_id: 1, a: 7, b: 3"));
}
@Test
public void testUpdatePush() throws Exception {
Document idObj = json("_id: 1");
collection.insertOne(idObj);
collection.updateOne(idObj, json("$push: {'field.subfield.subsubfield': 'value'}"));
Document expected = json("_id: 1, field: {subfield: {subsubfield: ['value']}}");
assertThat(collection.find(idObj).first()).isEqualTo(expected);
// push to non-array
collection.updateOne(idObj, json("$set: {field: 'value'}"));
assertMongoWriteException(() -> collection.updateOne(idObj, json("$push: {field: 'value'}")),
2, "BadValue", "The field 'field' must be an array but is of type string in document {_id: 1}");
// push with multiple fields
Document pushObj = json("$push: {field1: 'value', field2: 'value2'}");
collection.updateOne(idObj, pushObj);
expected = json("_id: 1, field: 'value', field1: ['value'], field2: ['value2']");
assertThat(collection.find(idObj).first()).isEqualTo(expected);
// push duplicate
pushObj = json("$push: {field1: 'value'}");
collection.updateOne(idObj, pushObj);
expected.put("field1", Arrays.asList("value", "value"));
assertThat(collection.find(idObj).first()).isEqualTo(expected);
}
@Test
public void testUpdatePushAll() throws Exception {
Document idObj = json("_id: 1");
collection.insertOne(idObj);
assertMongoWriteException(() -> collection.updateOne(idObj, json("$pushAll: {field: 'value'}")),
10153, "Modifier $pushAll allowed for arrays only");
collection.updateOne(idObj, json("$pushAll: {field: ['value', 'value2']}"));
assertThat(collection.find(idObj).first()).isEqualTo(json("_id: 1, field: ['value', 'value2']"));
}
@Test
public void testUpdateAddToSet() throws Exception {
Document idObj = json("_id: 1");
collection.insertOne(idObj);
collection.updateOne(idObj, json("$addToSet: {'field.subfield.subsubfield': 'value'}"));
assertThat(collection.find(idObj).first()).isEqualTo(json("_id: 1, field: {subfield: {subsubfield: ['value']}}"));
// addToSet to non-array
collection.updateOne(idObj, json("$set: {field: 'value'}"));
assertThatExceptionOfType(MongoWriteException.class)
.isThrownBy(() -> collection.updateOne(idObj, json("$addToSet: {field: 'value'}")))
.withMessageContaining("Cannot apply $addToSet to non-array field. Field named 'field' has non-array type string");
// addToSet with multiple fields
collection.updateOne(idObj, json("$addToSet: {field1: 'value', field2: 'value2'}"));
assertThat(collection.find(idObj).first())
.isEqualTo(json("_id: 1, field: 'value', field1: ['value'], field2: ['value2']"));
// addToSet duplicate
collection.updateOne(idObj, json("$addToSet: {field1: 'value'}"));
assertThat(collection.find(idObj).first())
.isEqualTo(json("_id: 1, field: 'value', field1: ['value'], field2: ['value2']"));
}
@Test
public void testUpdateAddToSetEach() throws Exception {
collection.insertOne(json("_id: 1"));
collection.updateOne(json("_id: 1"), addEachToSet("a", Arrays.asList(6, 5, 4)));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: [6, 5, 4]"));
collection.updateOne(json("_id: 1"), addEachToSet("a", Arrays.asList(3, 2, 1)));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: [6, 5, 4, 3, 2, 1]"));
collection.updateOne(json("_id: 1"), addEachToSet("a", Arrays.asList(7, 7, 9, 2)));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: [6, 5, 4, 3, 2, 1, 7, 9]"));
collection.updateOne(json("_id: 1"), addEachToSet("a", Arrays.asList(12, 13, 12)));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: [6, 5, 4, 3, 2, 1, 7, 9, 12, 13]"));
}
@Test
public void testUpdateDatasize() throws Exception {
Document obj = json("_id: 1, a: {x: [1, 2, 3]}");
collection.insertOne(obj);
Number oldSize = getCollStats().getInteger("size");
collection.updateOne(json("_id: 1"), set("a.x.0", 3));
assertThat(collection.find().first().get("a")).isEqualTo(json("x: [3, 2, 3]"));
Number newSize = getCollStats().getInteger("size");
assertThat(newSize).isEqualTo(oldSize);
// now increase the db
collection.updateOne(json("_id: 1"), set("a.x.0", "abc"));
Number yetNewSize = getCollStats().getInteger("size");
assertThat(yetNewSize.intValue() - oldSize.intValue()).isEqualTo(4);
}
@Test
public void testUpdatePull() throws Exception {
Document obj = json("_id: 1");
collection.insertOne(obj);
// pull from non-existing field
collection.updateOne(obj, json("$pull: {field1: 'value2', field2: 'value3'}"));
assertThat(collection.find(obj).first()).isEqualTo(obj);
// pull from non-array
collection.updateOne(obj, set("field", "value"));
assertMongoWriteException(() -> collection.updateOne(obj, pull("field", "value")),
2, "BadValue", "Cannot apply $pull to a non-array value");
// pull standard
collection.updateOne(obj, json("$set: {field: ['value1', 'value2', 'value1']}"));
collection.updateOne(obj, pull("field", "value1"));
assertThat(collection.find(obj).first().get("field")).isEqualTo(Collections.singletonList("value2"));
// pull with multiple fields
collection.updateOne(obj, json("$set: {field1: ['value1', 'value2', 'value1']}"));
collection.updateOne(obj, json("$set: {field2: ['value3', 'value3', 'value1']}"));
collection.updateOne(obj, json("$pull: {field1: 'value2', field2: 'value3'}"));
assertThat(collection.find(obj).first().get("field1")).isEqualTo(Arrays.asList("value1", "value1"));
assertThat(collection.find(obj).first().get("field2")).isEqualTo(Collections.singletonList("value1"));
}
@Test
public void testUpdatePullValueWithCondition() {
collection.insertOne(json("_id: 1, votes: [ 3, 5, 6, 7, 7, 8 ]"));
collection.updateOne(json("_id: 1"), json("$pull: {votes: {$gte: 6}}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, votes: [3, 5]"));
}
@Test
public void testUpdatePullDocuments() {
collection.insertOne(json("_id: 1, results: [{item: 'A', score: 5}, {item: 'B', score: 8, comment: 'foobar'}]"));
collection.insertOne(json("_id: 2, results: [{item: 'C', score: 8, comment: 'foobar'}, {item: 'B', score: 4}]"));
collection.updateOne(json(""), json("$pull: {results: {score: 8 , item: 'B'}}"));
assertThat(collection.find(json("_id: 1")).first()).isEqualTo(json("_id: 1, results: [{item: 'A', score: 5}]"));
assertThat(collection.find(json("_id: 2")).first()).isEqualTo(json("_id: 2, results: [{item: 'C', score: 8, comment: 'foobar'}, {item: 'B', score: 4}]"));
}
// https://github.com/bwaldvogel/mongo-java-server/issues/20
@Test
public void testUpdatePullLeavesEmptyArray() {
Document obj = json("_id: 1");
collection.insertOne(obj);
collection.updateOne(obj, json("$set: {field: [{'key1': 'value1', 'key2': 'value2'}]}"));
collection.updateOne(obj, json("$pull: {field: {'key1': 'value1'}}"));
assertThat(collection.find(obj).first()).isEqualTo(json("_id: 1, field: []"));
}
@Test
public void testUpdatePullAll() throws Exception {
Document obj = json("_id: 1");
collection.insertOne(obj);
collection.updateOne(obj, json("$set: {field: 'value'}"));
assertMongoWriteException(() -> collection.updateOne(obj, json("$pullAll: {field: 'value'}")),
2, "BadValue", "$pullAll requires an array argument but was given a string");
collection.updateOne(obj, json("$set: {field1: ['value1', 'value2', 'value1', 'value3', 'value4', 'value3']}"));
collection.updateOne(obj, json("$pullAll: {field1: ['value1', 'value3']}"));
assertThat(collection.find(obj).first().get("field1")).isEqualTo(Arrays.asList("value2", "value4"));
assertMongoWriteException(() -> collection.updateOne(obj, json("$pullAll: {field1: 'bar'}")),
2, "BadValue", "$pullAll requires an array argument but was given a string");
}
@Test
public void testUpdatePullAll_Documents() throws Exception {
collection.insertOne(json("_id: 1, persons: [{id: 1}, {id: 2}, {id: 5}, {id: 5}, {id: 1}, {id: 0}]"));
collection.updateOne(json("_id: 1"), json("$pullAll: {persons: [{id: 0.0}, {id: 5}]}"));
assertThat(collection.find(json("")))
.containsExactly(json("_id: 1, persons: [{id: 1}, {id: 2}, {id: 1}]"));
}
@Test
public void testUpdateSet() throws Exception {
Document object = json("_id: 1");
collection.insertOne(object);
assertThat(collection.find(object).first()).isEqualTo(object);
collection.updateOne(object, json("$set: {foo: 'bar'}"));
Document expected = json("");
expected.putAll(object);
expected.put("foo", "bar");
collection.updateOne(object, json("$set: {bar: 'bla'}"));
expected.put("bar", "bla");
assertThat(collection.find(object).first()).isEqualTo(expected);
assertMongoWriteException(() -> collection.updateOne(object, json("$set: {'foo.bar': 'bla'}")),
28, "PathNotViable", "Cannot create field 'bar' in element {foo: \"bar\"}");
assertThat(collection.find(object).first()).isEqualTo(expected);
collection.updateOne(object, json("$set: {'other.foo': '123'}"));
expected.putAll(json("other: {foo: '123'}"));
assertThat(collection.find(object).first()).isEqualTo(expected);
collection.updateOne(object, json("$set: {'other.foo': 42}"));
expected.putAll(json("other: {foo: 42}"));
assertThat(collection.find(object).first()).isEqualTo(expected);
collection.updateOne(object, json("$set: {'other.bar': 'x'}"));
expected.putAll(json("other: {foo: 42, bar: 'x'}"));
assertThat(collection.find(object).first()).isEqualTo(expected);
collection.updateOne(object, json("$set: {'other': null}"));
expected.putAll(json("other: null"));
assertThat(collection.find(object).first()).isEqualTo(expected);
}
@Test
public void testUpdateSet_arrayOfDocuments() throws Exception {
collection.insertOne(json("_id: 1, foo: [{bar: 1}, {bar: 2}]"));
assertMongoWriteException(() -> collection.updateOne(json("_id: 1"), json("$set: {'foo.bar': 3}")),
28, "PathNotViable", "Cannot create field 'bar' in element {foo: [ { bar: 1 }, { bar: 2 } ]}");
}
@Test
public void testUpdateSetOnInsert() throws Exception {
Document object = json("_id: 1");
collection.updateOne(object, json("$set: {b: 3}, $setOnInsert: {a: 3}"), new UpdateOptions().upsert(true));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, b: 3, a: 3"));
collection.updateOne(object, json("$set: {b: 4}, $setOnInsert: {a: 5}"), new UpdateOptions().upsert(true));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, b: 4, a: 3")); // 'a' is unchanged
}
@Test
public void testUpdateSetWithArrayIndices() throws Exception {
// SERVER-181
collection.insertOne(json("_id: 1, a: [{x: 0}]"));
collection.updateOne(json(""), json("$set: {'a.0.x': 3}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: [{x: 3}]"));
collection.updateOne(json(""), json("$set: {'a.1.z': 17}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: [{x: 3}, {z: 17}]"));
collection.updateOne(json(""), json("$set: {'a.0.y': 7}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: [{x: 3, y: 7}, {z: 17}]"));
collection.updateOne(json(""), json("$set: {'a.1': 'test'}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: [{x: 3, y: 7}, 'test']"));
}
@Test
public void testUpdateUnsetWithArrayIndices() throws Exception {
// SERVER-273
collection.insertOne(json("_id: 1, a: [{x: 0}]"));
collection.updateOne(json(""), json("$unset: {'a.0.x': 1}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: [{}]"));
collection.updateOne(json(""), json("$unset: {'a.0': 1}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: [null]"));
collection.updateOne(json(""), json("$unset: {'a.10': 1}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: [null]"));
}
@Test
public void testUpdateMax() throws Exception {
Document object = json("_id: 1");
collection.insertOne(object);
collection.updateOne(object, json("$max: {'foo.bar': 1}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : 1}"));
collection.updateOne(object, json("$max: {'foo.bar': 1}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : 1}"));
collection.updateOne(object, json("$max: {'foo.bar': 10}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : 10}"));
collection.updateOne(object, json("$max: {'foo.bar': -100}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : 10}"));
collection.updateOne(object, json("$max: {'foo.bar': '1'}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : '1'}"));
collection.updateOne(object, json("$max: {'foo.bar': null}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : '1'}"));
collection.updateOne(object, json("$max: {'foo.bar': '2', 'buz' : 1}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : '2'}, buz : 1"));
}
@Test
public void testUpdateMin() throws Exception {
Document object = json("_id: 1");
collection.insertOne(object);
collection.updateOne(object, json("$min: {'foo.bar': 'b'}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : 'b'}"));
collection.updateOne(object, json("$min: {'foo.bar': 'a'}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : 'a'}"));
collection.updateOne(object, json("$min: {'foo.bar': 10}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : 10}"));
collection.updateOne(object, json("$min: {'foo.bar': 10}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : 10}"));
collection.updateOne(object, json("$min: {'foo.bar': 1}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : 1}"));
collection.updateOne(object, json("$min: {'foo.bar': 100}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : 1}"));
collection.updateOne(object, json("$min: {'foo.bar': null}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : null}"));
collection.updateOne(object, json("$min: {'foo.bar': 'a'}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo : {bar : null}"));
}
@Test
public void testUpdateMinMaxWithLists() throws Exception {
collection.insertOne(json("_id: 1, a: [1, 2], b: [3, 4]"));
collection.insertOne(json("_id: 2"));
collection.insertOne(json("_id: 3, a: null, b: null"));
collection.insertOne(json("_id: 4, a: 'abc', b: 'xyz'"));
collection.insertOne(json("_id: 5, a: 1, b: 2"));
collection.updateMany(json(""), json("$min: {a: [2, 3], b: [1, 2]}"));
assertThat(collection.find(json("")))
.containsExactlyInAnyOrder(
json("_id: 1, a: [1, 2], b: [1, 2]"),
json("_id: 2, a: [2, 3], b: [1, 2]"),
json("_id: 3, a: null, b: null"),
json("_id: 4, a: 'abc', b: 'xyz'"),
json("_id: 5, a: 1, b: 2")
);
collection.updateMany(json(""), json("$max: {a: [1, 3], b: [2, 3]}"));
assertThat(collection.find(json("")))
.containsExactlyInAnyOrder(
json("_id: 1, a: [1, 3], b: [2, 3]"),
json("_id: 2, a: [2, 3], b: [2, 3]"),
json("_id: 3, a: [1, 3], b: [2, 3]"),
json("_id: 4, a: [1, 3], b: [2, 3]"),
json("_id: 5, a: [1, 3], b: [2, 3]")
);
}
// see http://docs.mongodb.org/manual/reference/operator/update/max
@Test
public void testUpdateMaxCompareNumbers() throws Exception {
Document object = json("_id: 1, highScore: 800, lowScore: 200");
collection.insertOne(object);
collection.updateOne(json("_id: 1"), json("$max: {highScore: 950}"));
assertThat(collection.find(json("_id: 1")).first()).isEqualTo(json("_id: 1, highScore: 950, lowScore: 200"));
collection.updateOne(json("_id: 1"), json("$max: {highScore: 870}"));
assertThat(collection.find(json("_id: 1")).first()).isEqualTo(json("_id: 1, highScore: 950, lowScore: 200"));
}
// see http://docs.mongodb.org/manual/reference/operator/update/max
@Test
public void testUpdateMaxCompareDates() throws Exception {
Document object = new Document("_id", 1).append("desc", "crafts")
.append("dateEntered", instant("2013-10-01T05:00:00Z"))
.append("dateExpired", instant("2013-10-01T16:38:16Z"));
collection.insertOne(object);
collection.updateOne(json("_id: 1"),
new Document("$max", new Document("dateExpired", instant("2013-09-30T00:00:00Z"))));
assertThat(collection.find(json("_id: 1")).first())
.isEqualTo(json("_id: 1, desc: 'crafts'")
.append("dateEntered", date("2013-10-01T05:00:00Z"))
.append("dateExpired", date("2013-10-01T16:38:16Z")));
collection.updateOne(json("_id: 1"),
new Document("$max", new Document("dateExpired", instant("2014-01-07T00:00:00Z"))));
assertThat(collection.find(json("_id: 1")).first()).isEqualTo(
json("_id: 1, desc: 'crafts'")
.append("dateEntered", date("2013-10-01T05:00:00Z"))
.append("dateExpired", date("2014-01-07T00:00:00Z")));
}
// see http://docs.mongodb.org/manual/reference/operator/update/min
@Test
public void testUpdateMinCompareNumbers() throws Exception {
Document object = json("_id: 1, highScore: 800, lowScore: 200");
collection.insertOne(object);
collection.updateOne(json("_id: 1"), json("$min: {lowScore: 150}"));
assertThat(collection.find(json("_id: 1")).first()).isEqualTo(json("_id: 1, highScore: 800, lowScore: 150"));
collection.updateOne(json("_id: 1"), json("$min: {lowScore: 250}"));
assertThat(collection.find(json("_id: 1")).first()).isEqualTo(json("_id: 1, highScore: 800, lowScore: 150"));
}
// see http://docs.mongodb.org/manual/reference/operator/update/min
@Test
public void testUpdateMinCompareDates() throws Exception {
Document object = new Document("_id", 1).append("desc", "crafts")
.append("dateEntered", instant("2013-10-01T05:00:00Z"))
.append("dateExpired", instant("2013-10-01T16:38:16Z"));
collection.insertOne(object);
collection.updateOne(json("_id: 1"),
new Document("$min", new Document("dateEntered", instant("2013-09-25T00:00:00Z"))));
assertThat(collection.find(json("_id: 1")).first()) //
.isEqualTo(json("_id: 1, desc: 'crafts'") //
.append("dateEntered", date("2013-09-25T00:00:00Z")) //
.append("dateExpired", date("2013-10-01T16:38:16Z")));
collection.updateOne(json("_id: 1"),
new Document("$min", new Document("dateEntered", instant("2014-01-07T00:00:00Z"))));
assertThat(collection.find(json("_id: 1")).first()) //
.isEqualTo(json("_id: 1, desc: 'crafts'") //
.append("dateEntered", date("2013-09-25T00:00:00Z")) //
.append("dateExpired", date("2013-10-01T16:38:16Z")));
}
@Test
public void testUpdatePop() throws Exception {
Document object = json("_id: 1");
collection.insertOne(object);
collection.updateOne(object, json("$pop: {'foo.bar': 1}"));
assertThat(collection.find(object).first()).isEqualTo(object);
collection.updateOne(object, json("$set: {'foo.bar': [1, 2, 3]}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo: {bar: [1, 2, 3]}"));
collection.updateOne(object, json("$pop: {'foo.bar': 1.0}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo: {bar: [1, 2]}"));
collection.updateOne(object, json("$pop: {'foo.bar': -1}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, foo: {bar: [2]}"));
assertMongoWriteException(() -> collection.updateOne(object, json("$pop: {'foo.bar': null}")),
9, "FailedToParse", "Expected a number in: foo.bar: null");
assertMongoWriteException(() -> collection.updateOne(object, json("$pop: {'foo.bar': 'x'}")),
9, "FailedToParse", "Expected a number in: foo.bar: \"x\"");
assertMongoWriteException(() -> collection.updateOne(object, json("$pop: {'foo.bar': 2}")),
9, "FailedToParse", "$pop expects 1 or -1, found: 2");
}
@Test
public void testUpdateUnset() throws Exception {
Document obj = json("_id: 1, a: 1, b: null, c: 'value'");
collection.insertOne(obj);
assertMongoWriteException(() -> collection.updateOne(obj, json("$unset: {_id: ''}")),
66, "ImmutableField", "Performing an update on the path '_id' would modify the immutable field '_id'");
collection.updateOne(json("_id: 1"), json("$unset: {'a.b.z':1}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: 1, b: null, c: 'value'"));
collection.updateOne(obj, json("$unset: {a:'', b:''}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, c: 'value'"));
collection.updateOne(obj, Updates.unset("c.y"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, c: 'value'"));
collection.replaceOne(json("_id: 1"), json("a: {b: 'foo', c: 'bar'}"));
collection.updateOne(json("_id: 1"), json("$unset: {'a.b':1}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: {c: 'bar'}"));
collection.updateOne(json("_id: 1"), json("$unset: {'a.b.z':1}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: {c: 'bar'}"));
}
@Test
public void testUpdateWithIdIn() {
collection.insertOne(json("_id: 1"));
Document update = json("$push: {n: {_id: 2, u: 3}}, $inc: {c: 4}");
Document expected = json("_id: 1, n: [{_id: 2, u: 3}], c: 4");
collection.updateOne(json("_id: {$in: [1]}"), update);
assertThat(collection.find().first()).isEqualTo(expected);
}
@Test
public void testUpdateMulti() throws Exception {
collection.insertOne(json("a: 1"));
collection.insertOne(json("a: 1"));
UpdateResult result = collection.updateOne(json("a: 1"), json("$set: {b: 2}"));
assertThat(result.getModifiedCount()).isEqualTo(1);
assertThat(collection.countDocuments(new Document("b", 2))).isEqualTo(1);
result = collection.updateMany(json("a: 1"), json("$set: {b: 3}"));
assertThat(result.getModifiedCount()).isEqualTo(2);
assertThat(collection.countDocuments(new Document("b", 2))).isEqualTo(0);
assertThat(collection.countDocuments(new Document("b", 3))).isEqualTo(2);
}
@Test
public void testUpdateIllegalInt() throws Exception {
collection.insertOne(json("_id: 1, a: {x: 1}"));
assertMongoWriteException(() -> collection.updateOne(json("_id: 1"), json("$inc: {a: 1}")),
14, "TypeMismatch", "Cannot apply $inc to a value of non-numeric type. {_id: 1} has the field 'a' of non-numeric type object");
assertThatExceptionOfType(MongoServerException.class)
.isThrownBy(() -> collection.updateOne(json("_id: 1"), json("$inc: {'a.x': 'b'}")))
.withMessage("Cannot increment with non-numeric argument: {a.x: \"b\"}");
}
@Test
public void testUpdateWithIdInMulti() {
collection.insertMany(Arrays.asList(json("_id: 1"), json("_id: 2")));
collection.updateMany(json("_id: {$in: [1, 2]}"), json("$set: {n: 1}"));
assertThat(collection.find())
.containsExactly(
json("_id: 1, n: 1"),
json("_id: 2, n: 1")
);
}
@Test
public void testUpdateWithIdInMultiReturnModifiedDocumentCount() {
collection.insertMany(Arrays.asList(json("_id: 1"), json("_id: 2")));
UpdateResult result = collection.updateMany(json("_id: {$in: [1, 2]}"), json("$set: {n: 1}"));
assertThat(result.getModifiedCount()).isEqualTo(2);
}
@Test
public void testUpdateWithIdQuery() {
collection.insertMany(Arrays.asList(json("_id: 1"), json("_id: 2")));
collection.updateMany(json("_id: {$gt:1}"), json("$set: {n: 1}"));
assertThat(collection.find())
.containsExactly(json("_id: 1"), json("_id: 2, n: 1"));
}
@Test
public void testUpdateWithObjectId() {
collection.insertOne(json("_id: {n: 1}"));
UpdateResult result = collection.updateOne(json("_id: {n: 1}"), json("$set: {a: 1}"));
assertThat(result.getModifiedCount()).isEqualTo(1);
assertThat(collection.find().first()).isEqualTo(json("_id: {n: 1}, a: 1"));
}
@Test
public void testUpdateArrayMatch() throws Exception {
collection.insertOne(json("_id: 1, a: [{x: 1, y: 1}, {x: 2, y: 2}, {x: 3, y: 3}]"));
collection.updateOne(json("'a.x': 2"), json("$inc: {'a.$.y': 1}"));
assertThat(collection.find(json("'a.x': 2")).first()).isEqualTo(json("_id: 1, a: [{x: 1, y: 1}, {x: 2, y: 3}, {x: 3, y: 3}]"));
collection.insertOne(json("'array': [{'123a': {'name': 'old'}}]"));
assertThat(collection.find(json("'array.123a.name': 'old'")).first()).isNotNull();
collection.updateOne(json("'array.123a.name': 'old'"), json("$set: {'array.$.123a.name': 'new'}"));
assertThat(collection.find(json("'array.123a.name': 'new'")).first()).isNotNull();
assertThat(collection.find(json("'array.123a.name': 'old'")).first()).isNull();
}
// https://github.com/bwaldvogel/mongo-java-server/issues/85
@Test
public void testUpdateArrayMatch_MultipleFields() throws Exception {
collection.insertOne(json("_id: 1, a: [{x: 1, y: 1}, {x: 2, y: 2}, {x: 3, y: 3}]"));
collection.updateOne(json("'a.x': 2"),
json("$inc: {'a.$.y': 1, 'a.$.x': 1}, $set: {'a.$.foo': 1, 'a.$.foo2': 1}"));
assertThat(collection.find(json("")))
.containsExactly(json("_id: 1, a: [{x: 1, y: 1}, {x: 3, y: 3, foo: 1, foo2: 1}, {x: 3, y: 3}]"));
}
// https://github.com/bwaldvogel/mongo-java-server/issues/32
@Test
public void testUpdateWithNotAndSizeOperator() throws Exception {
collection.insertOne(json("_id: 1, array: ['a', 'b']"));
collection.insertOne(json("_id: 2, array: ['b']"));
collection.insertOne(json("_id: 3, array: ['a']"));
collection.updateMany(json("array: {$not: {$size: 1}}"), json("$pull: {array: 'a'}"));
assertThat(collection.find())
.containsExactlyInAnyOrder(
json("_id: 1, array: ['b']"),
json("_id: 2, array: ['b']"),
json("_id: 3, array: ['a']")
);
}
@Test
public void testMultiUpdateArrayMatch() throws Exception {
collection.insertOne(json(""));
collection.insertOne(json("x: [1, 2, 3]"));
collection.insertOne(json("x: 99"));
collection.updateMany(json("x: 2"), json("$inc: {'x.$': 1}"));
assertThat(collection.find(json("x: 1")).first().get("x")).isEqualTo(Arrays.asList(1, 3, 3));
}
@Test
public void testUpsert() {
UpdateResult result = collection.updateMany(json("n:'jon'"), json("$inc: {a: 1}"), new UpdateOptions().upsert(true));
assertThat(result.getModifiedCount()).isEqualTo(0);
Document object = collection.find().first();
assertThat(result.getUpsertedId()).isEqualTo(new BsonObjectId(object.getObjectId("_id")));
object.remove("_id");
assertThat(object).isEqualTo(json("n: 'jon', a: 1"));
result = collection.updateOne(json("_id: 17, n: 'jon'"), json("$inc: {a: 1}"), new UpdateOptions().upsert(true));
assertThat(result.getUpsertedId()).isEqualTo(new BsonInt32(17));
assertThat(collection.find(json("_id: 17")).first()).isEqualTo(json("_id: 17, n: 'jon', a: 1"));
}
@Test
public void testUpsertFieldOrder() throws Exception {
collection.updateOne(json("'x.y': 2"), json("$inc: {a: 7}"), new UpdateOptions().upsert(true));
Document obj = collection.find().first();
obj.remove("_id");
// this actually differs from the official MongoDB implementation
assertThat(obj).isEqualTo(json("x: {y: 2}, a: 7"));
}
@Test
public void testUpsertWithoutId() {
UpdateResult result = collection.updateOne(eq("a", 1), set("a", 2), new UpdateOptions().upsert(true));
assertThat(result.getModifiedCount()).isEqualTo(0);
assertThat(result.getUpsertedId()).isNotNull();
assertThat(collection.find().first().get("_id")).isInstanceOf(ObjectId.class);
assertThat(collection.find().first().get("a")).isEqualTo(2);
}
@Test
public void testUpsertOnIdWithPush() {
Document update1 = json("$push: {c: {a: 1, b: 2}}");
Document update2 = json("$push: {c: {a: 3, b: 4}}");
collection.updateOne(json("_id: 1"), update1, new UpdateOptions().upsert(true));
collection.updateOne(json("_id: 1"), update2, new UpdateOptions().upsert(true));
Document expected = json("_id: 1, c: [{a: 1, b: 2}, {a: 3, b: 4}]");
assertThat(collection.find(json("'c.a':3, 'c.b':4")).first()).isEqualTo(expected);
}
@Test
public void testUpsertWithConditional() {
Document query = json("_id: 1, b: {$gt: 5}");
Document update = json("$inc: {a: 1}");
UpdateResult updateResult = collection.updateOne(query, update, new UpdateOptions().upsert(true));
assertThat(updateResult.getModifiedCount()).isZero();
assertThat(updateResult.getMatchedCount()).isZero();
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: 1"));
}
// https://github.com/bwaldvogel/mongo-java-server/issues/29
@Test
public void testUpsertWithoutChange() {
collection.insertOne(json("_id: 1, a: 2, b: 3"));
Document query = json("_id: 1");
Document update = json("$set: {a: 2}");
UpdateResult updateResult = collection.updateOne(query, update, new UpdateOptions().upsert(true));
assertThat(updateResult.getModifiedCount()).isZero();
assertThat(updateResult.getMatchedCount()).isOne();
assertThat(collection.find().first()).isEqualTo(json("_id: 1, a: 2, b: 3"));
}
@Test
public void testUpsertWithEmbeddedQuery() {
collection.updateOne(json("_id: 1, 'e.i': 1"), json("$set: {a: 1}"), new UpdateOptions().upsert(true));
assertThat(collection.find(json("_id: 1")).first()).isEqualTo(json("_id: 1, e: {i: 1}, a: 1"));
}
@Test
public void testUpsertWithIdIn() throws Exception {
Document query = json("_id: {$in: [1]}");
Document update = json("$push: {n: {_id: 2 ,u : 3}}, $inc: {c: 4}");
Document expected = json("_id: 1, n: [{_id: 2 ,u : 3}], c: 4");
UpdateResult updateResult = collection.updateOne(query, update, new UpdateOptions().upsert(true));
assertThat(updateResult.getModifiedCount()).isZero();
assertThat(updateResult.getMatchedCount()).isZero();
// the ID generation actually differs from official MongoDB which just
// create a random object id
Document actual = collection.find().first();
assertThat(actual).isEqualTo(expected);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/62
@Test
public void testUpsertWithId() throws Exception {
Document query = json("somekey: 'somevalue'");
Document update = json("$set: { _id: 'someid', somekey: 'some value' }");
UpdateResult updateResult = collection.updateOne(query, update, new UpdateOptions().upsert(true));
assertThat(updateResult.getModifiedCount()).isZero();
assertThat(updateResult.getMatchedCount()).isZero();
assertThat(updateResult.getUpsertedId()).isEqualTo(new BsonString("someid"));
assertThat(collection.find())
.containsExactly(json("_id: 'someid', somekey: 'some value' "));
}
// https://github.com/bwaldvogel/mongo-java-server/issues/62
@Test
public void testUpsertWithId_duplicateKey() throws Exception {
collection.insertOne(json("_id: 'someid', somekey: 'other value'"));
Document query = json("somekey: 'some value'");
Document update = json("$set: { _id: 'someid', somekey: 'some value' }");
assertMongoWriteException(() -> collection.updateOne(query, update, new UpdateOptions().upsert(true)),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: _id_ dup key: { : \"someid\" }");
}
// https://github.com/bwaldvogel/mongo-java-server/issues/93
@Test
public void testReplaceOneWithId() throws Exception {
collection.replaceOne(json("_id: 1"), json("_id: 1, value: 'abc'"), new ReplaceOptions().upsert(true));
assertThat(collection.find())
.containsExactly(json("_id: 1, value: 'abc'"));
collection.replaceOne(json("value: 'xyz'"), json("_id: 2, value: 'xyz'"), new ReplaceOptions().upsert(true));
assertThat(collection.find())
.containsExactly(
json("_id: 1, value: 'abc'"),
json("_id: 2, value: 'xyz'")
);
assertMongoWriteException(() -> collection.replaceOne(json("value: 'z'"), json("_id: 2, value: 'z'"), new ReplaceOptions().upsert(true)),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: _id_ dup key: { : 2 }");
}
@Test
public void testReplaceOneUpsertsWithGeneratedId() throws Exception {
collection.replaceOne(json("value: 'abc'"), json("value: 'abc'"), new ReplaceOptions().upsert(true));
assertThat(collection.find())
.extracting(document -> document.get("value"))
.containsExactly("abc");
assertThat(collection.find().first().get("_id"))
.isInstanceOf(ObjectId.class);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/41
@Test
public void testBulkUpsert() throws Exception {
List> models = Arrays.asList(
new ReplaceOneModel<>(Filters.eq("_id", 1), json("_id: 1, a: 1"), new ReplaceOptions().upsert(true)),
new ReplaceOneModel<>(Filters.eq("_id", 2), json("_id: 2, a: 1"), new ReplaceOptions().upsert(true))
);
BulkWriteResult result = collection.bulkWrite(models, new BulkWriteOptions().ordered(false));
assertThat(result.getUpserts())
.extracting(BulkWriteUpsert::getId)
.containsExactly(new BsonInt32(1), new BsonInt32(2));
assertThat(result.getUpserts())
.extracting(BulkWriteUpsert::getIndex)
.containsExactly(0, 1);
assertThat(collection.find())
.containsExactlyInAnyOrder(json("_id: 1, a: 1"), json("_id: 2, a: 1"));
models = Arrays.asList(
new ReplaceOneModel<>(Filters.eq("_id", 1), json("_id: 1, a: 2"), new ReplaceOptions().upsert(true)),
new ReplaceOneModel<>(Filters.eq("_id", 3), json("_id: 3, a: 2"), new ReplaceOptions().upsert(true)),
new ReplaceOneModel<>(Filters.eq("_id", 2), json("_id: 2, a: 2"), new ReplaceOptions().upsert(true))
);
result = collection.bulkWrite(models, new BulkWriteOptions().ordered(false));
assertThat(result.getUpserts())
.extracting(BulkWriteUpsert::getId)
.containsExactly(new BsonInt32(3));
assertThat(result.getUpserts())
.extracting(BulkWriteUpsert::getIndex)
.containsExactly(1);
assertThat(collection.find())
.containsExactlyInAnyOrder(
json("_id: 1, a: 2"),
json("_id: 2, a: 2"),
json("_id: 3, a: 2")
);
}
@Test
public void testUpdateWithMultiplyOperator() throws Exception {
Document object = json("_id: 1");
collection.insertOne(object);
collection.updateOne(object, json("$mul: {a: 2}, $set: {b: 2}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, a: 0, b: 2"));
collection.updateOne(object, json("$mul: {b: 2.5}, $inc: {a: 0.5}"));
assertThat(collection.find(object).first()).isEqualTo(json("_id: 1, a: 0.5, b: 5.0"));
}
@Test
public void testUpdateWithIllegalMultiplyFails() throws Exception {
Document object = json("_id: 1, foo: 'x', bar: 1");
collection.insertOne(object);
assertMongoWriteException(() -> collection.updateOne(object, json("$mul: {_id: 2}")),
66, "ImmutableField", "Performing an update on the path '_id' would modify the immutable field '_id'");
assertMongoWriteException(() -> collection.updateOne(object, json("$mul: {foo: 2}")),
14, "TypeMismatch", "Cannot apply $mul to a value of non-numeric type. {_id: 1} has the field 'foo' of non-numeric type string");
assertMongoWriteException(() -> collection.updateOne(object, json("$mul: {bar: 'x'}")),
14, "TypeMismatch", "Cannot multiply with non-numeric argument: {bar: \"x\"}");
}
@Test
public void testIsMaster() throws Exception {
Document isMaster = runCommand("isMaster");
assertThat(isMaster.getBoolean("ismaster")).isTrue();
assertThat(isMaster.getDate("localTime")).isInstanceOf(Date.class);
Integer maxBsonObjectSize = isMaster.getInteger("maxBsonObjectSize");
assertThat(maxBsonObjectSize).isEqualTo(16777216);
assertThat(isMaster.getInteger("maxMessageSizeBytes")).isGreaterThan(maxBsonObjectSize);
}
// https://github.com/foursquare/fongo/pull/26
// http://stackoverflow.com/questions/12403240/storing-null-vs-not-storing-the-key-at-all-in-mongodb
@Test
public void testFindWithNullOrNoFieldFilter() {
collection.insertOne(json("name: 'jon', group: 'group1'"));
collection.insertOne(json("name: 'leo', group: 'group1'"));
collection.insertOne(json("name: 'neil1', group: 'group2'"));
collection.insertOne(json("name: 'neil2', group: null"));
collection.insertOne(json("name: 'neil3'"));
// check {group: null} vs {group: {$exists: false}} filter
assertThat(collection.find(json("group: null")))
.as("should have two neils (neil2, neil3)")
.hasSize(2);
assertThat(collection.find(exists("group", false)))
.as("should have one neils (neil3)")
.hasSize(1);
// same check but for fields which do not exist in DB
assertThat(collection.find(json("other: null")))
.as("should return all documents")
.hasSize(5);
assertThat(collection.find(exists("other", false)))
.as("should return all documents")
.hasSize(5);
}
@Test
public void testInsertWithIllegalId() throws Exception {
assertMongoWriteException(() -> collection.insertOne(json("_id: [1, 2, 3]")),
2, "BadValue", "can't use an array for _id");
}
@Test
public void testInsertsWithUniqueIndex() {
collection.createIndex(new Document("uniqueKeyField", 1), new IndexOptions().unique(true));
collection.insertOne(json("uniqueKeyField: 'abc1', afield: 'avalue'"));
collection.insertOne(json("uniqueKeyField: 'abc2', afield: 'avalue'"));
collection.insertOne(json("uniqueKeyField: 'abc3', afield: 'avalue'"));
assertMongoWriteException(() -> collection.insertOne(json("uniqueKeyField: 'abc2', afield: 'avalue'")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: uniqueKeyField_1 dup key: { : \"abc2\" }");
collection.insertOne(json("uniqueKeyField: 1"));
collection.insertOne(json("uniqueKeyField: 1.1"));
assertMongoWriteException(() -> collection.insertOne(json("uniqueKeyField: 1.0")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: uniqueKeyField_1 dup key: { : 1.0 }");
}
@Test
public void testInsertBinaryData() throws Exception {
collection.insertOne(new Document("test", new byte[] { 0x01, 0x02, 0x03 }));
}
// see https://github.com/bwaldvogel/mongo-java-server/issues/9
@Test
public void testUniqueIndexWithSubdocument() {
collection.createIndex(json("'action.actionId': 1"), new IndexOptions().unique(true));
collection.insertOne(json("_id: 1, action: 'abc1'"));
collection.insertOne(json("_id: 2, action: {actionId: 1}"));
collection.insertOne(json("_id: 3, action: {actionId: 2}"));
collection.insertOne(json("_id: 4, action: {actionId: 3}"));
assertMongoWriteException(() -> collection.insertOne(json("action: {actionId: 1.0}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: action.actionId_1 dup key: { : 1.0 }");
assertThat(collection.find(json("action: 'abc1'")))
.containsExactly(json("_id: 1, action: 'abc1'"));
assertThat(collection.find(json("'action.actionId': 2")))
.containsExactly(json("_id: 3, action: {actionId: 2}"));
assertThat(collection.find(json("action: {actionId: 2}")))
.containsExactly(json("_id: 3, action: {actionId: 2}"));
assertThat(collection.find(json("'action.actionId.subKey': 23"))).isEmpty();
}
@Test
public void testUniqueIndexWithDeepDocuments() throws Exception {
collection.createIndex(json("a: 1"), new IndexOptions().unique(true));
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2, a: 1"));
collection.insertOne(json("_id: 3, a: {b: 0}"));
collection.insertOne(json("_id: 4, a: {b: {c: 1}}"));
collection.insertOne(json("_id: 5, a: {b: {c: 1, d: 1}}"));
collection.insertOne(json("_id: 6, a: {b: {d: 1, c: 1}}"));
collection.insertOne(json("_id: 7, a: {b: 1, c: 1}"));
collection.insertOne(json("_id: 8, a: {c: 1, d: 1}"));
collection.insertOne(json("_id: 9, a: {c: 1}"));
assertMongoWriteException(() -> collection.insertOne(json("a: {b: 0}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1 dup key: { : { b: 0 } }");
assertMongoWriteException(() -> collection.insertOne(json("a: {b: 0.00}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1 dup key: { : { b: 0.0 } }");
assertMongoWriteException(() -> collection.insertOne(json("a: {b: -0.0}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1 dup key: { : { b: -0.0 } }");
assertMongoWriteException(() -> collection.insertOne(json("a: {b: {c: 1.0}}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1 dup key: { : { b: { c: 1.0 } } }");
assertMongoWriteException(() -> collection.insertOne(json("a: {b: {c: 1, d: 1.0}}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1 dup key: { : { b: { c: 1, d: 1.0 } } }");
}
// see https://github.com/bwaldvogel/mongo-java-server/issues/39
@Test
public void testSecondaryUniqueIndexUpdate() throws Exception {
collection.createIndex(json("text: 1"), new IndexOptions().unique(true));
collection.insertOne(json("_id: 1, text: 'abc'"));
collection.insertOne(json("_id: 2, text: 'def'"));
collection.insertOne(json("_id: 3"));
assertMongoWriteException(() -> collection.insertOne(json("_id: 4")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: text_1 dup key: { : null }");
assertMongoWriteException(() -> collection.updateOne(json("_id: 1"), new Document("$set", json("text: 'def'"))),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: text_1 dup key: { : \"def\" }");
collection.updateOne(json("_id: 1"), new Document("$set", json("text: 'xyz'")));
collection.updateOne(json("_id: 2"), new Document("$set", json("text: 'abc'")));
assertMongoWriteException(() -> collection.updateOne(json("_id: 2"), new Document("$set", json("text: null"))),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: text_1 dup key: { : null }");
collection.deleteOne(json("text: 'xyz'"));
assertThat(collection.find())
.containsExactlyInAnyOrder(
json("_id: 2, text: 'abc'"),
json("_id: 3")
);
}
// see https://github.com/bwaldvogel/mongo-java-server/issues/39
@Test
public void testSecondarySparseUniqueIndex() throws Exception {
collection.createIndex(json("text: 1"), new IndexOptions().unique(true).sparse(true));
collection.insertOne(json("_id: 1, text: 'abc'"));
collection.insertOne(json("_id: 2, text: 'def'"));
collection.insertOne(json("_id: 3"));
collection.insertOne(json("_id: 4"));
collection.insertOne(json("_id: 5, text: null"));
assertMongoWriteException(() -> collection.insertOne(json("_id: 6, text: null")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: text_1 dup key: { : null }");
assertMongoWriteException(() -> collection.insertOne(json("_id: 7, text: 'abc'")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: text_1 dup key: { : \"abc\" }");
assertMongoWriteException(() -> collection.updateOne(json("_id: 2"), new Document("$set", json("text: null"))),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: text_1 dup key: { : null }");
collection.deleteOne(json("_id: 5"));
collection.updateOne(json("_id: 2"), new Document("$set", json("text: null")));
collection.updateOne(json("_id: 1"), new Document("$set", json("text: 'def'")));
collection.deleteMany(json("text: null"));
assertThat(collection.find()).containsExactly(json("_id: 1, text: 'def'"));
}
// see https://github.com/bwaldvogel/mongo-java-server/issues/39
@Test
public void testCompoundSparseUniqueIndex() throws Exception {
collection.createIndex(json("a: 1, b: 1"), new IndexOptions().unique(true).sparse(true));
collection.insertOne(json("_id: 1, a: 10, b: 20"));
collection.insertOne(json("_id: 2, a: 10"));
collection.insertOne(json("_id: 3, b: 20"));
collection.insertOne(json("_id: 4"));
collection.insertOne(json("_id: 5"));
collection.insertOne(json("_id: 6, a: null"));
assertMongoWriteException(() -> collection.insertOne(json("_id: 7, a: null")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1_b_1 dup key: { : null, : null }");
assertMongoWriteException(() -> collection.insertOne(json("_id: 7, b: null")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1_b_1 dup key: { : null, : null }");
collection.deleteMany(json("a: null, b: null"));
assertThat(collection.find())
.containsExactlyInAnyOrder(
json("_id: 1, a: 10, b: 20"),
json("_id: 2, a: 10"),
json("_id: 3, b: 20")
);
}
@Test
public void testCompoundSparseUniqueIndexOnEmbeddedDocuments() throws Exception {
collection.createIndex(json("'a.x': 1, 'b.x': 1"), new IndexOptions().unique(true).sparse(true));
collection.insertOne(json("_id: 1, a: 10, b: 20"));
collection.insertOne(json("_id: 2, a: 10"));
collection.insertOne(json("_id: 3, b: 20"));
collection.insertOne(json("_id: 4, a: {x: 1}"));
collection.insertOne(json("_id: 5, b: {x: 2}"));
collection.insertOne(json("_id: 6, a: {x: 1}, b: {x: 2}"));
collection.insertOne(json("_id: 7, a: {x: 2}, b: {x: 2}"));
collection.insertOne(json("_id: 8, a: {x: null}, b: {x: null}"));
collection.insertOne(json("_id: 9"));
assertMongoWriteException(() -> collection.insertOne(json("_id: 10, a: {x: 1.0}, b: {x: 2.0}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a.x_1_b.x_1 dup key: { : 1.0, : 2.0 }");
assertMongoWriteException(() -> collection.insertOne(json("_id: 11, a: {x: null}, b: {x: null}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a.x_1_b.x_1 dup key: { : null, : null }");
collection.deleteMany(json("a: {x: null}, b: {x: null}"));
collection.deleteMany(json("a: 10"));
collection.deleteMany(json("b: 20"));
assertThat(collection.find())
.containsExactlyInAnyOrder(
json("_id: 4, a: {x: 1}"),
json("_id: 5, b: {x: 2}"),
json("_id: 6, a: {x: 1}, b: {x: 2}"),
json("_id: 7, a: {x: 2}, b: {x: 2}"),
json("_id: 9")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/90
@Test
public void testUpdateWithSparseUniqueIndex() throws Exception {
collection.createIndex(json("a: 1"), new IndexOptions().unique(true).sparse(true));
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2"));
collection.updateOne(json("_id: 1"), json("$set: {a: 'x'}"));
collection.updateOne(json("_id: 2"), json("$set: {a: 'y'}"));
assertMongoWriteException(() -> collection.updateOne(json("_id: 1"), json("$set: {a: 'y'}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1 dup key: { : \"y\" }");
collection.updateOne(json("_id: 2"), json("$unset: {a: 1}"));
collection.updateOne(json("_id: 1"), json("$set: {a: 'y'}"));
}
@Test
public void testSparseUniqueIndexOnEmbeddedDocument() throws Exception {
collection.createIndex(json("'a.b.c': 1"), new IndexOptions().unique(true).sparse(true));
collection.insertOne(json("a: 1"));
collection.insertOne(json("a: 1"));
collection.insertOne(json("a: null"));
collection.insertOne(json("a: null"));
collection.insertOne(json("a: {b: 1}"));
collection.insertOne(json("a: {b: 1}"));
collection.insertOne(json("a: {b: null}"));
collection.insertOne(json("a: {b: null}"));
collection.insertOne(json("a: {b: {c: 1}}"));
collection.insertOne(json("a: {b: {c: 2}}"));
collection.insertOne(json("a: {b: {c: null}}"));
collection.insertOne(json("a: {b: {c: {d: 1}}}"));
collection.insertOne(json("a: {b: {c: {d: null}}}"));
assertMongoWriteException(() -> collection.insertOne(json("a: {b: {c: 1}}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a.b.c_1 dup key: { : 1 }");
assertMongoWriteException(() -> collection.insertOne(json("a: {b: {c: null}}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a.b.c_1 dup key: { : null }");
assertMongoWriteException(() -> collection.insertOne(json("a: {b: {c: 1, x: 100}}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a.b.c_1 dup key: { : 1 }");
assertMongoWriteException(() -> collection.insertOne(json("a: {b: {c: {d: 1}}}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a.b.c_1 dup key: { : { d: 1 } }");
assertMongoWriteException(() -> collection.insertOne(json("a: {b: {c: {d: null}}}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a.b.c_1 dup key: { : { d: null } }");
}
@Test
public void testAddNonUniqueIndexOnNonIdField() {
collection.insertOne(json("someField: 'abc'"));
assertThat(collection.listIndexes()).hasSize(1);
collection.createIndex(new Document("someField", 1), new IndexOptions().unique(false));
assertThat(collection.listIndexes()).hasSize(2);
collection.insertOne(json("someField: 'abc'"));
}
@Test
public void testAddSparseIndexOnNonIdField() {
collection.insertOne(json("someField: 'abc'"));
assertThat(collection.listIndexes()).hasSize(1);
collection.createIndex(new Document("someField", 1), new IndexOptions().sparse(true));
assertThat(collection.listIndexes()).hasSize(2);
collection.insertOne(json("someField: 'abc'"));
}
// https://github.com/bwaldvogel/mongo-java-server/issues/61
@Test
public void testDeleteAllDocumentsWithUniqueSparseIndex() {
collection.createIndex(new Document("someField.values", 1), new IndexOptions().unique(true).sparse(true));
collection.insertOne(json("_id: 1, someField: {values: ['abc']}"));
collection.insertOne(json("_id: 2, someField: {values: ['other']}"));
collection.insertOne(json("_id: 3"));
collection.insertOne(json("_id: 4, someField: ['abc']"));
collection.insertOne(json("_id: 5, someField: 'abc'"));
collection.insertOne(json("_id: 6, someField: null"));
collection.deleteMany(json(""));
assertThat(collection.countDocuments()).isZero();
}
@Test
public void testAddPartialIndexOnNonIdField() {
collection.insertOne(json("someField: 'abc'"));
assertThat(collection.listIndexes()).hasSize(1);
collection.createIndex(new Document("someField", 1), new IndexOptions()
.partialFilterExpression(json("someField: {$gt: 5}")));
assertThat(collection.listIndexes()).hasSize(2);
collection.insertOne(json("someField: 'abc'"));
}
@Test
public void testCompoundUniqueIndices() {
collection.createIndex(json("a: 1, b: 1"), new IndexOptions().unique(true));
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2, a: 'foo'"));
collection.insertOne(json("_id: 3, b: 'foo'"));
collection.insertOne(json("_id: 4, a: 'foo', b: 'foo'"));
collection.insertOne(json("_id: 5, a: 'foo', b: 'bar'"));
collection.insertOne(json("_id: 6, a: 'bar', b: 'foo'"));
collection.insertOne(json("_id: 7, a: {x: 1, y: 1}, b: 'foo'"));
collection.insertOne(json("_id: 8, a: {x: 1, y: 2}, b: 'foo'"));
assertMongoWriteException(() -> collection.insertOne(json("a: 'foo', b: 'foo'")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1_b_1 dup key: { : \"foo\", : \"foo\" }");
assertMongoWriteException(() -> collection.insertOne(json("b: 'foo'")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1_b_1 dup key: { : null, : \"foo\" }");
assertMongoWriteException(() -> collection.insertOne(json("a: {x: 1, y: 1}, b: 'foo'")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1_b_1 dup key: { : { x: 1, y: 1 }, : \"foo\" }");
assertThat(collection.find(json("a: 'bar'")))
.containsExactly(json("_id: 6, a: 'bar', b: 'foo'"));
assertThat(collection.find(json("b: 'foo', a: 'bar'")))
.containsExactly(json("_id: 6, a: 'bar', b: 'foo'"));
assertThat(collection.find(json("a: 'foo'")))
.containsExactlyInAnyOrder(
json("_id: 2, a: 'foo'"),
json("_id: 4, a: 'foo', b: 'foo'"),
json("_id: 5, a: 'foo', b: 'bar'")
);
}
@Test
public void testCompoundUniqueIndices_Subdocument() {
collection.createIndex(json("a: 1, 'b.c': 1"), new IndexOptions().unique(true));
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2, a: 'foo', b: 'foo'"));
collection.insertOne(json("_id: 3, a: 'bar', b: {c: 1}"));
collection.insertOne(json("_id: 4, a: 'bar', b: {c: 2}"));
assertMongoWriteException(() -> collection.insertOne(json("a: 'bar', b: {c: 1}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1_b.c_1 dup key: { : \"bar\", : 1 }");
}
// https://github.com/bwaldvogel/mongo-java-server/issues/80
@Test
public void testCompoundUniqueIndicesWithInQuery() {
collection.createIndex(json("a: 1, b: 1"), new IndexOptions().unique(true));
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2, a: 'foo'"));
collection.insertOne(json("_id: 3, b: 'foo'"));
collection.insertOne(json("_id: 4, a: 'foo', b: 'foo'"));
collection.insertOne(json("_id: 5, a: 'foo', b: 'bar'"));
assertThat(collection.find(json("a: 'foo', b: { $in: ['bar'] }")))
.hasSize(1);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/83
@Test
public void testAddUniqueIndexOnExistingDocuments() throws Exception {
collection.insertOne(json("_id: 1, value: 'a'"));
collection.insertOne(json("_id: 2, value: 'b'"));
collection.insertOne(json("_id: 3, value: 'c'"));
collection.createIndex(json("value: 1"), new IndexOptions().unique(true));
assertMongoWriteException(() -> collection.insertOne(json("value: 'c'")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: value_1 dup key: { : \"c\" }");
collection.insertOne(json("_id: 4, value: 'd'"));
}
@Test
public void testAddUniqueIndexOnExistingDocuments_violatingUniqueness() throws Exception {
collection.insertOne(json("_id: 1, value: 'a'"));
collection.insertOne(json("_id: 2, value: 'b'"));
collection.insertOne(json("_id: 3, value: 'c'"));
collection.insertOne(json("_id: 4, value: 'b'"));
assertThatExceptionOfType(DuplicateKeyException.class)
.isThrownBy(() -> collection.createIndex(json("value: 1"), new IndexOptions().unique(true)))
.withMessage("Write failed with error code 11000 and error message " +
"'E11000 duplicate key error collection: testdb.testcoll index: value_1 dup key: { : \"b\" }'");
assertThat(collection.listIndexes())
.containsExactly(json("name: '_id_', ns: 'testdb.testcoll', key: {_id: 1}, v: 2"));
collection.insertOne(json("_id: 5, value: 'a'"));
}
@Test
public void testCursorOptionNoTimeout() throws Exception {
try (MongoCursor cursor = collection.find().noCursorTimeout(true).iterator()) {
assertThat(cursor.hasNext()).isFalse();
}
}
@Test
public void testBulkInsert() throws Exception {
List> inserts = new ArrayList<>();
inserts.add(new InsertOneModel<>(json("_id: 1")));
inserts.add(new InsertOneModel<>(json("_id: 2")));
inserts.add(new InsertOneModel<>(json("_id: 3")));
BulkWriteResult result = collection.bulkWrite(inserts);
assertThat(result.getInsertedCount()).isEqualTo(3);
}
@Test
public void testBulkUpdateOrdered() throws Exception {
testBulkUpdate(true);
}
@Test
public void testBulkUpdateUnordered() throws Exception {
testBulkUpdate(false);
}
private void testBulkUpdate(boolean ordered) {
insertUpdateInBulk(ordered);
removeInBulk(ordered);
insertUpdateInBulkNoMatch(ordered);
}
@Test
public void testUpdateCurrentDateIllegalTypeSpecification() throws Exception {
Document object = json("_id: 1");
collection.insertOne(object);
assertMongoWriteException(() -> collection.updateOne(object, json("$currentDate: {lastModified: null}")),
2, "BadValue", "null is not valid type for $currentDate. Please use a boolean ('true') or a $type expression ({$type: 'timestamp/date'}).");
assertMongoWriteException(() -> collection.updateOne(object, json("$currentDate: {lastModified: 123.456}")),
2, "BadValue", "double is not valid type for $currentDate. Please use a boolean ('true') or a $type expression ({$type: 'timestamp/date'}).");
assertMongoWriteException(() -> collection.updateOne(object, json("$currentDate: {lastModified: 'foo'}")),
2, "BadValue", "string is not valid type for $currentDate. Please use a boolean ('true') or a $type expression ({$type: 'timestamp/date'}).");
assertMongoWriteException(() -> collection.updateOne(object, json("$currentDate: {lastModified: {$type: 'foo'}}")),
2, "BadValue", "The '$type' string field is required to be 'date' or 'timestamp': {$currentDate: {field : {$type: 'date'}}}");
assertThat(collection.find(object).first()).isEqualTo(object);
}
@Test
public void testUpdateCurrentDate() throws Exception {
Document object = json("_id: 1");
collection.insertOne(object);
collection.updateOne(object, json("$currentDate: {'x.lastModified': true}"));
assertThat(((Document) collection.find(object).first().get("x")).get("lastModified"))
.isInstanceOf(Date.class);
collection.updateOne(object, json("$currentDate: {'x.lastModified': {$type: 'date'}}"));
assertThat(((Document) collection.find(object).first().get("x")).get("lastModified"))
.isInstanceOf(Date.class);
collection.updateOne(object, json("$currentDate: {'x.lastModified': {$type: 'timestamp'}}"));
assertThat(((Document) collection.find(object).first().get("x")).get("lastModified"))
.isInstanceOf(BsonTimestamp.class);
}
@Test
public void testRenameField() throws Exception {
Document object = json("_id: 1, foo: 'x', bar: 'y'");
collection.insertOne(object);
collection.updateOne(json("_id: 1"), json("$rename: {foo: 'foo2', bar: 'bar2'}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, foo2: 'x', bar2: 'y'"));
collection.updateOne(json("_id: 1"), json("$rename: {'bar2': 'foo', foo2: 'bar'}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, bar: 'x', foo: 'y'"));
collection.updateOne(json("_id: 1"), json("$rename: {'bar': 'bar2', 'missing': 'foo'}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, bar2: 'x', foo: 'y'"));
}
@Test
public void testRenameField_embeddedDocument() {
Document object = json("_id: 1, foo: { a: 1, b: 2 }, bar: { c: 3, d: 4 }}");
collection.insertOne(object);
collection.updateOne(json("_id: 1"), json("$rename: {'foo.a': 'foo.z', 'bar.c': 'bar.x'}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, foo: { z: 1, b: 2 }, bar: { x: 3, d: 4 }}"));
collection.updateOne(json("_id: 1"), json("$rename: {'foo.z': 'foo.a', 'bar.a': 'bar.b'}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, foo: { a: 1, b: 2 }, bar: { x: 3, d: 4 }}"));
collection.updateOne(json("_id: 1"), json("$rename: {'missing.a': 'missing.b'}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, foo: { a: 1, b: 2 }, bar: { x: 3, d: 4 }}"));
collection.updateOne(json("_id: 1"), json("$rename: {'foo.a': 'a', 'bar.x': 'bar.c'}"));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, foo: { b: 2 }, bar: { c: 3, d: 4 }, a: 1}"));
assertThatExceptionOfType(MongoWriteException.class)
.isThrownBy(() -> collection.updateOne(json("_id: 1"), json("$rename: {'foo.b.c': 'foo.b.d'}")
));
}
@Test
public void testRenameFieldIllegalValue() throws Exception {
Document object = json("_id: 1, foo: 'x', bar: 'y'");
collection.insertOne(object);
assertMongoWriteException(() -> collection.updateOne(json("_id: 1"), json("$rename: {foo: 12345}")),
2, "BadValue", "The 'to' field for $rename must be a string: foo: 12345");
assertMongoWriteException(() -> collection.updateOne(json("_id: 1"), json("$rename: {'_id': 'id'}")),
66, "ImmutableField", "Performing an update on the path '_id' would modify the immutable field '_id'");
assertMongoWriteException(() -> collection.updateOne(json("_id: 1"), json("$rename: {foo: '_id'}")),
66, "ImmutableField", "Performing an update on the path '_id' would modify the immutable field '_id'");
assertMongoWriteException(() -> collection.updateOne(json("_id: 1"), json("$rename: {foo: 'bar', 'bar': 'bar2'}")),
40, "ConflictingUpdateOperators", "Updating the path 'bar' would create a conflict at 'bar'");
assertMongoWriteException(() -> collection.updateOne(json("_id: 1"), json("$rename: {bar: 'foo', bar2: 'foo'}")),
40, "ConflictingUpdateOperators", "Updating the path 'foo' would create a conflict at 'foo'");
}
@Test
public void testRenameCollection() throws Exception {
collection.insertOne(json("_id: 1, a: 10"));
collection.insertOne(json("_id: 2, a: 20"));
collection.insertOne(json("_id: 3, a: 30"));
collection.createIndex(new Document("a", 1), new IndexOptions().unique(true));
collection.renameCollection(new MongoNamespace(collection.getNamespace().getDatabaseName(), "other-collection-name"));
assertThat(db.listCollectionNames())
.containsExactly("other-collection-name");
MongoCollection otherCollection = getCollection("other-collection-name");
assertThat(otherCollection.countDocuments()).isEqualTo(3);
assertThat(otherCollection.listIndexes())
.containsExactlyInAnyOrder(
json("name: '_id_', ns: 'testdb.other-collection-name', key: {_id: 1}, v: 2"),
json("name: 'a_1', ns: 'testdb.other-collection-name', key: {a: 1}, unique: true, v: 2")
);
assertThat(collection.listIndexes()).isEmpty();
}
@Test
public void testRenameCollection_targetAlreadyExists() throws Exception {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2"));
collection.insertOne(json("_id: 3"));
MongoCollection otherCollection = db.getCollection("other-collection-name");
otherCollection.insertOne(json("_id: 1"));
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.renameCollection(new MongoNamespace(db.getName(), "other-collection-name")))
.withMessageContaining("Command failed with error 48 (NamespaceExists): 'target namespace exists'");
assertThat(db.listCollectionNames())
.containsExactlyInAnyOrder(getCollectionName(), "other-collection-name");
assertThat(collection.countDocuments()).isEqualTo(3);
assertThat(getCollection("other-collection-name").countDocuments()).isEqualTo(1);
}
@Test
public void testRenameCollection_dropTarget() throws Exception {
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2"));
collection.insertOne(json("_id: 3"));
MongoCollection otherCollection = db.getCollection("other-collection-name");
otherCollection.insertOne(json("_id: 1"));
collection.renameCollection(new MongoNamespace(db.getName(), "other-collection-name"),
new RenameCollectionOptions().dropTarget(true));
assertThat(db.listCollectionNames()).containsExactly("other-collection-name");
assertThat(getCollection("other-collection-name").countDocuments()).isEqualTo(3);
}
@Test
public void testListIndexes_empty() throws Exception {
assertThat(collection.listIndexes()).isEmpty();
}
@Test
public void testListIndexes() throws Exception {
collection.insertOne(json("_id: 1"));
MongoCollection other = db.getCollection("other");
other.insertOne(json("_id: 1"));
collection.createIndex(json("bla: 1"));
collection.createIndex(new Document("a", 1), new IndexOptions().unique(true));
collection.createIndex(new Document("a", 1).append("b", -1.0), new IndexOptions().unique(true));
assertThat(collection.listIndexes())
.containsExactlyInAnyOrder(
json("name: '_id_', ns: 'testdb.testcoll', key: {_id: 1}, v: 2"),
json("name: 'bla_1', ns: 'testdb.testcoll', key: {bla: 1}, v: 2"),
json("name: 'a_1', ns: 'testdb.testcoll', key: {a: 1}, unique: true, v: 2"),
json("name: 'a_1_b_-1', ns: 'testdb.testcoll', key: {a: 1, b: -1.0}, unique: true, v: 2")
);
assertThat(other.listIndexes())
.containsExactlyInAnyOrder(
json("name: '_id_', ns: 'testdb.other', key: {_id: 1}, v: 2")
);
}
@Test
public void testFieldSelection_deselectId() {
collection.insertOne(json("_id: 1, order:1, visits: 2"));
Document document = collection.find(json("")).projection(json("_id: 0")).first();
assertThat(document).isEqualTo(json("order:1, visits:2"));
}
@Test
public void testFieldSelection_deselectOneField() {
Document obj = json("_id: 1, order:1, visits: 2, eid: 12345");
collection.insertOne(obj);
Document document = collection.find(new Document()).projection(json("visits: 0")).first();
assertThat(document).isEqualTo(json("_id: 1, order:1, eid: 12345"));
}
@Test
public void testFieldSelection_deselectTwoFields() {
Document obj = json("_id: 1, order:1, visits: 2, eid: 12345");
collection.insertOne(obj);
Document document = collection.find(new Document()).projection(json("visits: 0, eid: 0")).first();
assertThat(document).isEqualTo(json("_id: 1, order:1"));
}
@Test
public void testFieldSelection_selectAndDeselectFields() {
Document obj = json("_id: 1, order:1, visits: 2, eid: 12345");
collection.insertOne(obj);
Document document = collection.find(new Document()).projection(json("visits: 0, eid: 1")).first();
assertThat(document).isEqualTo(json("_id: 1, eid: 12345"));
}
@Test
public void testPullWithInPattern() {
collection.insertOne(json("_id: 1, tags: ['aa', 'bb', 'ab', 'cc']"));
collection.updateOne(json("_id: 1"), pullByFilter(in("tags", Pattern.compile("a+"))));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, tags: ['bb', 'cc']"));
}
@Test
public void testPullWithInPatternAnchored() {
collection.insertOne(json("_id: 1, tags: ['aa', 'bb', 'ab', 'cc']"));
collection.updateOne(json("_id: 1"), pullByFilter(in("tags", Pattern.compile("^a+$"))));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, tags: ['bb', 'ab', 'cc']"));
}
@Test
public void testPullWithInNumbers() {
collection.insertOne(json("_id: 1, values: [1, 2, 2.5, 3.0, 4]"));
collection.updateOne(json("_id: 1"), pullByFilter(in("values", Arrays.asList(2.0, 3, 4L))));
assertThat(collection.find().first()).isEqualTo(json("_id: 1, values: [1, 2.5]"));
}
@Test
public void testDocumentWithHashMap() {
Map value = new HashMap<>();
value.put("foo", "bar");
collection.insertOne(new Document("_id", 1).append("map", value));
Bson document = collection.find().first();
assertThat(document).isEqualTo(json("_id: 1, map: {foo: 'bar'}"));
}
@Test
public void testFindAndOfOrs() throws Exception {
collection.insertOne(new Document("_id", 1).append("published", true).append("startDate", instant("2015-03-01T13:20:05Z")));
collection.insertOne(new Document("_id", 2).append("published", true).append("expiration", instant("2020-12-31T18:00:00Z")));
collection.insertOne(new Document("_id", 3).append("published", true));
collection.insertOne(new Document("_id", 4).append("published", false));
collection.insertOne(new Document("_id", 5).append("published", true).append("startDate", instant("2017-01-01T00:00:00Z")));
collection.insertOne(new Document("_id", 6).append("published", true).append("expiration", instant("2016-01-01T00:00:00Z")));
Instant instant = instant("2016-01-01T00:00:00Z");
Bson query = and(
ne("published", false),
or(exists("startDate", false), lt("startDate", instant)),
or(exists("expiration", false), gt("expiration", instant))
);
assertThat(collection.find(query).projection(json("_id: 1")))
.containsExactly(
json("_id: 1"),
json("_id: 2"),
json("_id: 3")
);
}
@Test
public void testInOperatorWithNullValue() {
collection.insertMany(Arrays.asList(
json("_id: 1, a: 1"),
json("_id: 2, a: 2"),
json("_id: 3, a: 3"),
json("_id: 4, a: 4"),
json("_id: 5"))
);
Bson inQueryWithNull = in("a", 2, null, 3);
assertThat(collection.find(inQueryWithNull).projection(json("_id: 1")))
.containsExactly(
json("_id: 2"),
json("_id: 3"),
json("_id: 5")
);
}
@Test
public void testQueryWithReference() throws Exception {
collection.insertOne(json("_id: 1"));
String collectionName = getCollectionName();
collection.insertOne(new Document("_id", 2).append("ref", new DBRef(collectionName, 1)));
collection.insertOne(new Document("_id", 3).append("ref", new DBRef(collectionName, 2)));
Document doc = collection.find(new Document("ref", new DBRef(collectionName, 1))).projection(json("_id: 1")).first();
assertThat(doc).isEqualTo(json("_id: 2"));
}
@Test
public void testQueryWithIllegalReference() throws Exception {
collection.insertOne(json("_id: 1"));
String collectionName = getCollectionName();
collection.insertOne(new Document("_id", 2).append("ref", new DBRef(collectionName, 1)));
collection.insertOne(new Document("_id", 3).append("ref", new DBRef(collectionName, 2)));
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("ref: {$ref: 'coll'}")).first())
.withMessageContaining("Query failed with error code 2 and error message 'unknown operator: $ref'");
}
@Test
public void testAndOrNorWithEmptyArray() throws Exception {
collection.insertOne(json(""));
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(and()).first())
.withMessageContaining("Query failed with error code 2 and error message '$and/$or/$nor must be a nonempty array'");
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(nor()).first())
.withMessageContaining("Query failed with error code 2 and error message '$and/$or/$nor must be a nonempty array'");
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(or()).first())
.withMessageContaining("Query failed with error code 2 and error message '$and/$or/$nor must be a nonempty array'");
}
@Test
public void testInsertLargeDocument() throws Exception {
insertAndFindLargeDocument(100, 1);
insertAndFindLargeDocument(1000, 2);
insertAndFindLargeDocument(10000, 3);
}
@Test
public void testInsertAndUpdateAsynchronously() throws Exception {
int numDocuments = 1000;
CountDownLatch latch = new CountDownLatch(numDocuments);
Queue errors = new LinkedBlockingQueue<>();
Semaphore concurrentOperationsOnTheFly = new Semaphore(50); // prevent MongoWaitQueueFullException
for (int i = 1; i <= numDocuments; i++) {
final Document document = new Document("_id", i);
for (int j = 0; j < 10; j++) {
document.append("key-" + i + "-" + j, "value-" + i + "-" + j);
}
concurrentOperationsOnTheFly.acquire();
asyncCollection.insertOne(document).subscribe(new Subscriber() {
@Override
public void onSubscribe(Subscription s) {
s.request(Integer.MAX_VALUE);
}
@Override
public void onNext(Success success) {
log.info("inserted {}", document);
Document query = new Document("_id", document.getInteger("_id"));
asyncCollection.updateOne(query, Updates.set("updated", true)).subscribe(new Subscriber() {
@Override
public void onSubscribe(Subscription s) {
s.request(Integer.MAX_VALUE);
}
@Override
public void onNext(UpdateResult updateResult) {
log.info("updated {}: {}", query, updateResult);
}
@Override
public void onError(Throwable t) {
handleError("update", t);
}
@Override
public void onComplete() {
release();
}
});
}
@Override
public void onError(Throwable t) {
handleError("insert", t);
}
@Override
public void onComplete() {
log.info("insert completed");
}
private void handleError(String operation, Throwable t) {
log.error(operation + " of {} failed", document, t);
RuntimeException exception = new RuntimeException("Failed to " + operation + " " + document, t);
errors.add(exception);
release();
throw exception;
}
private void release() {
latch.countDown();
concurrentOperationsOnTheFly.release();
}
});
}
boolean success = latch.await(30, TimeUnit.SECONDS);
assertThat(success).isTrue();
if (!errors.isEmpty()) {
throw errors.poll();
}
log.info("finished");
for (int i = 1; i <= numDocuments; i++) {
Document query = new Document("_id", i);
Document document = collection.find(query).first();
assertThat(document).describedAs(query.toJson()).isNotNull();
assertThat(document.getBoolean("updated")).describedAs(document.toJson()).isTrue();
}
long count = collection.countDocuments();
assertThat(count).isEqualTo(numDocuments);
}
@Test
public void testAllQuery() throws Exception {
// see https://docs.mongodb.com/manual/reference/operator/query/all/
collection.insertOne(new Document("_id", new ObjectId("5234cc89687ea597eabee675"))
.append("code", "xyz")
.append("tags", Arrays.asList("school", "book", "bag", "headphone", "appliance"))
.append("qty", Arrays.asList(
new Document().append("size", "S").append("num", 10).append("color", "blue"),
new Document().append("size", "M").append("num", 45).append("color", "blue"),
new Document().append("size", "L").append("num", 100).append("color", "green")
)));
collection.insertOne(new Document("_id", new ObjectId("5234cc8a687ea597eabee676"))
.append("code", "abc")
.append("tags", Arrays.asList("appliance", "school", "book"))
.append("qty", Arrays.asList(
new Document().append("size", "6").append("num", 100).append("color", "green"),
new Document().append("size", "6").append("num", 50).append("color", "blue"),
new Document().append("size", "8").append("num", 100).append("color", "brown")
)));
collection.insertOne(new Document("_id", new ObjectId("5234ccb7687ea597eabee677"))
.append("code", "efg")
.append("tags", Arrays.asList("school", "book"))
.append("qty", Arrays.asList(
new Document().append("size", "S").append("num", 10).append("color", "blue"),
new Document().append("size", "M").append("num", 100).append("color", "blue"),
new Document().append("size", "L").append("num", 100).append("color", "green")
)));
collection.insertOne(new Document("_id", new ObjectId("52350353b2eff1353b349de9"))
.append("code", "ijk")
.append("tags", Arrays.asList("electronics", "school"))
.append("qty", Collections.singletonList(
new Document().append("size", "M").append("num", 100).append("color", "green")
)));
assertThat(collection.find(json("tags: {$all: ['appliance', 'school', 'book']}")))
.extracting(d -> d.get("_id"))
.containsExactly(new ObjectId("5234cc89687ea597eabee675"), new ObjectId("5234cc8a687ea597eabee676"));
}
@Test
public void testMatchesElementQuery() throws Exception {
collection.insertOne(json("_id: 1, results: [82, 85, 88]"));
collection.insertOne(json("_id: 2, results: [75, 88, 89]"));
assertThat(collection.find(json("results: {$elemMatch: {$gte: 80, $lt: 85}}")))
.containsExactly(json("_id: 1, results: [82, 85, 88]"));
}
@Test
public void testMatchesElementInEmbeddedDocuments() throws Exception {
collection.insertOne(json("_id: 1, results: [{product: 'abc', score: 10}, {product: 'xyz', score: 5}]"));
collection.insertOne(json("_id: 2, results: [{product: 'abc', score: 9}, {product: 'xyz', score: 7}]"));
collection.insertOne(json("_id: 3, results: [{product: 'abc', score: 7}, {product: 'xyz', score: 8}]"));
assertThat(collection.find(json("results: {$elemMatch: {product: 'xyz', score: {$gte: 8}}}")))
.containsExactlyInAnyOrder(
json("_id: 3, results: [{product: 'abc', score: 7}, {product: 'xyz', score: 8}]")
);
assertThat(collection.find(json("results: {$elemMatch: {product: 'xyz'}}}")))
.containsExactlyInAnyOrder(
json("_id: 1, results: [{product: 'abc', score: 10}, {product: 'xyz', score: 5}]"),
json("_id: 2, results: [{product: 'abc', score: 9}, {product: 'xyz', score: 7}]"),
json("_id: 3, results: [{product: 'abc', score: 7}, {product: 'xyz', score: 8}]")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/42
@Test
public void testElemMatchWithExpression() throws Exception {
collection.insertOne(json("_id: 1, languages: [{key: 'C'}, {key: 'Java'}]"));
collection.insertOne(json("_id: 2, languages: [{key: 'Python'}]"));
collection.insertOne(json("_id: 3, languages: [{key: 'C++'}, {key: 'C'}]"));
assertThat(collection.find(json("languages: {$elemMatch: {$or: [{key: 'C'}, {key: 'C++'}]}}")))
.containsExactly(
json("_id: 1, languages: [{key: 'C'}, {key: 'Java'}]"),
json("_id: 3, languages: [{key: 'C++'}, {key: 'C'}]")
);
assertThat(collection.find(json("languages: {$elemMatch: {$and: [{key: 'Java'}, {key: {$ne: 'Python'}}]}}")))
.containsExactly(
json("_id: 1, languages: [{key: 'C'}, {key: 'Java'}]")
);
assertThat(collection.find(json("languages: {$elemMatch: {$nor: [{key: 'C'}, {key: 'C++'}, {key: 'Java'}]}}")))
.containsExactly(
json("_id: 2, languages: [{key: 'Python'}]")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/97
@Test
public void testElemMatchAndAllQuery() throws Exception {
collection.insertOne(json("_id: 1, list: [{aa: 'bb'}, {cc: 'dd'}]"));
collection.insertOne(json("_id: 2, list: [{aa: 'bb'}, {cc: 'ee'}]"));
collection.insertOne(json("_id: 3, list: [{cc: 'dd'}]"));
collection.insertOne(json("_id: 4"));
collection.insertOne(json("_id: 5, list: []"));
collection.insertOne(json("_id: 6, list: [{aa: 'bb'}, {cc: 'dd'}, {ee: 'ff'}]"));
collection.insertOne(json("_id: 7, list: {aa: 'bb'}"));
assertThat(collection.find(json("list: {$all: [{$elemMatch: {aa: 'bb'}}, {$elemMatch: {cc: 'dd'}}], $size: 2}")))
.containsExactly(json("_id: 1, list: [{aa: 'bb'}, {cc: 'dd'}]"));
assertThat(collection.find(json("list: {$size: 2, $all: [{$elemMatch: {aa: 'bb'}}, {$elemMatch: {cc: 'dd'}}]}")))
.containsExactly(json("_id: 1, list: [{aa: 'bb'}, {cc: 'dd'}]"));
assertThat(collection.find(json("list: {$all: [{$elemMatch: {aa: 'bb'}}], $size: 2}")))
.containsExactly(
json("_id: 1, list: [{aa: 'bb'}, {cc: 'dd'}]"),
json("_id: 2, list: [{aa: 'bb'}, {cc: 'ee'}]")
);
assertThat(collection.find(json("list: {$all: [{$elemMatch: {$and: [{aa: {$ne: 'bb'}}, {cc: {$ne: 'dd'}}]}}]}")))
.containsExactly(
json("_id: 2, list: [{aa: 'bb'}, {cc: 'ee'}]"),
json("_id: 6, list: [{aa: 'bb'}, {cc: 'dd'}, {ee: 'ff'}]")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/51
@Test
public void testQueryWithElemMatch() {
collection.insertOne(json("_id: 1, materials: [{materialId: 'A'}, {materialId: 'B'}, {materialId: 'C'}]"));
collection.insertOne(json("_id: 2, materials: [{materialId: 'B'}]"));
collection.insertOne(json("_id: 3, materials: []"));
collection.insertOne(json("_id: 4"));
collection.insertOne(json("_id: 5, materials: 'ABC'"));
collection.insertOne(json("_id: 6, materials: {materialId: 'A'}"));
assertThat(collection.find(json("materials: {$elemMatch: {materialId: 'A'}}")))
.containsExactly(json("_id: 1, materials: [{materialId: 'A'}, {materialId: 'B'}, {materialId: 'C'}]"));
}
@Test
public void testProjectionWithElemMatch() {
collection.insertOne(json("_id: 1, zipcode: 63109, students: [{name: 'john'}, {name: 'jess'}, {name: 'jeff'}]"));
collection.insertOne(json("_id: 2, zipcode: 63110, students: [{name: 'ajax'}, {name: 'achilles'}]"));
collection.insertOne(json("_id: 3, zipcode: 63109, students: [{name: 'ajax'}, {name: 'achilles'}]"));
collection.insertOne(json("_id: 4, zipcode: 63109, students: [{name: 'barney'}]"));
collection.insertOne(json("_id: 5, zipcode: 63109, students: [1, 2, 3]"));
collection.insertOne(json("_id: 6, zipcode: 63109, students: {name: 'achilles'}"));
Document query = json("zipcode: 63109");
Document projection = json("students: {$elemMatch: {name: 'achilles'}}");
assertThat(collection.find(query).projection(projection))
.containsExactlyInAnyOrder(
json("_id: 1"),
json("_id: 3, students: [{name: 'achilles'}]"),
json("_id: 4"),
json("_id: 5"),
json("_id: 6")
);
}
@Test
public void testProjectionWithElemMatch_BigSubdocument() {
collection.insertOne(json("_id: 1, zipcode: 63109," +
" students: [" +
" {name: 'john', school: 102, age: 10}," +
" {name: 'jess', school: 102, age: 11}," +
" {name: 'jeff', school: 108, age: 15}" +
" ]"));
collection.insertOne(json("_id: 2, zipcode: 63110," +
" students: [" +
" {name: 'ajax', school: 100, age: 7}," +
" {name: 'achilles', school: 100, age: 8 }" +
" ]"));
collection.insertOne(json("_id: 3, zipcode: 63109," +
" students: [" +
" {name: 'ajax', school: 100, age: 7}," +
" {name: 'achilles', school: 100, age: 8}" +
" ]"));
collection.insertOne(json("_id: 4, zipcode: 63109," +
" students: [" +
" {name: 'barney', school: 102, age: 7}" +
" ]"));
assertThat(collection.find(json("zipcode: 63109")).projection(json("students: {$elemMatch: {school: 102}}}")))
.containsExactlyInAnyOrder(
json("_id: 1, students: [{name: 'john', school: 102, age: 10}]"),
json("_id: 3"),
json("_id: 4, students: [{name: 'barney', school: 102, age: 7}]")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/104
@Test
public void testQueryWithProjection_elemMatchAndPositionalOperator() throws Exception {
collection.insertOne(json("_id: 1, states: [{state: 'A', key: 'abc'}, {state: 'B', key: 'efg'}]"));
collection.insertOne(json("_id: 2, states: [{state: 'B', key: 'abc'}, {state: 'B', key: 'efg'}]"));
assertThat(collection.find(json("states: {$elemMatch: {state: {$eq: 'A'}, key: {$eq: 'abc'}}}")).
projection(json("'states.$': 1")))
.containsExactly(json("_id: 1, states: [{state: 'A', key: 'abc'}]"));
}
@Test
public void testProjectionWithSlice() throws Exception {
collection.insertOne(json("_id: 1, values: ['a', 'b', 'c', 'd', 'e']"));
collection.insertOne(json("_id: 2, values: 'xyz'"));
assertThat(collection.find(json("_id: 1")).projection(json("values: {$slice: 1}")))
.containsExactly(json("_id: 1, values: ['a']"));
assertThat(collection.find(json("_id: 1")).projection(json("values: {$slice: ['xyz', 2]}")))
.containsExactly(json("_id: 1, values: ['a', 'b']"));
assertThat(collection.find(json("_id: 1")).projection(json("values: {$slice: [-3, 2]}")))
.containsExactly(json("_id: 1, values: ['c', 'd']"));
assertThat(collection.find(json("_id: 2")).projection(json("values: {$slice: 1}")))
.containsExactly(json("_id: 2, values: 'xyz'"));
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("_id: 1")).projection(json("values: {$slice: ['$_id', '$_id']}")).first())
.withMessageContaining("Query failed with error code 2 and error message '$slice limit must be positive'");
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("_id: 1")).projection(json("values: {$slice: [1, 0]}")).first())
.withMessageContaining("Query failed with error code 2 and error message '$slice limit must be positive'");
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("_id: 1")).projection(json("values: {$slice: [1, 'xyz']}")).first())
.withMessageContaining("Query failed with error code 2 and error message '$slice limit must be positive'");
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("_id: 1")).projection(json("values: {$slice: [1, 2, 3]}")).first())
.withMessageContaining("Query failed with error code 2 and error message '$slice array wrong size'");
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("_id: 1")).projection(json("values: {$slice: 'abc'}")).first())
.withMessageContaining("Query failed with error code 2 and error message '$slice only supports numbers and [skip, limit] arrays'");
}
@Test
public void testMatchesNullOrMissing() throws Exception {
collection.insertOne(json("_id: 1, x: null"));
collection.insertOne(json("_id: 2"));
collection.insertOne(json("_id: 3, x: 123"));
assertThat(collection.find(json("x: null")))
.containsExactlyInAnyOrder(
json("_id: 1, x: null"),
json("_id: 2")
);
}
@Test
public void testIllegalElementMatchQuery() throws Exception {
collection.insertOne(json("_id: 1, results: [ 82, 85, 88 ]"));
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("results: {$elemMatch: [ 85 ]}")).first())
.withMessageContaining("Query failed with error code 2 and error message '$elemMatch needs an Object'");
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("results: {$elemMatch: 1}")).first())
.withMessageContaining("Query failed with error code 2 and error message '$elemMatch needs an Object'");
}
@Test
public void testQueryWithOperatorAndWithoutOperator() throws Exception {
collection.insertOne(json("_id: 1, x: {y: 23}"));
collection.insertOne(json("_id: 2, x: 9"));
collection.insertOne(json("_id: 3, x: 100"));
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("x: {$lt: 10, y: 23}")).first())
.withMessageContaining("Query failed with error code 2 and error message 'unknown operator: y'");
assertThat(collection.find(json("x: {y: 23, $lt: 10}"))).isEmpty();
assertThat(collection.find(json("x: {y: {$lt: 100, z: 23}}"))).isEmpty();
assertThat(collection.find(json("a: 123, x: {y: {$lt: 100, z: 23}}"))).isEmpty();
}
@Test
public void testQueryWithComment() throws Exception {
collection.insertOne(json("_id: 1, x: 2"));
collection.insertOne(json("_id: 2, x: 3"));
collection.insertOne(json("_id: 3, x: 4"));
assertThat(collection.find(json("x: {$mod: [2, 0 ]}, $comment: 'Find even values.'")))
.extracting(d -> d.get("_id"))
.containsExactly(1, 3);
}
@Test
public void testValidate() throws Exception {
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> db.runCommand(new Document("validate", getCollectionName())))
.withMessageContaining("Command failed with error 26 (NamespaceNotFound): 'ns not found'");
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2"));
collection.insertOne(json("_id: 3"));
collection.deleteOne(json("_id: 2"));
Document result = db.runCommand(new Document("validate", getCollectionName()));
assertThat(result.get("nrecords")).isEqualTo(2);
}
@Test
public void testGetLastError() throws Exception {
collection.insertOne(json("_id: 1"));
Document actual = db.runCommand(json("getlasterror: 1"));
assertThat(actual.get("n")).isEqualTo(0);
assertThat(actual).containsKey("err");
assertThat(actual.get("err")).isNull();
assertThat(actual.get("ok")).isEqualTo(1.0);
assertThatExceptionOfType(MongoWriteException.class)
.isThrownBy(() -> collection.insertOne(json("_id: 1.0")))
.withMessageContaining("E11000 duplicate key error collection: testdb.testcoll index: _id_ dup key: { : 1.0 }");
Document lastError = db.runCommand(json("getlasterror: 1"));
assertThat(lastError.get("code")).isEqualTo(11000);
assertThat(lastError.getString("err")).contains("duplicate key");
assertThat(lastError.getString("codeName")).isEqualTo("DuplicateKey");
assertThat(lastError.get("ok")).isEqualTo(1.0);
}
@Test
public void testGetPrevError() throws Exception {
restart();
collection.insertOne(json("_id: 1"));
assertThat(db.runCommand(json("getpreverror: 1")))
.isEqualTo(json("n: 0, nPrev: -1, err: null, ok: 1.0"));
assertMongoWriteException(() -> collection.insertOne(json("_id: 1.0")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: _id_ dup key: { : 1.0 }");
Document lastError = db.runCommand(json("getpreverror: 1"));
assertThat(lastError.get("code")).isEqualTo(11000);
assertThat(lastError.getString("err")).contains("duplicate key");
assertThat(lastError.getDouble("ok")).isEqualTo(1.0);
}
@Test
public void testResetError() throws Exception {
collection.insertOne(json("_id: 1"));
assertThatExceptionOfType(MongoWriteException.class)
.isThrownBy(() -> collection.insertOne(json("_id: 1.0")))
.withMessageContaining("duplicate key error collection: testdb.testcoll index: _id_ dup key: { : 1.0 }");
assertThat(db.runCommand(json("reseterror: 1")))
.isEqualTo(json("ok: 1.0"));
assertThat(db.runCommand(json("getpreverror: 1")))
.isEqualTo(json("nPrev: -1, err: null, n: 0, ok: 1.0"));
assertThat(db.runCommand(json("getlasterror: 1")))
.containsAllEntriesOf(json("err: null, n: 0, ok: 1.0"));
}
@Test
public void testIllegalTopLevelOperator() throws Exception {
Document query = json("$illegalOperator: 1");
collection.insertOne(json("_id: 1"));
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(query).first())
.withMessageContaining("Query failed with error code 2 and error message 'unknown top level operator: $illegalOperator'");
}
@Test
public void testExprQuery() throws Exception {
Document query = json("$expr: {$gt: ['$spent', '$budget']}");
assertThat(collection.find(query)).isEmpty();
collection.insertOne(json("_id: 1, category: 'food', budget: 400, spent: 450"));
collection.insertOne(json("_id: 2, category: 'drinks', budget: 100, spent: 150"));
collection.insertOne(json("_id: 3, category: 'clothes', budget: 100, spent: 50"));
collection.insertOne(json("_id: 4, category: 'misc', budget: 500, spent: 300"));
collection.insertOne(json("_id: 5, category: 'travel', budget: 200, spent: 650"));
assertThat(collection.find(query))
.containsExactly(
json("_id: 1, category: 'food', budget: 400, spent: 450"),
json("_id: 2, category: 'drinks', budget: 100, spent: 150"),
json("_id: 5, category: 'travel', budget: 200, spent: 650")
);
assertThat(collection.find(json("_id: {$gt: 3}"))).hasSize(2);
assertThat(collection.find(json("_id: {$gt: {$expr: {$literal: 3}}}"))).isEmpty();
assertThat(collection.find(json("$expr: {$eq: ['$budget', {$multiply: ['$spent', 2]}]}")))
.containsExactly(json("_id: 3, category: 'clothes', budget: 100, spent: 50"));
}
@Test
public void testExprQuery_IllegalFieldPath() throws Exception {
collection.insertOne(json("_id: 1"));
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("$expr: {$eq: ['$a.', 10]}")).first())
.withMessageContaining("Query failed with error code 40353 and error message 'FieldPath must not end with a '.'.'");
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("$expr: {$eq: ['$.a', 10]}")).first())
.withMessageContaining("Query failed with error code 15998 and error message 'FieldPath field names may not be empty strings.'");
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(json("$expr: {$eq: ['$a..1', 10]}")).first())
.withMessageContaining("Query failed with error code 15998 and error message 'FieldPath field names may not be empty strings.'");
}
@Test
public void testQueryEmbeddedDocument() throws Exception {
collection.insertOne(json("_id: 1, b: null"));
collection.insertOne(json("_id: 2, b: {c: null}"));
collection.insertOne(json("_id: 3, b: {c: 123}"));
collection.insertOne(json("_id: 4, b: {c: ['a', null, 'b']}"));
collection.insertOne(json("_id: 5, b: {c: [1, 2, 3]}"));
collection.insertOne(json("_id: 6"));
collection.insertOne(json("_id: 7, b: {c: 1, d: 2}"));
collection.insertOne(json("_id: 8, b: {c: {d: 1, e: 2}}"));
assertThat(collection.find(json("'b.c': 1")))
.containsExactlyInAnyOrder(
json("_id: 5, b: {c: [1, 2, 3]}"),
json("_id: 7, b: {c: 1, d: 2}")
);
assertThat(collection.find(json("b: {c: 1}"))).isEmpty();
assertThat(collection.find(json("'b.c': null")))
.containsExactlyInAnyOrder(
json("_id: 1, b: null"),
json("_id: 2, b: {c: null}"),
json("_id: 4, b: {c: ['a', null, 'b']}"),
json("_id: 6")
);
assertThat(collection.find(json("b: {c: null}")))
.containsExactly(json("_id: 2, b: {c: null}"));
assertThat(collection.find(json("'b.c': {d: 1}"))).isEmpty();
assertThat(collection.find(json("'b.c': {d: {$gte: 1}}"))).isEmpty();
assertThat(collection.find(json("'b.c': {d: {$gte: 1}, e: {$lte: 2}}"))).isEmpty();
assertThat(collection.find(json("'b.c.d': {$gte: 1}")))
.containsExactlyInAnyOrder(json("_id: 8, b: {c: {d: 1, e: 2}}"));
assertThat(collection.find(json("'b.c': {d: 1, e: 2}")))
.containsExactlyInAnyOrder(json("_id: 8, b: {c: {d: 1, e: 2}}"));
assertThat(collection.find(json("'b.c.e': 2")))
.containsExactlyInAnyOrder(json("_id: 8, b: {c: {d: 1, e: 2}}"));
}
@Test
public void testQueryWithEquivalentEmbeddedDocument() throws Exception {
collection.insertOne(json("_id: 1, a: {b: 1, c: 0}"));
collection.insertOne(json("_id: 2, a: {b: 1, c: 0.0}"));
collection.insertOne(json("_id: 3, a: {b: 1.0, c: 0.0}"));
collection.insertOne(json("_id: 4, a: {b: 1.0, c: 0}"));
collection.insertOne(json("_id: 5, a: {b: {c: 1.0}}"));
collection.insertOne(json("_id: 6, a: {b: {c: 1}}"));
collection.insertOne(json("_id: 7, a: {b: {c: 1, d: 1.0}}"));
collection.insertOne(json("_id: 8, a: {c: 0, b: 1.0}"));
collection.insertOne(json("_id: 9, a: {c: 0}"));
collection.insertOne(json("_id: 10, a: {b: 1}"));
assertThat(collection.find(json("a: {b: 1.0, c: -0.0}")))
.containsExactlyInAnyOrder(
json("_id: 1, a: {b: 1, c: 0}"),
json("_id: 2, a: {b: 1, c: 0.0}"),
json("_id: 3, a: {b: 1.0, c: 0.0}"),
json("_id: 4, a: {b: 1.0, c: 0}")
);
assertThat(collection.find(json("a: {b: {c: 1}}")))
.containsExactlyInAnyOrder(
json("_id: 5, a: {b: {c: 1.0}}"),
json("_id: 6, a: {b: {c: 1}}")
);
}
@Test
public void testOrderByMissingAndNull() throws Exception {
collection.insertOne(json("_id: 1, a: null"));
collection.insertOne(json("_id: 2"));
collection.insertOne(json("_id: 3, a: {b: 1}"));
collection.insertOne(json("_id: 4, a: null"));
collection.insertOne(json("_id: 5"));
assertThat(collection.find(json("")).sort(json("a: 1, _id: 1")))
.containsExactly(
json("_id: 1, a: null"),
json("_id: 2"),
json("_id: 4, a: null"),
json("_id: 5"),
json("_id: 3, a: {b: 1}")
);
}
@Test
public void testOrderByEmbeddedDocument() throws Exception {
collection.insertOne(json("_id: 1, a: {b: 1, c: 0}"));
collection.insertOne(json("_id: 2, a: {b: 1, c: 0.0}"));
collection.insertOne(json("_id: 3, a: {b: 1, c: null}"));
collection.insertOne(json("_id: 4, a: {b: 1.0, c: 0}"));
collection.insertOne(json("_id: 5, a: {b: 1.0, c: 0.0}"));
collection.insertOne(json("_id: 6, a: {b: 1.0, c: 0}"));
collection.insertOne(json("_id: 7, a: {b: {c: 1.0}}"));
collection.insertOne(json("_id: 8, a: {c: 0, b: 1.0}"));
collection.insertOne(json("_id: 9, a: {c: 0}"));
collection.insertOne(json("_id: 10, a: {b: 1}"));
collection.insertOne(json("_id: 11, a: {b: {c: 0.0}}"));
collection.insertOne(json("_id: 12, a: {c: 2}"));
collection.insertOne(json("_id: 13, a: {b: null, c: 0}"));
collection.insertOne(json("_id: 14, a: {b: 'abc'}"));
collection.insertOne(json("_id: 15, a: null, b: 123"));
collection.insertOne(json("_id: 16, b: 123"));
collection.insertOne(json("_id: 17, a: null, b: 123"));
assertThat(collection.find(json("")).sort(json("a: 1, _id: 1")))
.containsExactly(
json("_id: 15, a: null, b: 123"),
json("_id: 16, b: 123"),
json("_id: 17, a: null, b: 123"),
json("_id: 13, a: {b: null, c: 0}"),
json("_id: 10, a: {b: 1}"),
json("_id: 3, a: {b: 1, c: null}"),
json("_id: 1, a: {b: 1, c: 0}"),
json("_id: 2, a: {b: 1, c: 0.0}"),
json("_id: 4, a: {b: 1.0, c: 0}"),
json("_id: 5, a: {b: 1.0, c: 0.0}"),
json("_id: 6, a: {b: 1.0, c: 0}"),
json("_id: 9, a: {c: 0}"),
json("_id: 8, a: {c: 0, b: 1.0}"),
json("_id: 12, a: {c: 2}"),
json("_id: 14, a: {b: 'abc'}"),
json("_id: 11, a: {b: {c: 0.0}}"),
json("_id: 7, a: {b: {c: 1.0}}")
);
}
@Test
public void testFindByListValue() throws Exception {
collection.insertOne(json("_id: 1, a: [2, 1]"));
collection.insertOne(json("_id: 2, a: [2, 1.0]"));
collection.insertOne(json("_id: 3, a: [1, 2]"));
collection.insertOne(json("_id: 4, a: [1, 2, 3]"));
collection.insertOne(json("_id: 5, a: [3, 2]"));
collection.insertOne(json("_id: 6, a: [2, 3]"));
collection.insertOne(json("_id: 7, a: [3]"));
collection.insertOne(json("_id: 8, a: [3, 2]"));
assertThat(collection.find(json("a: [2, 1]")))
.containsExactlyInAnyOrder(
json("_id: 1, a: [2, 1]"),
json("_id: 2, a: [2, 1.0]")
);
assertThat(collection.find(json("a: [1, 2]")))
.containsExactly(json("_id: 3, a: [1, 2]"));
}
@Test
public void testFindAndOrderByWithListValues() throws Exception {
collection.insertOne(json("_id: 1, a: []"));
collection.insertOne(json("_id: 2, a: null"));
collection.insertOne(json("_id: 3, a: [2, 1]"));
collection.insertOne(json("_id: 4, a: [2, 1.0]"));
collection.insertOne(json("_id: 5, a: [1, 2]"));
collection.insertOne(json("_id: 6, a: [1, 2, 3]"));
collection.insertOne(json("_id: 7, a: [3, 2]"));
collection.insertOne(json("_id: 8, a: [2, 3]"));
collection.insertOne(json("_id: 9, a: [3]"));
collection.insertOne(json("_id: 10, a: [3, 2]"));
collection.insertOne(json("_id: 11, a: [null, 1, 2]"));
collection.insertOne(json("_id: 12, a: [1, 'abc', 2]"));
collection.insertOne(json("_id: 13"));
collection.insertOne(json("_id: 14, a: 'xyz'"));
collection.insertOne(json("_id: 15, a: {b: 5}"));
collection.insertOne(json("_id: 16, a: 1"));
assertThat(collection.find(json("")).sort(json("a: 1, _id: -1")))
.containsExactly(
json("_id: 1, a: []"),
json("_id: 13"),
json("_id: 11, a: [null, 1, 2]"),
json("_id: 2, a: null"),
json("_id: 16, a: 1"),
json("_id: 12, a: [1, 'abc', 2]"),
json("_id: 6, a: [1, 2, 3]"),
json("_id: 5, a: [1, 2]"),
json("_id: 4, a: [2, 1.0]"),
json("_id: 3, a: [2, 1]"),
json("_id: 10, a: [3, 2]"),
json("_id: 8, a: [2, 3]"),
json("_id: 7, a: [3, 2]"),
json("_id: 9, a: [3]"),
json("_id: 14, a: 'xyz'"),
json("_id: 15, a: {b: 5}")
);
assertThat(collection.find(json("")).sort(json("a: 1, _id: 1")))
.containsExactly(
json("_id: 1, a: []"),
json("_id: 2, a: null"),
json("_id: 11, a: [null, 1, 2]"),
json("_id: 13"),
json("_id: 3, a: [2, 1]"),
json("_id: 4, a: [2, 1.0]"),
json("_id: 5, a: [1, 2]"),
json("_id: 6, a: [1, 2, 3]"),
json("_id: 12, a: [1, 'abc', 2]"),
json("_id: 16, a: 1"),
json("_id: 7, a: [3, 2]"),
json("_id: 8, a: [2, 3]"),
json("_id: 10, a: [3, 2]"),
json("_id: 9, a: [3]"),
json("_id: 14, a: 'xyz'"),
json("_id: 15, a: {b: 5}")
);
assertThat(collection.find(json("")).sort(json("a: -1, _id: -1")))
.containsExactly(
json("_id: 15, a: {b: 5}"),
json("_id: 14, a: 'xyz'"),
json("_id: 12, a: [1, 'abc', 2]"),
json("_id: 10, a: [3, 2]"),
json("_id: 9, a: [3]"),
json("_id: 8, a: [2, 3]"),
json("_id: 7, a: [3, 2]"),
json("_id: 6, a: [1, 2, 3]"),
json("_id: 11, a: [null, 1, 2]"),
json("_id: 5, a: [1, 2]"),
json("_id: 4, a: [2, 1.0]"),
json("_id: 3, a: [2, 1]"),
json("_id: 16, a: 1"),
json("_id: 13"),
json("_id: 2, a: null"),
json("_id: 1, a: []")
);
}
@Test
public void testDistinctEmbeddedDocument() throws Exception {
collection.insertOne(json("_id: 1, a: {b: 1, c: 0}"));
collection.insertOne(json("_id: 2, a: {b: null}"));
collection.insertOne(json("_id: 3, a: {b: 1, c: null}"));
collection.insertOne(json("_id: 4, a: {b: 1.0, c: 0}"));
collection.insertOne(json("_id: 5, a: {b: 1.0, c: 0.0}"));
collection.insertOne(json("_id: 6, a: {b: 1.0, c: null}"));
collection.insertOne(json("_id: 7, a: {b: {c: 1.0}}"));
collection.insertOne(json("_id: 8, a: {c: 0, b: 1.0}"));
collection.insertOne(json("_id: 9, a: {c: 0, b: null}"));
collection.insertOne(json("_id: 10, a: {b: 1}"));
collection.insertOne(json("_id: 11, a: {b: {c: 0.0}}"));
collection.insertOne(json("_id: 12"));
collection.insertOne(json("_id: 13, a: {c: 0}"));
collection.insertOne(json("_id: 14, a: {c: null}"));
collection.insertOne(json("_id: 15, a: null"));
assertThat(collection.distinct("a", Document.class))
.containsExactlyInAnyOrder(
json("b: 1, c: 0"),
json("b: null"),
json("b: 1, c: null"),
json("b: {c: 1.0}"),
json("b: 1.0, c: 0"),
json("b: null, c: 0"),
json("b: 1"),
json("b: {c: 0.0}"),
json("c: 0"),
json("c: null"),
null
);
}
@Test
public void testEmptyArrayQuery() throws Exception {
collection.insertOne(json("_id: 1"));
assertThatExceptionOfType(MongoQueryException.class)
.isThrownBy(() -> collection.find(Filters.and()).first())
.withMessageContaining("must be a nonempty array");
}
@Test
public void testFindAllReferences() throws Exception {
collection.insertOne(new Document("_id", 1).append("ref", new DBRef("coll1", 1)));
collection.insertOne(new Document("_id", 2).append("ref", new DBRef("coll1", 2)));
collection.insertOne(new Document("_id", 3).append("ref", new DBRef("coll2", 1)));
collection.insertOne(new Document("_id", 4).append("ref", new DBRef("coll2", 2)));
collection.insertOne(json("_id: 5, ref: [1, 2, 3, 4]"));
collection.insertOne(json("_id: 6"));
assertThat(collection.find(json("ref: {$ref: 'coll1', $id: 1}")).projection(json("_id: 1")))
.containsExactly(json("_id: 1"));
}
@Test
public void testInsertAndQueryNegativeZero() throws Exception {
collection.insertOne(json("_id: 1, value: -0.0"));
collection.insertOne(json("_id: 2, value: 0.0"));
collection.insertOne(json("_id: 3, value: -0.0"));
assertThat(collection.find(json("value: -0.0")))
.containsExactlyInAnyOrder(
json("_id: 1, value: -0.0"),
json("_id: 2, value: 0.0"),
json("_id: 3, value: -0.0")
);
assertThat(collection.find(json("value: {$lt: 0.0}"))).isEmpty();
assertThat(collection.find(json("value: 0")).sort(json("value: 1, _id: 1")))
.extracting(doc -> doc.getDouble("value"))
.containsExactly(-0.0, +0.0, -0.0);
}
@Test
public void testUniqueIndexWithNegativeZero() throws Exception {
collection.createIndex(json("value: 1"), new IndexOptions().unique(true));
collection.insertOne(json("_id: 1, value: -0.0"));
assertMongoWriteException(() -> collection.insertOne(json("_id: 2, value: 0.0")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: value_1 dup key: { : 0.0 }");
assertMongoWriteException(() -> collection.insertOne(json("_id: 3, value: -0.0")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: value_1 dup key: { : -0.0 }");
assertMongoWriteException(() -> collection.insertOne(json("_id: 4, value: 0")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: value_1 dup key: { : 0 }");
}
// https://github.com/bwaldvogel/mongo-java-server/issues/45
@Test
public void testDecimal128() throws Exception {
collection.insertOne(json("_id: {'$numberDecimal': '1'}"));
collection.insertOne(json("_id: {'$numberDecimal': '2'}"));
collection.insertOne(json("_id: {'$numberDecimal': '3.0'}"));
collection.insertOne(json("_id: {'$numberDecimal': '200000000000000000000000000000000.5'}"));
assertMongoWriteException(() -> collection.insertOne(json("_id: {'$numberDecimal': '1'}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: _id_ dup key: { : 1 }");
assertThat(collection.find(json("_id: {$eq: {'$numberDecimal': '3'}}")))
.containsExactly(
json("_id: {'$numberDecimal': '3.0'}")
);
assertThat(collection.find(json("_id: {$gt: {'$numberDecimal': '100000'}}")))
.containsExactly(
json("_id: {'$numberDecimal': '200000000000000000000000000000000.5'}")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/45
@Test
public void testArrayNe() throws Exception {
collection.insertOne(json("_id: 'a', values: [-1]"));
collection.insertOne(json("_id: 'b', values: [0]"));
collection.insertOne(json("_id: 'c', values: 1.0"));
collection.insertOne(json("_id: 'd', values: {'$numberDecimal': '1.0'}"));
collection.insertOne(json("_id: 'e', values: {'$numberDecimal': '0.0'}"));
collection.insertOne(json("_id: 'f', values: [-0.0]"));
collection.insertOne(json("_id: 'g', values: [0, 1]"));
collection.insertOne(json("_id: 'h', values: 0.0"));
collection.insertOne(json("_id: 'i', values: []"));
collection.insertOne(json("_id: 'j', values: null"));
collection.insertOne(json("_id: 'k'"));
assertThat(collection.find(json("values: {$ne: 0}")))
.containsExactly(
json("_id: 'a', values: [-1]"),
json("_id: 'c', values: 1.0"),
json("_id: 'd', values: {'$numberDecimal': '1.0'}"),
json("_id: 'i', values: []"),
json("_id: 'j', values: null"),
json("_id: 'k'")
);
assertThat(collection.find(json("values: {$ne: []}")))
.containsExactly(
json("_id: 'a', values: [-1]"),
json("_id: 'b', values: [0]"),
json("_id: 'c', values: 1.0"),
json("_id: 'd', values: {'$numberDecimal': '1.0'}"),
json("_id: 'e', values: {'$numberDecimal': '0.0'}"),
json("_id: 'f', values: [-0.0]"),
json("_id: 'g', values: [0, 1]"),
json("_id: 'h', values: 0.0"),
json("_id: 'j', values: null"),
json("_id: 'k'")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/48
@Test
public void testExistsQuery() throws Exception {
collection.insertOne(json("_id: 1, a: {b: 1}"));
collection.insertOne(json("_id: 2, a: null"));
collection.insertOne(json("_id: 3, a: {b: null}"));
collection.insertOne(json("_id: 4"));
assertThat(collection.find(json("'a.b': {$exists: false}")))
.containsExactlyInAnyOrder(
json("_id: 2, a: null"),
json("_id: 4")
);
assertThat(collection.find(json("'a.b': {$exists: true}")))
.containsExactlyInAnyOrder(
json("_id: 1, a: {b: 1}"),
json("_id: 3, a: {b: null}")
);
assertThat(collection.find(json("a: {b: {$exists: true}}"))).isEmpty();
assertThat(collection.find(json("a: {$exists: true}")))
.containsExactlyInAnyOrder(
json("_id: 1, a: {b: 1}"),
json("_id: 2, a: null"),
json("_id: 3, a: {b: null}")
);
assertThat(collection.find(json("b: {$exists: true}"))).isEmpty();
}
@Test
public void testExistsQueryWithArray() throws Exception {
collection.insertOne(json("_id: 1, a: {b: 1}"));
collection.insertOne(json("_id: 2, a: ['X', 'Y', 'Z']"));
collection.insertOne(json("_id: 3, a: [[1, 2], [3, 4]]"));
collection.insertOne(json("_id: 4, a: ['x']"));
collection.insertOne(json("_id: 5, a: []"));
collection.insertOne(json("_id: 6, a: null"));
collection.insertOne(json("_id: 7"));
assertThat(collection.find(json("'a.1': {$exists: true}")))
.containsExactlyInAnyOrder(
json("_id: 2, a: ['X', 'Y', 'Z']"),
json("_id: 3, a: [[1, 2], [3, 4]]")
);
assertThat(collection.find(json("'a.0': {$exists: false}")))
.containsExactlyInAnyOrder(
json("_id: 1, a: {b: 1}"),
json("_id: 5, a: []"),
json("_id: 6, a: null"),
json("_id: 7")
);
assertThat(collection.find(json("'a.0.1': {$exists: true}")))
.containsExactlyInAnyOrder(
json("_id: 3, a: [[1, 2], [3, 4]]")
);
assertThat(collection.find(json("'a.0.1': {$exists: false}")))
.containsExactlyInAnyOrder(
json("_id: 1, a: {b: 1}"),
json("_id: 2, a: ['X', 'Y', 'Z']"),
json("_id: 4, a: ['x']"),
json("_id: 5, a: []"),
json("_id: 6, a: null"),
json("_id: 7")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/53
@Test
public void testExistsQueryWithTrailingDot() throws Exception {
collection.insertOne(json("_id: 1, a: {b: 1}"));
collection.insertOne(json("_id: 2, a: ['X', 'Y', 'Z']"));
collection.insertOne(json("_id: 3, a: [[1, 2], [3, 4]]"));
collection.insertOne(json("_id: 4, a: ['x']"));
collection.insertOne(json("_id: 5, a: []"));
collection.insertOne(json("_id: 6, a: null"));
collection.insertOne(json("_id: 7"));
collection.insertOne(json("_id: 8, a: {b: {c: 'd'}}"));
assertThat(collection.find(json("'a.': {$exists: true}")))
.containsExactlyInAnyOrder(
json("_id: 2, a: ['X', 'Y', 'Z']"),
json("_id: 3, a: [[1, 2], [3, 4]]"),
json("_id: 4, a: ['x']"),
json("_id: 5, a: []")
);
assertThat(collection.find(json("'a.1.': {$exists: true}")))
.containsExactlyInAnyOrder(
json("_id: 3, a: [[1, 2], [3, 4]]")
);
assertThat(collection.find(json("'.a': {$exists: true}"))).isEmpty();
assertThat(collection.find(json("'a.b.': {$exists: true}"))).isEmpty();
assertThat(collection.find(json("'a..': {$exists: true}"))).isEmpty();
assertThat(collection.find(json("'a.....111': {$exists: true}"))).isEmpty();
assertThat(collection.find(json("'a.': {$exists: false}")))
.containsExactlyInAnyOrder(
json("_id: 1, a: {b: 1}"),
json("_id: 6, a: null"),
json("_id: 7"),
json("_id: 8, a: {b: {c: 'd'}}")
);
assertThat(collection.find(json("'a.1.': {$exists: false}")))
.containsExactlyInAnyOrder(
json("_id: 1, a: {b: 1}"),
json("_id: 2, a: ['X', 'Y', 'Z']"),
json("_id: 4, a: ['x']"),
json("_id: 5, a: []"),
json("_id: 6, a: null"),
json("_id: 7"),
json("_id: 8, a: {b: {c: 'd'}}")
);
assertThat(collection.find(json("'a..': {$exists: false}")))
.containsExactlyInAnyOrder(
json("_id: 1, a: {b: 1}"),
json("_id: 2, a: ['X', 'Y', 'Z']"),
json("_id: 3, a: [[1, 2], [3, 4]]"),
json("_id: 4, a: ['x']"),
json("_id: 5, a: []"),
json("_id: 6, a: null"),
json("_id: 7"),
json("_id: 8, a: {b: {c: 'd'}}")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/56
@Test
public void testRegExQuery() throws Exception {
collection.insertOne(json("_id: 'one', name: 'karl'"));
collection.insertOne(json("_id: 'two', name: 'Karl'"));
collection.insertOne(json("_id: 'Three', name: 'KARL'"));
collection.insertOne(json("_id: null"));
collection.insertOne(json("_id: 123, name: ['karl', 'john']"));
assertThat(collection.find(json("_id: {$regex: '^T.+$', $options: 'i'}")))
.containsExactlyInAnyOrder(
json("_id: 'two', name: 'Karl'"),
json("_id: 'Three', name: 'KARL'")
);
assertThat(collection.find(json("_id: {$regex: 't.+'}")))
.containsExactly(
json("_id: 'two', name: 'Karl'")
);
assertThat(collection.find(json("_id: {$regex: '^(one|1.+)$'}")))
.containsExactly(
json("_id: 'one', name: 'karl'")
);
assertThat(collection.find(json("name: {$regex: 'arl', $options: 'i'}")))
.containsExactlyInAnyOrder(
json("_id: 'one', name: 'karl'"),
json("_id: 'two', name: 'Karl'"),
json("_id: 'Three', name: 'KARL'"),
json("_id: 123, name: ['karl', 'john']")
);
}
// https://github.com/bwaldvogel/mongo-java-server/issues/67
@Test
public void testInsertAndFindJavaScriptContent() throws Exception {
collection.insertOne(new Document("_id", 1).append("data", new BsonJavaScript("int i = 0")));
assertThat(collection.find(json("_id: 1")).first())
.extracting(document -> document.get("data"))
.isEqualTo(new Code("int i = 0"));
assertThat(collection.find(new Document("data", new BsonJavaScript("int i = 0"))).first())
.extracting(document -> document.get("_id"))
.isEqualTo(1);
}
private void insertAndFindLargeDocument(int numKeyValues, int id) {
Document document = new Document("_id", id);
for (int i = 0; i < numKeyValues; i++) {
document.put("key-" + i, "value-" + i);
}
collection.insertOne(document);
Document persistentDocument = collection.find(new Document("_id", id)).first();
assertThat(persistentDocument).hasSize(numKeyValues + 1);
}
private void insertUpdateInBulk(boolean ordered) {
List> ops = new ArrayList<>();
ops.add(new InsertOneModel<>(json("_id: 1, field: 'x'")));
ops.add(new InsertOneModel<>(json("_id: 2, field: 'x'")));
ops.add(new InsertOneModel<>(json("_id: 3, field: 'x'")));
ops.add(new UpdateManyModel<>(json("field: 'x'"), set("field", "y")));
BulkWriteResult result = collection.bulkWrite(ops, new BulkWriteOptions().ordered(ordered));
assertThat(result.getInsertedCount()).isEqualTo(3);
assertThat(result.getDeletedCount()).isEqualTo(0);
assertThat(result.getModifiedCount()).isEqualTo(3);
assertThat(result.getMatchedCount()).isEqualTo(3);
long totalDocuments = collection.countDocuments();
assertThat(totalDocuments).isEqualTo(3);
long documentsWithY = collection.countDocuments(json("field: 'y'"));
assertThat(documentsWithY).isEqualTo(3);
}
private void insertUpdateInBulkNoMatch(boolean ordered) {
collection.insertOne(json("foo: 'bar'"));
List> ops = new ArrayList<>();
ops.add(new UpdateOneModel<>(ne("foo", "bar"), set("field", "y")));
BulkWriteResult result = collection.bulkWrite(ops, new BulkWriteOptions().ordered(ordered));
assertThat(result.getInsertedCount()).isEqualTo(0);
assertThat(result.getDeletedCount()).isEqualTo(0);
assertThat(result.getModifiedCount()).isEqualTo(0);
assertThat(result.getMatchedCount()).isEqualTo(0);
}
private void removeInBulk(boolean ordered) {
DeleteManyModel deleteOp = new DeleteManyModel<>(json("field: 'y'"));
BulkWriteResult result = collection.bulkWrite(Collections.singletonList(deleteOp),
new BulkWriteOptions().ordered(ordered));
assertThat(result.getDeletedCount()).isEqualTo(3);
assertThat(collection.countDocuments()).isZero();
}
@FunctionalInterface
private interface Callable {
void call();
}
private static void assertMongoWriteException(Callable callable, int expectedErrorCode, String expectedMessage) {
assertMongoWriteException(callable, expectedErrorCode, "Location" + expectedErrorCode, expectedMessage);
}
private static void assertMongoWriteException(Callable callable, int expectedErrorCode, String expectedCodeName,
String expectedMessage) {
try {
callable.call();
fail("MongoWriteException expected");
} catch (MongoWriteException e) {
assertThat(e).hasMessage(expectedMessage);
assertThat(e.getError().getCode()).isEqualTo(expectedErrorCode);
Document actual = db.runCommand(json("getlasterror: 1"));
assertThat(actual.getString("codeName")).isEqualTo(expectedCodeName);
}
}
// https://github.com/bwaldvogel/mongo-java-server/issues/76
@Test
public void testInsertWithoutId() throws Exception {
DocumentCodec documentCodec = Mockito.spy(new DocumentCodec());
Mockito.doAnswer(AdditionalAnswers.returnsFirstArg()).when(documentCodec).generateIdIfAbsentFromDocument(Mockito.any());
MongoClientOptions mongoClientOptions = MongoClientOptions.builder()
.codecRegistry(CodecRegistries.fromCodecs(documentCodec))
.build();
try (MongoClient mongoClient = new MongoClient(new ServerAddress(serverAddress), mongoClientOptions)) {
MongoDatabase database = mongoClient.getDatabase(db.getName());
MongoCollection collection = database.getCollection(getCollectionName());
collection.insertOne(json("x: 1"));
assertThat(collection.find(json("x: 1")).first().get("_id"))
.isInstanceOf(ObjectId.class);
}
Mockito.verify(documentCodec).generateIdIfAbsentFromDocument(Mockito.any());
}
@Test
public void testMultikeyIndex_simpleArrayValues() throws Exception {
collection.createIndex(json("a: 1"), new IndexOptions().unique(true));
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2, a: 1"));
collection.insertOne(json("_id: 3, a: [2, 3]"));
collection.insertOne(json("_id: 4, a: [4, 5, 4]"));
collection.insertOne(json("_id: 5, a: [[1, 2], [3, 4]]"));
collection.insertOne(json("_id: 6, a: [[1, 3], [4, 5]]"));
collection.insertOne(json("_id: 7, a: [[2, 1], [4, 3]]"));
assertMongoWriteException(() -> collection.insertOne(json("a: [1]")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1 dup key: { : 1 }");
assertMongoWriteException(() -> collection.insertOne(json("a: [6, 1]")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1 dup key: { : 1 }");
assertMongoWriteException(() -> collection.insertOne(json("a: [2.0, 4.0]")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1 dup key: { : 2.0 }");
assertMongoWriteException(() -> collection.insertOne(json("a: [[1, 4], [3, 4]]")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1 dup key: { : [ 3, 4 ] }");
collection.deleteOne(json("_id: 3"));
collection.insertOne(json("_id: 8, a: [2, 3]"));
assertMongoWriteException(() -> collection.replaceOne(json("_id: 1"), json("_id: 1, a: [3, 4]")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1 dup key: { : 3 }");
collection.replaceOne(json("_id: 4"), json("_id: 4, a: ['x', 'y']"));
collection.insertOne(json("_id: 9, a: [4, 6]"));
assertMongoWriteException(() -> collection.updateOne(json("_id: 9"), json("$push: {a: 2}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1 dup key: { : 2 }");
Document result = collection.findOneAndUpdate(json("_id: 8"), json("$pull: {a: 2}"),
new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER));
assertThat(result).isEqualTo(json("_id: 8, a: [3]"));
result = collection.findOneAndUpdate(json("_id: 9"), json("$push: {a: 2}"),
new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER));
assertThat(result).isEqualTo(json("_id: 9, a: [4, 6, 2]"));
result = collection.findOneAndUpdate(json("_id: 9"), json("$push: {a: 2}"),
new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER));
assertThat(result).isEqualTo(json("_id: 9, a: [4, 6, 2, 2]"));
}
@Test
public void testCompoundMultikeyIndex_simpleArrayValues() throws Exception {
collection.createIndex(json("a: 1, b: 1"), new IndexOptions().unique(true));
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2, a: 1"));
collection.insertOne(json("_id: 3, a: [2, 3], b: 1"));
collection.insertOne(json("_id: 4, a: [4, 5], b: 1"));
collection.insertOne(json("_id: 5, a: [1, 2, 3, 4, 5], b: 2"));
assertMongoWriteException(() -> collection.insertOne(json("a: [1]")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1_b_1 dup key: { : 1, : null }");
assertMongoWriteException(() -> collection.insertOne(json("a: [6, 2], b: 1")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1_b_1 dup key: { : 2, : 1 }");
assertMongoWriteException(() -> collection.insertOne(json("a: ['abc'], b: [1, 2, 3]")),
171, "CannotIndexParallelArrays", "cannot index parallel arrays [b] [a]");
collection.deleteOne(json("_id: 3"));
collection.insertOne(json("_id: 6, a: [2, 3], b: 1"));
assertMongoWriteException(() -> collection.replaceOne(json("_id: 1"), json("_id: 1, a: [3, 4], b: 1")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a_1_b_1 dup key: { : 3, : 1 }");
collection.replaceOne(json("_id: 4"), json("_id: 4, a: ['x', 'y'], b: 1"));
collection.insertOne(json("_id: 7, a: [4, 6], b: 1"));
}
@Test
public void testCompoundMultikeyIndex_threeKeys() throws Exception {
collection.createIndex(json("b: 1, a: 1, c: 1"), new IndexOptions().unique(true));
assertMongoWriteException(() -> collection.insertOne(json("b: [1, 2, 3], a: ['abc'], c: ['x', 'y']")),
171, "CannotIndexParallelArrays", "cannot index parallel arrays [a] [b]");
}
// https://github.com/bwaldvogel/mongo-java-server/issues/69
@Test
public void testCompoundMultikeyIndex_documents() throws Exception {
collection.createIndex(json("item: 1, 'stock.size': 1"), new IndexOptions().unique(true));
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2, item: 'abc'"));
collection.insertOne(json("_id: 3, item: 'abc', stock: [{size: 'S', color: 'red'}]"));
collection.insertOne(json("_id: 4, item: 'abc', stock: [{size: 'L', color: 'black'}]"));
collection.insertOne(json("_id: 5, item: 'abc', stock: [{size: 'M'}, {size: 'XL'}]"));
collection.insertOne(json("_id: 6, item: 'xyz', stock: [{size: 'S'}, {size: 'M'}]"));
collection.insertOne(json("_id: 7, item: 'xyz', stock: [1, 2, 3]"));
assertMongoWriteException(() -> collection.insertOne(json("item: 'abc'")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: item_1_stock.size_1 dup key: { : \"abc\", : null }");
assertMongoWriteException(() -> collection.insertOne(json("item: 'abc', stock: [{color: 'black'}]")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: item_1_stock.size_1 dup key: { : \"abc\", : null }");
assertMongoWriteException(() -> collection.insertOne(json("item: 'abc', stock: [{size: 'S'}]")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: item_1_stock.size_1 dup key: { : \"abc\", : \"S\" }");
assertMongoWriteException(() -> collection.insertOne(json("item: 'abc', stock: [{size: 'XL'}]")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: item_1_stock.size_1 dup key: { : \"abc\", : \"XL\" }");
}
@Test
public void testCompoundMultikeyIndex_deepDocuments() throws Exception {
collection.createIndex(json("'a.b.c': 1"), new IndexOptions().unique(true));
collection.insertOne(json("_id: 1"));
collection.insertOne(json("_id: 2, a: {b: {c: 1}}"));
collection.insertOne(json("_id: 3, a: {b: {c: 2}}"));
collection.insertOne(json("_id: 4, a: [{b: {c: 3}}, {b: {c: 4}}]"));
collection.insertOne(json("_id: 5, a: [{b: [{c: 5}, {c: 6}]}, {b: [{c: 7}, {c: 8}]}]"));
assertMongoWriteException(() -> collection.insertOne(json("a: {b: 1}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a.b.c_1 dup key: { : null }");
assertMongoWriteException(() -> collection.insertOne(json("a: [{b: 1}, {b: 2}]")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a.b.c_1 dup key: { : null }");
assertMongoWriteException(() -> collection.insertOne(json("a: {b: {c: 1}}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a.b.c_1 dup key: { : 1 }");
assertMongoWriteException(() -> collection.insertOne(json("a: {b: {c: [1, 2]}}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a.b.c_1 dup key: { : 1 }");
assertMongoWriteException(() -> collection.insertOne(json("a: {b: {c: 4}}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a.b.c_1 dup key: { : 4 }");
assertMongoWriteException(() -> collection.insertOne(json("a: {b: {c: 8}}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: a.b.c_1 dup key: { : 8 }");
}
// https://github.com/bwaldvogel/mongo-java-server/issues/82
@Test
public void testUpdateArrayWithPositionalAll() {
collection.insertOne(json("_id: 1, grades: [95, 102, 90, 150]"));
collection.findOneAndUpdate(
json("_id: 1"),
json("$inc: {'grades.$[]': -10}"));
assertThat(collection.find(json("_id: 1")).first())
.isEqualTo(json("_id: 1, grades: [85, 92, 80, 140]"));
collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades.$[]': 'abc'}"));
assertThat(collection.find(json("_id: 1")).first())
.isEqualTo(json("_id: 1, grades: ['abc', 'abc', 'abc', 'abc']"));
}
@Test
public void testUpdateArrayWithPositionalAll_NullValue() {
collection.insertOne(json("_id: 1, grades: [1, 2, null, 3]"));
collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades.$[]': 'abc'}"));
assertThat(collection.find(json("_id: 1")).first())
.isEqualTo(json("_id: 1, grades: ['abc', 'abc', 'abc', 'abc']"));
}
@Test
public void testUpdateArrayWithPositionalAllAndArrayFilter() {
collection.insertOne(json("_id: 1, grades: [{x: [1, 2, 3]}, {x: [3, 4, 5]}, {x: [1, 2, 3]}]"));
collection.findOneAndUpdate(
json("_id: 1"),
json("$inc: {'grades.$[].x.$[element]': 1}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("element: {$gte: 3}"))));
assertThat(collection.find(json("_id: 1")).first())
.isEqualTo(json("_id: 1, grades: [{x: [1, 2, 4]}, {x: [4, 5, 6]}, {x: [1, 2, 4]}]"));
}
@Test
public void testUpdateArrayOfDocumentsWithPositionalAll() {
collection.insertOne(json("_id: 1, grades: [{value: 20}, {value: 30}, {value: 40}]"));
collection.findOneAndUpdate(
json("_id: 1"),
json("$inc: {'grades.$[].value': 10}"));
assertThat(collection.find(json("_id: 1")).first())
.isEqualTo(json("_id: 1, grades: [{value: 30}, {value: 40}, {value: 50}]"));
collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades.$[].value': 10}"));
assertThat(collection.find(json("_id: 1")).first())
.isEqualTo(json("_id: 1, grades: [{value: 10}, {value: 10}, {value: 10}]"));
}
@Test
public void testIllegalUpdateWithPositionalAll() {
collection.insertOne(json("_id: 1, a: {b: [1, 2, 3]}"));
collection.insertOne(json("_id: 2, a: {b: 5}"));
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(json("_id: 1"), json("$set: {'a.$[]': 'abc'}")))
.withMessageContaining("Command failed with error 2 (BadValue): 'Cannot apply array updates to non-array element a: { b: [ 1, 2, 3 ] }");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(json("_id: 2"), json("$set: {'a.b.$[]': 'abc'}")))
.withMessageContaining("Command failed with error 2 (BadValue): 'Cannot apply array updates to non-array element b: 5");
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(json("_id: 1"), json("$set: {'a.b.$[].c': 'abc'}")))
.withMessageContaining("Command failed with error 28 (PathNotViable): 'Cannot create field 'c' in element {0: 1}");
}
// https://github.com/bwaldvogel/mongo-java-server/issues/82
@Test
public void testUpsertWithPositionalAll() throws Exception {
Document result = collection.findOneAndUpdate(json("_id: 1, a: [5, 8]"), json("$set: {'a.$[]': 1}"),
new FindOneAndUpdateOptions().upsert(true).returnDocument(ReturnDocument.AFTER));
assertThat(result).isEqualTo(json("_id: 1, a: [1, 1]"));
}
@Test
public void testUpdateWithMultipleArrayFiltersInOnePath() throws Exception {
collection.insertOne(json("_id: 1, grades: [{value: 10, x: [1, 2]}, {value: 20, x: [3, 4]}]"));
collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades.$[element].x.$[]': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("'element.value': {$gt: 10}"))));
assertThat(collection.find(json("_id: 1")).first())
.isEqualTo(json("_id: 1, grades: [{value: 10, x: [1, 2]}, {value: 20, x: ['abc', 'abc']}]"));
collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades.0.x.$[element]': 'abc'}"),
new FindOneAndUpdateOptions().arrayFilters(Arrays.asList(json("'element': {$gt: 1}"))));
assertThat(collection.find(json("_id: 1")).first())
.isEqualTo(json("_id: 1, grades: [{value: 10, x: [1, 'abc']}, {value: 20, x: ['abc', 'abc']}]"));
}
@Test
public void testUpdateArrayWithMultiplePositionalAll() {
collection.insertOne(json("_id: 1, grades: [[1, 2], [3, 4]]"));
collection.insertOne(json("_id: 2, grades: [{c: [1, 2]}, {c: [3, 4]}]"));
collection.insertOne(json("_id: 3, grades: [{c: [1, 2]}, {c: [3, 4]}, {d: [5, 6]}]"));
collection.findOneAndUpdate(
json("_id: 1"),
json("$inc: {'grades.$[].$[]': 1}"));
assertThat(collection.find(json("_id: 1")).first())
.isEqualTo(json("_id: 1, grades: [[2, 3], [4, 5]]"));
collection.findOneAndUpdate(
json("_id: 2"),
json("$inc: {'grades.$[].c.$[]': 1}"));
assertThat(collection.find(json("_id: 2")).first())
.isEqualTo(json("_id: 2, grades: [{c: [2, 3]}, {c: [4, 5]}]"));
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(json("_id: 3"), json("$inc: {'grades.$[].c.$[]': 1}")))
.withMessageContaining("Command failed with error 2 (BadValue): 'The path 'grades.2.c' must exist in the document in order to apply array updates.");
}
@Test
public void testUpdateArrayWithMultiplePositionalAll_Simple() {
collection.insertOne(json("_id: 1, grades: [[1, 2], [3, 4]]"));
collection.findOneAndUpdate(
json("_id: 1"),
json("$set: {'grades.$[].$[]': 1}"));
assertThat(collection.find(json("_id: 1")).first())
.isEqualTo(json("_id: 1, grades: [[1, 1], [1, 1]]"));
}
@Test
public void testUpdateArrayWithIllegalMultiplePositionalAll() {
collection.insertOne(json("_id: 1, grades: [[[1, 2], [3, 4]], [[4, 5], [2, 3]]]"));
assertThatExceptionOfType(MongoCommandException.class)
.isThrownBy(() -> collection.findOneAndUpdate(
json("_id: 1"),
json("$inc: {'grades.$[].$[]': 1}")))
.withMessageContaining("Command failed with error 14 (TypeMismatch): 'Cannot apply $inc to a value of non-numeric type. {_id: 1} has the field '0' of non-numeric type array");
}
// https://github.com/bwaldvogel/mongo-java-server/issues/98
@Test
public void testGetKeyValues_multiKey_document_nested_objects() throws Exception {
collection.createIndex(json("'stock.size': 1, 'stock.quantity': 1"), new IndexOptions().unique(true));
collection.insertOne(json("stock: [{size: 'S', quantity: 10}]"));
collection.insertOne(json("stock: [{size: 'M', quantity: 10}, {size: 'L', quantity: 10}]"));
collection.insertOne(json("stock: [{size: 'S', quantity: 20}]"));
collection.insertOne(json("stock: [{quantity: 20}]"));
collection.insertOne(json("stock: [{size: 'M'}]"));
collection.insertOne(json("stock: {size: ['XL', 'XXL']}"));
assertThatExceptionOfType(MongoWriteException.class)
.isThrownBy(() -> collection.insertOne(json("stock: {size: ['S', 'M'], quantity: [30, 40]}")))
.withMessage("cannot index parallel arrays [quantity] [size]");
assertMongoWriteException(() -> collection.insertOne(json("stock: {size: 'S', quantity: 10}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: stock.size_1_stock.quantity_1 dup key: { : \"S\", : 10 }");
assertMongoWriteException(() -> collection.insertOne(json("stock: [{size: 'XL', quantity: 7}, {size: 'M', quantity: 10}]")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: stock.size_1_stock.quantity_1 dup key: { : \"M\", : 10 }");
assertMongoWriteException(() -> collection.insertOne(json("stock: [{size: 'M'}]")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: stock.size_1_stock.quantity_1 dup key: { : \"M\", : null }");
assertMongoWriteException(() -> collection.insertOne(json("stock: {size: 'XL'}")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: stock.size_1_stock.quantity_1 dup key: { : \"XL\", : null }");
assertMongoWriteException(() -> collection.insertOne(json("stock: [{quantity: 20}]")),
11000, "DuplicateKey", "E11000 duplicate key error collection: testdb.testcoll index: stock.size_1_stock.quantity_1 dup key: { : null, : 20 }");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy