/driver-core/src/main/com/mongodb/internal/operation/EstimatedDocumentCountOperation.java

https://github.com/jyemin/mongo-java-driver · Java · 127 lines · 96 code · 16 blank · 15 comment · 4 complexity · 167e7ec11be5cebf8af24ed13405e6d1 MD5 · raw file

  1. /*
  2. * Copyright 2008-present MongoDB, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.mongodb.internal.operation;
  17. import com.mongodb.MongoCommandException;
  18. import com.mongodb.MongoNamespace;
  19. import com.mongodb.connection.ConnectionDescription;
  20. import com.mongodb.internal.async.SingleResultCallback;
  21. import com.mongodb.internal.binding.AsyncReadBinding;
  22. import com.mongodb.internal.binding.ReadBinding;
  23. import com.mongodb.internal.operation.CommandOperationHelper.CommandReadTransformer;
  24. import com.mongodb.internal.operation.CommandOperationHelper.CommandReadTransformerAsync;
  25. import com.mongodb.internal.session.SessionContext;
  26. import com.mongodb.lang.Nullable;
  27. import org.bson.BsonDocument;
  28. import org.bson.BsonString;
  29. import org.bson.BsonValue;
  30. import org.bson.codecs.BsonDocumentCodec;
  31. import org.bson.codecs.Decoder;
  32. import java.util.concurrent.TimeUnit;
  33. import static com.mongodb.assertions.Assertions.notNull;
  34. import static com.mongodb.internal.operation.CommandOperationHelper.CommandCreator;
  35. import static com.mongodb.internal.operation.CommandOperationHelper.executeRetryableRead;
  36. import static com.mongodb.internal.operation.CommandOperationHelper.executeRetryableReadAsync;
  37. import static com.mongodb.internal.operation.CommandOperationHelper.isNamespaceError;
  38. import static com.mongodb.internal.operation.CommandOperationHelper.rethrowIfNotNamespaceError;
  39. import static com.mongodb.internal.operation.DocumentHelper.putIfNotZero;
  40. import static com.mongodb.internal.operation.OperationHelper.validateReadConcern;
  41. import static com.mongodb.internal.operation.OperationReadConcernHelper.appendReadConcernToCommand;
  42. import static java.util.Collections.singletonList;
  43. public class EstimatedDocumentCountOperation implements AsyncReadOperation<Long>, ReadOperation<Long> {
  44. private static final Decoder<BsonDocument> DECODER = new BsonDocumentCodec();
  45. private final MongoNamespace namespace;
  46. private boolean retryReads;
  47. private long maxTimeMS;
  48. private BsonValue comment;
  49. public EstimatedDocumentCountOperation(final MongoNamespace namespace) {
  50. this.namespace = notNull("namespace", namespace);
  51. }
  52. public EstimatedDocumentCountOperation retryReads(final boolean retryReads) {
  53. this.retryReads = retryReads;
  54. return this;
  55. }
  56. public EstimatedDocumentCountOperation maxTime(final long maxTime, final TimeUnit timeUnit) {
  57. notNull("timeUnit", timeUnit);
  58. this.maxTimeMS = TimeUnit.MILLISECONDS.convert(maxTime, timeUnit);
  59. return this;
  60. }
  61. @Nullable
  62. public BsonValue getComment() {
  63. return comment;
  64. }
  65. public EstimatedDocumentCountOperation comment(@Nullable final BsonValue comment) {
  66. this.comment = comment;
  67. return this;
  68. }
  69. @Override
  70. public Long execute(final ReadBinding binding) {
  71. try {
  72. return executeRetryableRead(binding, namespace.getDatabaseName(), getCommandCreator(binding.getSessionContext()),
  73. CommandResultDocumentCodec.create(DECODER, singletonList("firstBatch")), transformer(), retryReads);
  74. } catch (MongoCommandException e) {
  75. return rethrowIfNotNamespaceError(e, 0L);
  76. }
  77. }
  78. @Override
  79. public void executeAsync(final AsyncReadBinding binding, final SingleResultCallback<Long> callback) {
  80. executeRetryableReadAsync(binding, namespace.getDatabaseName(), getCommandCreator(binding.getSessionContext()),
  81. CommandResultDocumentCodec.create(DECODER, singletonList("firstBatch")), asyncTransformer(), retryReads,
  82. (result, t) -> {
  83. if (isNamespaceError(t)) {
  84. callback.onResult(0L, null);
  85. } else {
  86. callback.onResult(result, t);
  87. }
  88. });
  89. }
  90. private CommandReadTransformer<BsonDocument, Long> transformer() {
  91. return (result, source, connection) -> transformResult(result, connection.getDescription());
  92. }
  93. private CommandReadTransformerAsync<BsonDocument, Long> asyncTransformer() {
  94. return (result, source, connection) -> transformResult(result, connection.getDescription());
  95. }
  96. private long transformResult(final BsonDocument result, final ConnectionDescription connectionDescription) {
  97. return (result.getNumber("n")).longValue();
  98. }
  99. private CommandCreator getCommandCreator(final SessionContext sessionContext) {
  100. return (serverDescription, connectionDescription) -> {
  101. validateReadConcern(connectionDescription, sessionContext.getReadConcern());
  102. BsonDocument document = new BsonDocument("count", new BsonString(namespace.getCollectionName()));
  103. appendReadConcernToCommand(sessionContext, connectionDescription.getMaxWireVersion(), document);
  104. putIfNotZero(document, "maxTimeMS", maxTimeMS);
  105. if (comment != null) {
  106. document.put("comment", comment);
  107. }
  108. return document;
  109. };
  110. }
  111. }