40
40
import com .mongodb .operation .OperationHelper .CallableWithConnectionAndSource ;
41
41
import org .bson .BsonBoolean ;
42
42
import org .bson .BsonDocument ;
43
+ import org .bson .BsonDocumentReader ;
43
44
import org .bson .BsonInt32 ;
44
45
import org .bson .BsonInt64 ;
45
46
import org .bson .BsonString ;
46
47
import org .bson .BsonValue ;
47
48
import org .bson .codecs .BsonDocumentCodec ;
48
49
import org .bson .codecs .Decoder ;
50
+ import org .bson .codecs .DecoderContext ;
49
51
52
+ import java .util .Collections ;
50
53
import java .util .HashMap ;
51
54
import java .util .List ;
52
55
import java .util .Map ;
65
68
import static com .mongodb .operation .OperationHelper .cursorDocumentToQueryResult ;
66
69
import static com .mongodb .operation .OperationHelper .releasingCallback ;
67
70
import static com .mongodb .operation .OperationHelper .serverIsAtLeastVersionThreeDotTwo ;
68
- import static com .mongodb .operation .OperationHelper .serverIsAtLeastVersionThreeDotZero ;
69
71
import static com .mongodb .operation .OperationHelper .withConnection ;
70
72
71
73
/**
@@ -482,7 +484,8 @@ public BatchCursor<T> execute(final ReadBinding binding) {
482
484
public BatchCursor <T > call (final ConnectionSource source , final Connection connection ) {
483
485
if (serverIsAtLeastVersionThreeDotTwo (connection .getDescription ())) {
484
486
try {
485
- return executeWrappedCommandProtocol (binding , namespace .getDatabaseName (), asCommandDocument (),
487
+ return executeWrappedCommandProtocol (binding , namespace .getDatabaseName (),
488
+ wrapInExplainIfNecessary (asCommandDocument ()),
486
489
CommandResultDocumentCodec .create (decoder , FIRST_BATCH ),
487
490
connection , transformer (source , connection ));
488
491
} catch (MongoCommandException e ) {
@@ -518,7 +521,8 @@ public void call(final AsyncConnectionSource source, final AsyncConnection conne
518
521
errorHandlingCallback (callback ).onResult (null , t );
519
522
} else {
520
523
if (serverIsAtLeastVersionThreeDotTwo (connection .getDescription ())) {
521
- executeWrappedCommandProtocolAsync (binding , namespace .getDatabaseName (), asCommandDocument (),
524
+ executeWrappedCommandProtocolAsync (binding , namespace .getDatabaseName (),
525
+ wrapInExplainIfNecessary (asCommandDocument ()),
522
526
CommandResultDocumentCodec .create (decoder , FIRST_BATCH ),
523
527
connection , asyncTransformer (source , connection ),
524
528
releasingCallback (exceptionTransformingCallback (errorHandlingCallback (callback )),
@@ -595,7 +599,7 @@ public BsonDocument call(final ConnectionSource connectionSource, final Connecti
595
599
connectionSource .getServerDescription (),
596
600
connection );
597
601
try {
598
- if (serverIsAtLeastVersionThreeDotZero (connection .getDescription ())) {
602
+ if (serverIsAtLeastVersionThreeDotTwo (connection .getDescription ())) {
599
603
try {
600
604
return new CommandReadOperation <BsonDocument >(getNamespace ().getDatabaseName (),
601
605
new BsonDocument ("explain" , asCommandDocument ()),
@@ -800,6 +804,18 @@ private BsonDocument asCommandDocument() {
800
804
return document ;
801
805
}
802
806
807
+ private BsonDocument wrapInExplainIfNecessary (final BsonDocument findCommandDocument ) {
808
+ if (isExplain ()) {
809
+ return new BsonDocument ("explain" , findCommandDocument );
810
+ } else {
811
+ return findCommandDocument ;
812
+ }
813
+ }
814
+
815
+ private boolean isExplain () {
816
+ return modifiers != null && modifiers .get ("$explain" , BsonBoolean .FALSE ).equals (BsonBoolean .TRUE );
817
+ }
818
+
803
819
private boolean isTailableCursor () {
804
820
return cursorType .isTailable ();
805
821
}
@@ -808,13 +824,12 @@ private boolean isAwaitData() {
808
824
return cursorType == CursorType .TailableAwait ;
809
825
}
810
826
811
- private CommandTransformer <BsonDocument , BatchCursor <T >> transformer (final ConnectionSource source , final Connection
812
- connection ) {
827
+ private CommandTransformer <BsonDocument , BatchCursor <T >> transformer (final ConnectionSource source ,
828
+ final Connection connection ) {
813
829
return new CommandTransformer <BsonDocument , BatchCursor <T >>() {
814
830
@ Override
815
831
public BatchCursor <T > apply (final BsonDocument result , final ServerAddress serverAddress ) {
816
- QueryResult <T > queryResult = cursorDocumentToQueryResult (result .getDocument ("cursor" ),
817
- connection .getDescription ().getServerAddress ());
832
+ QueryResult <T > queryResult = documentToQueryResult (result , serverAddress );
818
833
return new QueryBatchCursor <T >(queryResult , limit , batchSize , getMaxTimeForCursor (), decoder , source , connection );
819
834
}
820
835
};
@@ -825,17 +840,27 @@ private long getMaxTimeForCursor() {
825
840
}
826
841
827
842
private CommandTransformer <BsonDocument , AsyncBatchCursor <T >> asyncTransformer (final AsyncConnectionSource source ,
828
- final AsyncConnection connection ) {
843
+ final AsyncConnection connection ) {
829
844
return new CommandTransformer <BsonDocument , AsyncBatchCursor <T >>() {
830
845
@ Override
831
846
public AsyncBatchCursor <T > apply (final BsonDocument result , final ServerAddress serverAddress ) {
832
- QueryResult <T > queryResult = cursorDocumentToQueryResult (result .getDocument ("cursor" ),
833
- connection .getDescription ().getServerAddress ());
847
+ QueryResult <T > queryResult = documentToQueryResult (result , serverAddress );
834
848
return new AsyncQueryBatchCursor <T >(queryResult , limit , batchSize , getMaxTimeForCursor (), decoder , source , connection );
835
849
}
836
850
};
837
851
}
838
852
853
+ private QueryResult <T > documentToQueryResult (final BsonDocument result , final ServerAddress serverAddress ) {
854
+ QueryResult <T > queryResult ;
855
+ if (isExplain ()) {
856
+ T decodedDocument = decoder .decode (new BsonDocumentReader (result ), DecoderContext .builder ().build ());
857
+ queryResult = new QueryResult <T >(getNamespace (), Collections .singletonList (decodedDocument ), 0 , serverAddress );
858
+ } else {
859
+ queryResult = cursorDocumentToQueryResult (result .getDocument ("cursor" ), serverAddress );
860
+ }
861
+ return queryResult ;
862
+ }
863
+
839
864
private static class ExplainResultCallback implements SingleResultCallback <AsyncBatchCursor <BsonDocument >> {
840
865
private final SingleResultCallback <BsonDocument > callback ;
841
866
0 commit comments