Skip to content

Commit 36b60bd

Browse files
committed
JAVA-2552: Support array filters in MongoCollection (sync and async)
1 parent cc44e5f commit 36b60bd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1386
-311
lines changed

driver-async/src/main/com/mongodb/async/client/MongoCollectionImpl.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -308,14 +308,16 @@ public void bulkWrite(final List<? extends WriteModel<? extends TDocument>> requ
308308
WriteRequest.Type.UPDATE)
309309
.multi(false)
310310
.upsert(updateOneModel.getOptions().isUpsert())
311-
.collation(updateOneModel.getOptions().getCollation());
311+
.collation(updateOneModel.getOptions().getCollation())
312+
.arrayFilters(toBsonDocumentList(updateOneModel.getOptions().getArrayFilters()));
312313
} else if (writeModel instanceof UpdateManyModel) {
313314
UpdateManyModel<TDocument> updateManyModel = (UpdateManyModel<TDocument>) writeModel;
314315
writeRequest = new UpdateRequest(toBsonDocument(updateManyModel.getFilter()), toBsonDocument(updateManyModel.getUpdate()),
315316
WriteRequest.Type.UPDATE)
316317
.multi(true)
317318
.upsert(updateManyModel.getOptions().isUpsert())
318-
.collation(updateManyModel.getOptions().getCollation());
319+
.collation(updateManyModel.getOptions().getCollation())
320+
.arrayFilters(toBsonDocumentList(updateManyModel.getOptions().getArrayFilters()));
319321
} else if (writeModel instanceof DeleteOneModel) {
320322
DeleteOneModel<TDocument> deleteOneModel = (DeleteOneModel<TDocument>) writeModel;
321323
writeRequest = new DeleteRequest(toBsonDocument(deleteOneModel.getFilter())).multi(false)
@@ -498,7 +500,8 @@ public void findOneAndUpdate(final Bson filter, final Bson update, final FindOne
498500
.upsert(options.isUpsert())
499501
.maxTime(options.getMaxTime(MILLISECONDS), MILLISECONDS)
500502
.bypassDocumentValidation(options.getBypassDocumentValidation())
501-
.collation(options.getCollation()), callback);
503+
.collation(options.getCollation())
504+
.arrayFilters(toBsonDocumentList(options.getArrayFilters())), callback);
502505
}
503506

504507
@Override
@@ -627,7 +630,8 @@ public void onResult(final BulkWriteResult result, final Throwable t) {
627630
private void update(final Bson filter, final Bson update, final UpdateOptions options, final boolean multi,
628631
final SingleResultCallback<UpdateResult> callback) {
629632
executeSingleWriteRequest(new UpdateRequest(toBsonDocument(filter), toBsonDocument(update), WriteRequest.Type.UPDATE)
630-
.upsert(options.isUpsert()).multi(multi).collation(options.getCollation()), options.getBypassDocumentValidation(),
633+
.upsert(options.isUpsert()).multi(multi).collation(options.getCollation())
634+
.arrayFilters(toBsonDocumentList(options.getArrayFilters())), options.getBypassDocumentValidation(),
631635
new SingleResultCallback<BulkWriteResult>() {
632636
@Override
633637
public void onResult(final BulkWriteResult result, final Throwable t) {
@@ -708,4 +712,15 @@ private BsonDocument documentToBsonDocument(final TDocument document) {
708712
private BsonDocument toBsonDocument(final Bson document) {
709713
return document == null ? null : document.toBsonDocument(documentClass, codecRegistry);
710714
}
715+
716+
private List<BsonDocument> toBsonDocumentList(final List<? extends Bson> bsonList) {
717+
if (bsonList == null) {
718+
return null;
719+
}
720+
List<BsonDocument> bsonDocumentList = new ArrayList<BsonDocument>(bsonList.size());
721+
for (Bson cur : bsonList) {
722+
bsonDocumentList.add(toBsonDocument(cur));
723+
}
724+
return bsonDocumentList;
725+
}
711726
}

driver-async/src/test/functional/com/mongodb/async/client/CrudTest.java

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.mongodb.MongoNamespace;
2020
import com.mongodb.async.SingleResultCallback;
21+
import com.mongodb.bulk.BulkWriteResult;
2122
import com.mongodb.client.model.Collation;
2223
import com.mongodb.client.model.CollationAlternate;
2324
import com.mongodb.client.model.CollationCaseFirst;
@@ -28,8 +29,12 @@
2829
import com.mongodb.client.model.FindOneAndDeleteOptions;
2930
import com.mongodb.client.model.FindOneAndReplaceOptions;
3031
import com.mongodb.client.model.FindOneAndUpdateOptions;
32+
import com.mongodb.client.model.InsertOneModel;
3133
import com.mongodb.client.model.ReturnDocument;
34+
import com.mongodb.client.model.UpdateManyModel;
35+
import com.mongodb.client.model.UpdateOneModel;
3236
import com.mongodb.client.model.UpdateOptions;
37+
import com.mongodb.client.model.WriteModel;
3338
import com.mongodb.client.result.DeleteResult;
3439
import com.mongodb.client.result.UpdateResult;
3540
import org.bson.BsonArray;
@@ -98,7 +103,16 @@ public void shouldPassAllOutcomes() {
98103
BsonDocument outcome = getOperationMongoOperations(definition.getDocument("operation"));
99104
BsonDocument expectedOutcome = definition.getDocument("outcome");
100105

101-
assertEquals(description, expectedOutcome.get("result"), outcome.get("result"));
106+
// Hack to workaround the lack of upsertedCount
107+
BsonValue expectedResult = expectedOutcome.get("result");
108+
BsonValue actualResult = outcome.get("result");
109+
if (actualResult.isDocument()
110+
&& actualResult.asDocument().containsKey("upsertedCount")
111+
&& actualResult.asDocument().getNumber("upsertedCount").intValue() == 0
112+
&& !expectedResult.asDocument().containsKey("upsertedCount")) {
113+
expectedResult.asDocument().append("upsertedCount", actualResult.asDocument().get("upsertedCount"));
114+
}
115+
assertEquals(description, expectedResult, actualResult);
102116

103117
if (expectedOutcome.containsKey("collection")) {
104118
assertCollectionEquals(expectedOutcome.getDocument("collection"));
@@ -170,6 +184,8 @@ private BsonDocument convertMongoOperationToResult(final Object result) {
170184
return toResult(BsonNull.VALUE);
171185
} else if (result instanceof MongoOperationBsonDocument) {
172186
return toResult((MongoOperationBsonDocument) result);
187+
} else if (result instanceof MongoOperationBulkWriteResult) {
188+
return toResult((MongoOperationBulkWriteResult) result);
173189
} else if (result instanceof MongoOperationUpdateResult) {
174190
return toResult((MongoOperationUpdateResult) result);
175191
} else if (result instanceof MongoOperationDeleteResult) {
@@ -226,6 +242,23 @@ private BsonDocument toResult(final MongoOperationUpdateResult operation) {
226242
return toResult(resultDoc);
227243
}
228244

245+
private BsonDocument toResult(final MongoOperationBulkWriteResult operation) {
246+
BulkWriteResult bulkWriteResult = operation.get();
247+
BsonDocument resultDoc = new BsonDocument();
248+
if (bulkWriteResult.wasAcknowledged()) {
249+
resultDoc.append("deletedCount", new BsonInt32(bulkWriteResult.getDeletedCount()));
250+
resultDoc.append("insertedIds", new BsonDocument());
251+
resultDoc.append("matchedCount", new BsonInt32(bulkWriteResult.getMatchedCount()));
252+
if (bulkWriteResult.isModifiedCountAvailable()) {
253+
resultDoc.append("modifiedCount", new BsonInt32(bulkWriteResult.getModifiedCount()));
254+
}
255+
resultDoc.append("upsertedCount", bulkWriteResult.getUpserts() == null
256+
? new BsonInt32(0) : new BsonInt32(bulkWriteResult.getUpserts().size()));
257+
resultDoc.append("upsertedIds", new BsonDocument());
258+
}
259+
return toResult(resultDoc);
260+
}
261+
229262
private BsonDocument toResult(final MongoOperationDeleteResult operation) {
230263
DeleteResult deleteResult = operation.get();
231264
return toResult(new BsonDocument("deletedCount", new BsonInt32((int) deleteResult.getDeletedCount())));
@@ -401,6 +434,9 @@ public void execute() {
401434
if (arguments.containsKey("collation")) {
402435
options.collation(getCollation(arguments.getDocument("collation")));
403436
}
437+
if (arguments.containsKey("arrayFilters")) {
438+
options.arrayFilters((getArrayFilters(arguments.getArray("arrayFilters"))));
439+
}
404440
collection.findOneAndUpdate(arguments.getDocument("filter"), arguments.getDocument("update"), options, getCallback());
405441
}
406442
};
@@ -479,6 +515,9 @@ public void execute() {
479515
if (arguments.containsKey("collation")) {
480516
options.collation(getCollation(arguments.getDocument("collation")));
481517
}
518+
if (arguments.containsKey("arrayFilters")) {
519+
options.arrayFilters((getArrayFilters(arguments.getArray("arrayFilters"))));
520+
}
482521
collection.updateMany(arguments.getDocument("filter"), arguments.getDocument("update"), options, getCallback());
483522
}
484523
};
@@ -495,11 +534,61 @@ public void execute() {
495534
if (arguments.containsKey("collation")) {
496535
options.collation(getCollation(arguments.getDocument("collation")));
497536
}
537+
if (arguments.containsKey("arrayFilters")) {
538+
options.arrayFilters((getArrayFilters(arguments.getArray("arrayFilters"))));
539+
}
498540
collection.updateOne(arguments.getDocument("filter"), arguments.getDocument("update"), options, getCallback());
499541
}
500542
};
501543
}
502544

545+
private MongoOperationBulkWriteResult getBulkWriteMongoOperation(final BsonDocument arguments) {
546+
return new MongoOperationBulkWriteResult() {
547+
@Override
548+
public void execute() {
549+
List<WriteModel<BsonDocument>> writeModels = new ArrayList<WriteModel<BsonDocument>>();
550+
for (BsonValue bsonValue : arguments.getArray("requests")) {
551+
BsonDocument cur = bsonValue.asDocument();
552+
if (cur.containsKey("name")) {
553+
String name = cur.getString("name").getValue();
554+
BsonDocument requestArguments = cur.getDocument("arguments");
555+
if (name.equals("insertOne")) {
556+
writeModels.add(new InsertOneModel<BsonDocument>(requestArguments.getDocument("document")));
557+
} else if (name.equals("updateOne")) {
558+
writeModels.add(new UpdateOneModel<BsonDocument>(requestArguments.getDocument("filter"),
559+
requestArguments.getDocument("update"),
560+
getUpdateOptions(requestArguments)));
561+
} else if (name.equals("updateMany")) {
562+
writeModels.add(new UpdateManyModel<BsonDocument>(requestArguments.getDocument("filter"),
563+
requestArguments.getDocument("update"),
564+
getUpdateOptions(requestArguments)));
565+
} else {
566+
throw new UnsupportedOperationException("Unsupported write request type");
567+
}
568+
} else {
569+
if (cur.get("insertOne") != null) {
570+
BsonDocument insertOneArguments = cur.getDocument("insertOne");
571+
writeModels.add(new InsertOneModel<BsonDocument>(insertOneArguments.getDocument("document")));
572+
} else if (cur.get("updateOne") != null) {
573+
BsonDocument updateOneArguments = cur.getDocument("updateOne");
574+
writeModels.add(new UpdateOneModel<BsonDocument>(updateOneArguments.getDocument("filter"),
575+
updateOneArguments.getDocument("update"),
576+
getUpdateOptions(updateOneArguments)));
577+
} else if (cur.get("updateMany") != null) {
578+
BsonDocument updateManyArguments = cur.getDocument("updateMany");
579+
writeModels.add(new UpdateManyModel<BsonDocument>(updateManyArguments.getDocument("filter"),
580+
updateManyArguments.getDocument("update"),
581+
getUpdateOptions(updateManyArguments)));
582+
} else {
583+
throw new UnsupportedOperationException("Unsupported write request type");
584+
}
585+
}
586+
}
587+
collection.bulkWrite(writeModels, getCallback());
588+
}
589+
};
590+
}
591+
503592

504593
Collation getCollation(final BsonDocument bsonCollation) {
505594
Collation.Builder builder = Collation.builder();
@@ -536,6 +625,23 @@ Collation getCollation(final BsonDocument bsonCollation) {
536625
return builder.build();
537626
}
538627

628+
private UpdateOptions getUpdateOptions(final BsonDocument requestArguments) {
629+
return new UpdateOptions()
630+
.arrayFilters(getArrayFilters(requestArguments.getArray("arrayFilters", null)));
631+
}
632+
633+
634+
private List<BsonDocument> getArrayFilters(final BsonArray bsonArray) {
635+
if (bsonArray == null) {
636+
return null;
637+
}
638+
List<BsonDocument> arrayFilters = new ArrayList<BsonDocument>(bsonArray.size());
639+
for (BsonValue cur : bsonArray) {
640+
arrayFilters.add(cur.asDocument());
641+
}
642+
return arrayFilters;
643+
}
644+
539645
abstract class MongoOperationLong extends MongoOperation<Long> {
540646
}
541647

@@ -546,6 +652,9 @@ abstract class MongoOperationBsonDocument extends MongoOperation<BsonDocument> {
546652
abstract class MongoOperationUpdateResult extends MongoOperation<UpdateResult> {
547653
}
548654

655+
abstract class MongoOperationBulkWriteResult extends MongoOperation<BulkWriteResult> {
656+
}
657+
549658
abstract class MongoOperationDeleteResult extends MongoOperation<DeleteResult> {
550659
}
551660

0 commit comments

Comments
 (0)