mongo 1.12.5 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CONTRIBUTING.md +64 -0
- data/LICENSE +1 -1
- data/README.md +21 -126
- data/Rakefile +39 -21
- data/bin/mongo_console +6 -38
- data/lib/mongo/address/ipv4.rb +85 -0
- data/lib/mongo/address/ipv6.rb +85 -0
- data/lib/mongo/address/unix.rb +76 -0
- data/lib/mongo/address.rb +111 -0
- data/lib/mongo/auth/cr/conversation.rb +119 -0
- data/lib/mongo/auth/cr.rb +44 -0
- data/lib/mongo/auth/executable.rb +52 -0
- data/lib/mongo/auth/ldap/conversation.rb +92 -0
- data/lib/mongo/auth/ldap.rb +48 -0
- data/lib/mongo/auth/roles.rb +104 -0
- data/lib/mongo/auth/scram/conversation.rb +450 -0
- data/lib/mongo/auth/scram.rb +53 -0
- data/lib/mongo/auth/user/view.rb +102 -0
- data/lib/mongo/auth/user.rb +159 -0
- data/lib/mongo/auth/x509/conversation.rb +92 -0
- data/lib/mongo/auth/x509.rb +48 -0
- data/lib/mongo/auth.rb +108 -0
- data/lib/mongo/bulk_write/bulk_writable.rb +191 -0
- data/lib/mongo/bulk_write/deletable.rb +60 -0
- data/lib/mongo/bulk_write/insertable.rb +52 -0
- data/lib/mongo/bulk_write/ordered_bulk_write.rb +48 -0
- data/lib/mongo/bulk_write/replacable.rb +57 -0
- data/lib/mongo/bulk_write/unordered_bulk_write.rb +46 -0
- data/lib/mongo/bulk_write/updatable.rb +68 -0
- data/lib/mongo/bulk_write.rb +52 -0
- data/lib/mongo/client.rb +246 -0
- data/lib/mongo/cluster/topology/replica_set.rb +160 -0
- data/lib/mongo/cluster/topology/sharded.rb +132 -0
- data/lib/mongo/cluster/topology/standalone.rb +132 -0
- data/lib/mongo/cluster/topology/unknown.rb +155 -0
- data/lib/mongo/cluster/topology.rb +60 -0
- data/lib/mongo/cluster.rb +203 -0
- data/lib/mongo/collection/view/aggregation.rb +108 -0
- data/lib/mongo/collection/view/explainable.rb +49 -0
- data/lib/mongo/collection/view/immutable.rb +43 -0
- data/lib/mongo/collection/view/iterable.rb +48 -0
- data/lib/mongo/collection/view/map_reduce.rb +191 -0
- data/lib/mongo/collection/view/readable.rb +363 -0
- data/lib/mongo/collection/view/writable.rb +185 -0
- data/lib/mongo/collection/view.rb +169 -0
- data/lib/mongo/collection.rb +130 -1101
- data/lib/mongo/cursor.rb +78 -681
- data/lib/mongo/database/view.rb +101 -0
- data/lib/mongo/database.rb +224 -0
- data/lib/mongo/error/bulk_write_error.rb +41 -0
- data/lib/mongo/error/invalid_bulk_operation.rb +36 -0
- data/lib/mongo/error/invalid_bulk_operation_type.rb +36 -0
- data/lib/mongo/error/invalid_collection_name.rb +39 -0
- data/lib/mongo/error/invalid_database_name.rb +39 -0
- data/{test/replica_set/ssl_test.rb → lib/mongo/error/invalid_document.rb} +21 -14
- data/lib/mongo/error/invalid_file.rb +38 -0
- data/lib/mongo/error/invalid_nonce.rb +46 -0
- data/lib/mongo/error/invalid_replacement_document.rb +39 -0
- data/lib/mongo/error/invalid_signature.rb +47 -0
- data/{test/functional/ssl_test.rb → lib/mongo/error/invalid_update_document.rb} +22 -12
- data/lib/mongo/error/max_bson_size.rb +40 -0
- data/lib/mongo/error/max_message_size.rb +42 -0
- data/{test/functional/db_connection_test.rb → lib/mongo/error/multi_index_drop.rb} +17 -8
- data/lib/mongo/{utils.rb → error/need_primary_server.rb} +10 -6
- data/lib/mongo/{connection.rb → error/operation_failure.rb} +10 -6
- data/lib/mongo/error/parser.rb +77 -0
- data/lib/mongo/{connection/socket.rb → error/socket_error.rb} +10 -5
- data/lib/mongo/error/socket_timeout_error.rb +23 -0
- data/lib/mongo/error/unsupported_features.rb +43 -0
- data/lib/mongo/error.rb +82 -0
- data/lib/mongo/event/listeners.rb +63 -0
- data/lib/mongo/event/primary_elected.rb +53 -0
- data/lib/mongo/event/publisher.rb +42 -0
- data/lib/mongo/event/server_added.rb +53 -0
- data/lib/mongo/event/server_removed.rb +53 -0
- data/lib/mongo/event/subscriber.rb +41 -0
- data/lib/mongo/event.rb +40 -0
- data/lib/mongo/grid/file/chunk.rb +184 -0
- data/lib/mongo/grid/file/metadata.rb +229 -0
- data/lib/mongo/grid/file.rb +106 -0
- data/lib/mongo/grid/fs.rb +149 -0
- data/lib/mongo/{gridfs.rb → grid.rb} +3 -5
- data/lib/mongo/index/view.rb +261 -0
- data/lib/mongo/index.rb +64 -0
- data/lib/mongo/loggable.rb +126 -0
- data/lib/mongo/logger.rb +132 -0
- data/lib/mongo/operation/aggregate/result.rb +88 -0
- data/lib/mongo/operation/aggregate.rb +100 -0
- data/lib/mongo/operation/command.rb +62 -0
- data/lib/mongo/operation/executable.rb +105 -0
- data/lib/mongo/operation/kill_cursors.rb +39 -0
- data/lib/mongo/operation/limited.rb +37 -0
- data/lib/mongo/operation/list_collections/result.rb +114 -0
- data/lib/mongo/operation/list_indexes/result.rb +118 -0
- data/lib/mongo/operation/map_reduce/result.rb +122 -0
- data/lib/mongo/operation/map_reduce.rb +96 -0
- data/lib/mongo/operation/read/collections_info.rb +67 -0
- data/lib/mongo/operation/read/get_more.rb +71 -0
- data/lib/mongo/operation/read/indexes.rb +68 -0
- data/lib/mongo/operation/read/list_collections.rb +75 -0
- data/lib/mongo/operation/read/list_indexes.rb +77 -0
- data/lib/mongo/operation/read/query.rb +71 -0
- data/lib/mongo/{functional.rb → operation/read.rb} +7 -7
- data/lib/mongo/operation/read_preferrable.rb +34 -0
- data/lib/mongo/operation/result.rb +259 -0
- data/lib/mongo/operation/specifiable.rb +397 -0
- data/lib/mongo/operation/write/bulk/bulk_delete/result.rb +75 -0
- data/lib/mongo/operation/write/bulk/bulk_delete.rb +144 -0
- data/lib/mongo/operation/write/bulk/bulk_insert/result.rb +68 -0
- data/lib/mongo/operation/write/bulk/bulk_insert.rb +129 -0
- data/lib/mongo/operation/write/bulk/bulk_mergable.rb +67 -0
- data/lib/mongo/operation/write/bulk/bulk_update/result.rb +162 -0
- data/lib/mongo/operation/write/bulk/bulk_update.rb +153 -0
- data/lib/mongo/operation/write/bulk/legacy_bulk_mergable.rb +83 -0
- data/lib/mongo/operation/write/bulk.rb +17 -0
- data/lib/mongo/operation/write/command/create_index.rb +50 -0
- data/lib/mongo/operation/write/command/create_user.rb +43 -0
- data/lib/mongo/operation/write/command/delete.rb +56 -0
- data/lib/mongo/operation/write/command/drop_index.rb +51 -0
- data/lib/mongo/operation/write/command/insert.rb +55 -0
- data/lib/mongo/operation/write/command/remove_user.rb +42 -0
- data/lib/mongo/operation/write/command/update.rb +60 -0
- data/lib/mongo/operation/write/command/writable.rb +61 -0
- data/lib/mongo/operation/write/command.rb +22 -0
- data/lib/mongo/operation/write/create_index.rb +89 -0
- data/lib/mongo/operation/write/create_user.rb +75 -0
- data/lib/mongo/operation/write/delete/result.rb +40 -0
- data/lib/mongo/operation/write/delete.rb +93 -0
- data/lib/mongo/operation/write/drop_index.rb +62 -0
- data/lib/mongo/{utils/thread_local_variable_manager.rb → operation/write/insert/result.rb} +15 -8
- data/lib/mongo/operation/write/insert.rb +90 -0
- data/lib/mongo/operation/write/remove_user.rb +70 -0
- data/lib/mongo/operation/write/update/result.rb +160 -0
- data/lib/mongo/operation/write/update.rb +103 -0
- data/lib/mongo/{connection/socket/socket_util.rb → operation/write.rb} +10 -24
- data/lib/mongo/operation.rb +25 -0
- data/lib/mongo/options/mapper.rb +78 -0
- data/lib/mongo/options.rb +15 -0
- data/lib/mongo/protocol/bit_vector.rb +61 -0
- data/lib/mongo/protocol/delete.rb +94 -0
- data/lib/mongo/protocol/get_more.rb +99 -0
- data/lib/mongo/protocol/insert.rb +99 -0
- data/lib/mongo/protocol/kill_cursors.rb +74 -0
- data/lib/mongo/protocol/message.rb +252 -0
- data/lib/mongo/protocol/query.rb +147 -0
- data/lib/mongo/protocol/reply.rb +72 -0
- data/lib/mongo/protocol/serializers.rb +180 -0
- data/lib/mongo/protocol/update.rb +111 -0
- data/lib/mongo/protocol.rb +15 -0
- data/lib/mongo/server/connectable.rb +110 -0
- data/lib/mongo/server/connection.rb +134 -0
- data/lib/mongo/server/connection_pool/queue.rb +182 -0
- data/lib/mongo/server/connection_pool.rb +141 -0
- data/lib/mongo/server/context.rb +66 -0
- data/lib/mongo/server/description/features.rb +85 -0
- data/lib/mongo/server/description/inspector/primary_elected.rb +58 -0
- data/lib/mongo/server/description/inspector/server_added.rb +59 -0
- data/lib/mongo/server/description/inspector/server_removed.rb +59 -0
- data/lib/mongo/server/description/inspector.rb +79 -0
- data/lib/mongo/server/description.rb +450 -0
- data/lib/mongo/server/monitor/connection.rb +89 -0
- data/lib/mongo/server/monitor.rb +176 -0
- data/lib/mongo/server.rb +163 -0
- data/lib/mongo/server_selector/nearest.rb +94 -0
- data/lib/mongo/server_selector/primary.rb +88 -0
- data/lib/mongo/server_selector/primary_preferred.rb +94 -0
- data/lib/mongo/server_selector/secondary.rb +91 -0
- data/lib/mongo/server_selector/secondary_preferred.rb +96 -0
- data/lib/mongo/server_selector/selectable.rb +209 -0
- data/lib/mongo/server_selector.rb +81 -0
- data/lib/mongo/socket/ssl.rb +130 -0
- data/lib/mongo/socket/tcp.rb +69 -0
- data/lib/mongo/socket/unix.rb +64 -0
- data/lib/mongo/socket.rb +179 -0
- data/lib/mongo/uri.rb +504 -0
- data/lib/mongo/version.rb +21 -0
- data/lib/mongo/write_concern/acknowledged.rb +52 -0
- data/lib/mongo/write_concern/normalizable.rb +51 -0
- data/lib/mongo/write_concern/unacknowledged.rb +55 -0
- data/lib/mongo/write_concern.rb +99 -0
- data/lib/mongo.rb +24 -82
- data/mongo.gemspec +17 -14
- data/spec/certificates/ca.pem +17 -0
- data/spec/certificates/client.pem +101 -0
- data/spec/certificates/crl.pem +10 -0
- data/spec/certificates/crl_client_revoked.pem +12 -0
- data/spec/certificates/password_protected.pem +51 -0
- data/spec/certificates/server.pem +34 -0
- data/spec/mongo/address/ipv4_spec.rb +74 -0
- data/spec/mongo/address/ipv6_spec.rb +74 -0
- data/spec/mongo/address/unix_spec.rb +30 -0
- data/spec/mongo/address_spec.rb +206 -0
- data/spec/mongo/auth/cr_spec.rb +59 -0
- data/spec/mongo/auth/ldap_spec.rb +40 -0
- data/spec/mongo/auth/scram/conversation_spec.rb +197 -0
- data/spec/mongo/auth/scram_spec.rb +55 -0
- data/spec/mongo/auth/user/view_spec.rb +76 -0
- data/spec/mongo/auth/user_spec.rb +190 -0
- data/spec/mongo/auth/x509_spec.rb +40 -0
- data/spec/mongo/auth_spec.rb +65 -0
- data/spec/mongo/bulk/bulk_write_spec.rb +262 -0
- data/spec/mongo/client_spec.rb +564 -0
- data/spec/mongo/cluster/topology/replica_set_spec.rb +101 -0
- data/spec/mongo/cluster/topology/sharded_spec.rb +74 -0
- data/spec/mongo/cluster/topology/standalone_spec.rb +79 -0
- data/spec/mongo/cluster/topology_spec.rb +65 -0
- data/spec/mongo/cluster_spec.rb +129 -0
- data/spec/mongo/collection/view/aggregation_spec.rb +148 -0
- data/spec/mongo/collection/view/explainable_spec.rb +32 -0
- data/spec/mongo/collection/view/map_reduce_spec.rb +242 -0
- data/spec/mongo/collection/view/readable_spec.rb +603 -0
- data/spec/mongo/collection/view/writable_spec.rb +679 -0
- data/spec/mongo/collection/view_spec.rb +530 -0
- data/spec/mongo/collection_spec.rb +362 -0
- data/spec/mongo/crud_spec.rb +42 -0
- data/spec/mongo/cursor_spec.rb +295 -0
- data/spec/mongo/database_spec.rb +302 -0
- data/spec/mongo/error/parser_spec.rb +119 -0
- data/spec/mongo/event/publisher_spec.rb +50 -0
- data/spec/mongo/event/subscriber_spec.rb +34 -0
- data/spec/mongo/grid/file/chunk_spec.rb +226 -0
- data/spec/mongo/grid/file/metadata_spec.rb +92 -0
- data/spec/mongo/grid/file_spec.rb +172 -0
- data/spec/mongo/grid/fs_spec.rb +129 -0
- data/spec/mongo/index/view_spec.rb +330 -0
- data/spec/mongo/loggable_spec.rb +62 -0
- data/spec/mongo/logger_spec.rb +97 -0
- data/spec/mongo/operation/aggregate/result_spec.rb +80 -0
- data/spec/mongo/operation/aggregate_spec.rb +127 -0
- data/spec/mongo/operation/command_spec.rb +98 -0
- data/spec/mongo/operation/kill_cursors_spec.rb +66 -0
- data/spec/mongo/operation/limited_spec.rb +50 -0
- data/spec/mongo/operation/map_reduce_spec.rb +143 -0
- data/spec/mongo/operation/read/collections_info_spec.rb +40 -0
- data/spec/mongo/operation/read/get_more_spec.rb +81 -0
- data/spec/mongo/operation/read/indexes_spec.rb +31 -0
- data/spec/mongo/operation/read/query_spec.rb +84 -0
- data/spec/mongo/operation/result_spec.rb +275 -0
- data/spec/mongo/operation/specifiable_spec.rb +53 -0
- data/spec/mongo/operation/write/bulk_delete_spec.rb +235 -0
- data/spec/mongo/operation/write/bulk_insert_spec.rb +235 -0
- data/spec/mongo/operation/write/bulk_update_spec.rb +236 -0
- data/spec/mongo/operation/write/command/delete_spec.rb +103 -0
- data/spec/mongo/operation/write/command/insert_spec.rb +103 -0
- data/spec/mongo/operation/write/command/update_spec.rb +109 -0
- data/spec/mongo/operation/write/create_index_spec.rb +63 -0
- data/spec/mongo/operation/write/create_user_spec.rb +44 -0
- data/spec/mongo/operation/write/delete_spec.rb +186 -0
- data/spec/mongo/operation/write/drop_index_spec.rb +51 -0
- data/spec/mongo/operation/write/insert_spec.rb +244 -0
- data/spec/mongo/operation/write/remove_user_spec.rb +46 -0
- data/spec/mongo/operation/write/response_spec.rb +85 -0
- data/spec/mongo/operation/write/update_spec.rb +228 -0
- data/spec/mongo/protocol/delete_spec.rb +167 -0
- data/spec/mongo/protocol/get_more_spec.rb +146 -0
- data/spec/mongo/protocol/insert_spec.rb +161 -0
- data/spec/mongo/protocol/kill_cursors_spec.rb +101 -0
- data/spec/mongo/protocol/query_spec.rb +285 -0
- data/spec/mongo/protocol/reply_spec.rb +157 -0
- data/spec/mongo/protocol/update_spec.rb +186 -0
- data/spec/mongo/server/connection_pool/queue_spec.rb +170 -0
- data/spec/mongo/server/connection_pool_spec.rb +120 -0
- data/spec/mongo/server/connection_spec.rb +312 -0
- data/spec/mongo/server/description/features_spec.rb +138 -0
- data/spec/mongo/server/description/inspector/primary_elected_spec.rb +94 -0
- data/spec/mongo/server/description/inspector/server_added_spec.rb +92 -0
- data/spec/mongo/server/description/inspector/server_removed_spec.rb +95 -0
- data/spec/mongo/server/description_spec.rb +510 -0
- data/spec/mongo/server/monitor_spec.rb +144 -0
- data/spec/mongo/server_discovery_and_monitoring_spec.rb +103 -0
- data/spec/mongo/server_selection_rtt_spec.rb +104 -0
- data/spec/mongo/server_selection_spec.rb +89 -0
- data/spec/mongo/server_selector/nearest_spec.rb +250 -0
- data/spec/mongo/server_selector/primary_preferred_spec.rb +290 -0
- data/spec/mongo/server_selector/primary_spec.rb +114 -0
- data/spec/mongo/server_selector/secondary_preferred_spec.rb +252 -0
- data/spec/mongo/server_selector/secondary_spec.rb +196 -0
- data/spec/mongo/server_selector_spec.rb +101 -0
- data/spec/mongo/server_spec.rb +131 -0
- data/spec/mongo/uri_spec.rb +517 -0
- data/spec/mongo/write_concern/acknowledged_spec.rb +44 -0
- data/spec/mongo/write_concern/unacknowledged_spec.rb +15 -0
- data/spec/spec_helper.rb +133 -0
- data/spec/support/authorization.rb +247 -0
- data/spec/support/crud/read.rb +144 -0
- data/spec/support/crud/write.rb +214 -0
- data/spec/support/crud.rb +203 -0
- data/spec/support/crud_tests/read/aggregate.yml +43 -0
- data/spec/support/crud_tests/read/count.yml +37 -0
- data/spec/support/crud_tests/read/distinct.yml +33 -0
- data/spec/support/crud_tests/read/find.yml +50 -0
- data/spec/support/crud_tests/write/deleteMany.yml +36 -0
- data/spec/support/crud_tests/write/deleteOne.yml +49 -0
- data/spec/support/crud_tests/write/findOneAndDelete.yml +54 -0
- data/spec/support/crud_tests/write/findOneAndReplace.yml +153 -0
- data/spec/support/crud_tests/write/findOneAndUpdate.yml +161 -0
- data/spec/support/crud_tests/write/insertMany.yml +24 -0
- data/spec/support/crud_tests/write/insertOne.yml +19 -0
- data/spec/support/crud_tests/write/replaceOne.yml +96 -0
- data/spec/support/crud_tests/write/updateMany.yml +83 -0
- data/spec/support/crud_tests/write/updateOne.yml +80 -0
- data/spec/support/helpers.rb +140 -0
- data/spec/support/matchers.rb +37 -0
- data/spec/support/sdam/rs/discover_arbiters.yml +41 -0
- data/spec/support/sdam/rs/discover_passives.yml +41 -0
- data/spec/support/sdam/rs/discover_primary.yml +40 -0
- data/spec/support/sdam/rs/discover_secondary.yml +41 -0
- data/spec/support/sdam/rs/discovery.yml +195 -0
- data/spec/support/sdam/rs/ghost_discovered.yml +39 -0
- data/spec/support/sdam/rs/hosts_differ_from_seeds.yml +34 -0
- data/spec/support/sdam/rs/member_reconfig.yml +68 -0
- data/spec/support/sdam/rs/member_standalone.yml +60 -0
- data/spec/support/sdam/rs/new_primary.yml +74 -0
- data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +71 -0
- data/spec/support/sdam/rs/non_rs_member.yml +31 -0
- data/spec/support/sdam/rs/normalize_case.yml +49 -0
- data/spec/support/sdam/rs/primary_becomes_standalone.yml +52 -0
- data/spec/support/sdam/rs/primary_changes_set_name.yml +57 -0
- data/spec/support/sdam/rs/primary_disconnect.yml +56 -0
- data/spec/support/sdam/rs/primary_wrong_set_name.yml +27 -0
- data/spec/support/sdam/rs/response_from_removed.yml +63 -0
- data/spec/support/sdam/rs/rsother_discovered.yml +41 -0
- data/spec/support/sdam/rs/sec_not_auth.yml +49 -0
- data/spec/support/sdam/rs/secondary_wrong_set_name.yml +28 -0
- data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +69 -0
- data/spec/support/sdam/rs/unexpected_mongos.yml +26 -0
- data/spec/support/sdam/rs/wrong_set_name.yml +35 -0
- data/spec/support/sdam/sharded/multiple_mongoses.yml +46 -0
- data/spec/support/sdam/sharded/non_mongos_removed.yml +41 -0
- data/spec/support/sdam/sharded/normalize_uri_case.yml +32 -0
- data/spec/support/sdam/single/direct_connection_external_ip.yml +34 -0
- data/spec/support/sdam/single/direct_connection_mongos.yml +33 -0
- data/spec/support/sdam/single/direct_connection_rsarbiter.yml +35 -0
- data/spec/support/sdam/single/direct_connection_rsprimary.yml +34 -0
- data/spec/support/sdam/single/direct_connection_rssecondary.yml +35 -0
- data/spec/support/sdam/single/direct_connection_slave.yml +32 -0
- data/spec/support/sdam/single/direct_connection_standalone.yml +32 -0
- data/spec/support/sdam/single/not_ok_response.yml +39 -0
- data/spec/support/sdam/single/standalone_removed.yml +32 -0
- data/spec/support/sdam/single/unavailable_seed.yml +28 -0
- data/spec/support/server_discovery_and_monitoring.rb +167 -0
- data/spec/support/server_selection/rtt/first_value.yml +4 -0
- data/spec/support/server_selection/rtt/first_value_zero.yml +4 -0
- data/spec/support/server_selection/rtt/value_test_1.yml +4 -0
- data/spec/support/server_selection/rtt/value_test_2.yml +4 -0
- data/spec/support/server_selection/rtt/value_test_3.yml +4 -0
- data/spec/support/server_selection/rtt/value_test_4.yml +4 -0
- data/spec/support/server_selection/rtt/value_test_5.yml +4 -0
- data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest.yml +26 -0
- data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest_non_matching.yml +21 -0
- data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Primary.yml +21 -0
- data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred.yml +26 -0
- data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred_non_matching.yml +21 -0
- data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary.yml +26 -0
- data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred.yml +26 -0
- data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred_non_matching.yml +21 -0
- data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary_non_matching.yml +21 -0
- data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest.yml +33 -0
- data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest_non_matching.yml +26 -0
- data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Primary.yml +29 -0
- data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred.yml +29 -0
- data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred_non_matching.yml +29 -0
- data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Secondary.yml +31 -0
- data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/SecondaryPreferred.yml +31 -0
- data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/SecondaryPreferred_non_matching.yml +29 -0
- data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Secondary_non_matching.yml +26 -0
- data/spec/support/server_selection/selection/Sharded/read/SecondaryPreferred.yml +26 -0
- data/spec/support/server_selection/selection/Single/read/SecondaryPreferred.yml +19 -0
- data/spec/support/server_selection/selection/Unknown/read/SecondaryPreferred.yml +11 -0
- data/spec/support/server_selection.rb +157 -0
- data/spec/support/server_selection_rtt.rb +41 -0
- data/spec/support/shared/bulk_write.rb +535 -0
- data/spec/support/shared/cursor.rb +38 -0
- data/spec/support/shared/operation.rb +77 -0
- data/spec/support/shared/protocol.rb +31 -0
- data/spec/support/shared/server_selector.rb +111 -0
- data/spec/support/shared/socket.rb +82 -0
- data/spec/support/travis.rb +14 -0
- data.tar.gz.sig +2 -3
- metadata +583 -186
- metadata.gz.sig +0 -0
- data/VERSION +0 -1
- data/lib/mongo/bulk_write_collection_view.rb +0 -387
- data/lib/mongo/collection_writer.rb +0 -364
- data/lib/mongo/connection/node.rb +0 -249
- data/lib/mongo/connection/pool.rb +0 -340
- data/lib/mongo/connection/pool_manager.rb +0 -320
- data/lib/mongo/connection/sharding_pool_manager.rb +0 -67
- data/lib/mongo/connection/socket/ssl_socket.rb +0 -95
- data/lib/mongo/connection/socket/tcp_socket.rb +0 -87
- data/lib/mongo/connection/socket/unix_socket.rb +0 -39
- data/lib/mongo/db.rb +0 -808
- data/lib/mongo/exception.rb +0 -145
- data/lib/mongo/functional/authentication.rb +0 -455
- data/lib/mongo/functional/logging.rb +0 -85
- data/lib/mongo/functional/read_preference.rb +0 -183
- data/lib/mongo/functional/scram.rb +0 -556
- data/lib/mongo/functional/uri_parser.rb +0 -409
- data/lib/mongo/functional/write_concern.rb +0 -66
- data/lib/mongo/gridfs/grid.rb +0 -112
- data/lib/mongo/gridfs/grid_ext.rb +0 -53
- data/lib/mongo/gridfs/grid_file_system.rb +0 -163
- data/lib/mongo/gridfs/grid_io.rb +0 -484
- data/lib/mongo/legacy.rb +0 -140
- data/lib/mongo/mongo_client.rb +0 -697
- data/lib/mongo/mongo_replica_set_client.rb +0 -535
- data/lib/mongo/mongo_sharded_client.rb +0 -159
- data/lib/mongo/networking.rb +0 -372
- data/lib/mongo/utils/conversions.rb +0 -110
- data/lib/mongo/utils/core_ext.rb +0 -70
- data/lib/mongo/utils/server_version.rb +0 -69
- data/lib/mongo/utils/support.rb +0 -80
- data/test/functional/authentication_test.rb +0 -39
- data/test/functional/bulk_api_stress_test.rb +0 -133
- data/test/functional/bulk_write_collection_view_test.rb +0 -1198
- data/test/functional/client_test.rb +0 -627
- data/test/functional/collection_test.rb +0 -2175
- data/test/functional/collection_writer_test.rb +0 -83
- data/test/functional/conversions_test.rb +0 -163
- data/test/functional/cursor_fail_test.rb +0 -57
- data/test/functional/cursor_message_test.rb +0 -56
- data/test/functional/cursor_test.rb +0 -683
- data/test/functional/db_api_test.rb +0 -835
- data/test/functional/db_test.rb +0 -348
- data/test/functional/grid_file_system_test.rb +0 -285
- data/test/functional/grid_io_test.rb +0 -252
- data/test/functional/grid_test.rb +0 -273
- data/test/functional/pool_test.rb +0 -136
- data/test/functional/safe_test.rb +0 -98
- data/test/functional/support_test.rb +0 -62
- data/test/functional/timeout_test.rb +0 -60
- data/test/functional/uri_test.rb +0 -446
- data/test/functional/write_concern_test.rb +0 -118
- data/test/helpers/general.rb +0 -50
- data/test/helpers/test_unit.rb +0 -476
- data/test/replica_set/authentication_test.rb +0 -37
- data/test/replica_set/basic_test.rb +0 -189
- data/test/replica_set/client_test.rb +0 -393
- data/test/replica_set/connection_test.rb +0 -138
- data/test/replica_set/count_test.rb +0 -66
- data/test/replica_set/cursor_test.rb +0 -220
- data/test/replica_set/insert_test.rb +0 -157
- data/test/replica_set/max_values_test.rb +0 -151
- data/test/replica_set/pinning_test.rb +0 -105
- data/test/replica_set/query_test.rb +0 -73
- data/test/replica_set/read_preference_test.rb +0 -219
- data/test/replica_set/refresh_test.rb +0 -211
- data/test/replica_set/replication_ack_test.rb +0 -95
- data/test/sharded_cluster/basic_test.rb +0 -203
- data/test/shared/authentication/basic_auth_shared.rb +0 -260
- data/test/shared/authentication/bulk_api_auth_shared.rb +0 -249
- data/test/shared/authentication/gssapi_shared.rb +0 -176
- data/test/shared/authentication/sasl_plain_shared.rb +0 -96
- data/test/shared/authentication/scram_shared.rb +0 -92
- data/test/shared/ssl_shared.rb +0 -235
- data/test/test_helper.rb +0 -61
- data/test/threading/basic_test.rb +0 -120
- data/test/tools/mongo_config.rb +0 -708
- data/test/tools/mongo_config_test.rb +0 -160
- data/test/unit/client_test.rb +0 -381
- data/test/unit/collection_test.rb +0 -166
- data/test/unit/connection_test.rb +0 -335
- data/test/unit/cursor_test.rb +0 -307
- data/test/unit/db_test.rb +0 -136
- data/test/unit/grid_test.rb +0 -76
- data/test/unit/mongo_sharded_client_test.rb +0 -48
- data/test/unit/node_test.rb +0 -93
- data/test/unit/pool_manager_test.rb +0 -111
- data/test/unit/read_pref_test.rb +0 -406
- data/test/unit/read_test.rb +0 -159
- data/test/unit/safe_test.rb +0 -158
- data/test/unit/sharding_pool_manager_test.rb +0 -84
- data/test/unit/write_concern_test.rb +0 -175
data/lib/mongo/cursor.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C)
|
1
|
+
# Copyright (C) 2014-2015 MongoDB, Inc.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -14,729 +14,126 @@
|
|
14
14
|
|
15
15
|
module Mongo
|
16
16
|
|
17
|
-
#
|
17
|
+
# Client-side representation of an iterator over a query result set on
|
18
|
+
# the server.
|
19
|
+
#
|
20
|
+
# A +Cursor+ is not created directly by a user. Rather, +CollectionView+
|
21
|
+
# creates a +Cursor+ in an Enumerable module method.
|
22
|
+
#
|
23
|
+
# @example Get an array of 5 users named Emily.
|
24
|
+
# users.find({:name => 'Emily'}).limit(5).to_a
|
25
|
+
#
|
26
|
+
# @example Call a block on each user doc.
|
27
|
+
# users.find.each { |doc| puts doc }
|
28
|
+
#
|
29
|
+
# @note The +Cursor+ API is semipublic.
|
30
|
+
# @api semipublic
|
18
31
|
class Cursor
|
32
|
+
extend Forwardable
|
19
33
|
include Enumerable
|
20
|
-
include Mongo::Constants
|
21
|
-
include Mongo::Conversions
|
22
|
-
include Mongo::Logging
|
23
|
-
include Mongo::ReadPreference
|
24
34
|
|
25
|
-
|
26
|
-
|
27
|
-
:options, :cursor_id, :show_disk_loc,
|
28
|
-
:comment, :compile_regex, :read, :tag_sets,
|
29
|
-
:acceptable_latency
|
35
|
+
def_delegators :@view, :collection, :limit
|
36
|
+
def_delegators :collection, :client, :database
|
30
37
|
|
31
|
-
#
|
38
|
+
# Creates a +Cursor+ object.
|
32
39
|
#
|
33
|
-
#
|
34
|
-
#
|
40
|
+
# @example Instantiate the cursor.
|
41
|
+
# Mongo::Cursor.new(view, response, server)
|
35
42
|
#
|
36
|
-
# @
|
37
|
-
|
38
|
-
|
39
|
-
@cursor_id = opts.delete(:cursor_id)
|
40
|
-
@db = collection.db
|
41
|
-
@collection = collection
|
42
|
-
@ns = opts.delete(:ns)
|
43
|
-
@connection = @db.connection
|
44
|
-
@logger = @connection.logger
|
45
|
-
|
46
|
-
# Query selector
|
47
|
-
@selector = opts.delete(:selector) || {}
|
48
|
-
|
49
|
-
# Query pre-serialized bson to append
|
50
|
-
@bson = @selector.delete(:bson)
|
51
|
-
|
52
|
-
# Special operators that form part of $query
|
53
|
-
@order = opts.delete(:order)
|
54
|
-
@explain = opts.delete(:explain)
|
55
|
-
@hint = opts.delete(:hint)
|
56
|
-
@snapshot = opts.delete(:snapshot)
|
57
|
-
@max_scan = opts.delete(:max_scan)
|
58
|
-
@return_key = opts.delete(:return_key)
|
59
|
-
@show_disk_loc = opts.delete(:show_disk_loc)
|
60
|
-
@comment = opts.delete(:comment)
|
61
|
-
@compile_regex = opts.key?(:compile_regex) ? opts.delete(:compile_regex) : true
|
62
|
-
|
63
|
-
# Wire-protocol settings
|
64
|
-
@fields = convert_fields_for_query(opts.delete(:fields))
|
65
|
-
@skip = opts.delete(:skip) || 0
|
66
|
-
@limit = opts.delete(:limit) || 0
|
67
|
-
@tailable = opts.delete(:tailable)
|
68
|
-
@timeout = opts.key?(:timeout) ? opts.delete(:timeout) : true
|
69
|
-
@options = 0
|
70
|
-
|
71
|
-
# Use this socket for the query
|
72
|
-
@socket = opts.delete(:socket)
|
73
|
-
@pool = opts.delete(:pool)
|
74
|
-
|
75
|
-
@closed = false
|
76
|
-
@query_run = false
|
77
|
-
|
78
|
-
@transformer = opts.delete(:transformer)
|
79
|
-
@read = opts.delete(:read) || @collection.read
|
80
|
-
Mongo::ReadPreference::validate(@read)
|
81
|
-
@tag_sets = opts.delete(:tag_sets) || @collection.tag_sets
|
82
|
-
@acceptable_latency = opts.delete(:acceptable_latency) || @collection.acceptable_latency
|
83
|
-
|
84
|
-
batch_size(opts.delete(:batch_size) || 0)
|
85
|
-
|
86
|
-
@cache = opts.delete(:first_batch) || []
|
87
|
-
@returned = 0
|
88
|
-
|
89
|
-
if(!@timeout)
|
90
|
-
add_option(OP_QUERY_NO_CURSOR_TIMEOUT)
|
91
|
-
end
|
92
|
-
if(@read != :primary)
|
93
|
-
add_option(OP_QUERY_SLAVE_OK)
|
94
|
-
end
|
95
|
-
if(@tailable)
|
96
|
-
add_option(OP_QUERY_TAILABLE)
|
97
|
-
end
|
98
|
-
|
99
|
-
# If a cursor_id is provided, this is a cursor for a command
|
100
|
-
if @cursor_id
|
101
|
-
@command_cursor = true
|
102
|
-
@query_run = true
|
103
|
-
end
|
104
|
-
|
105
|
-
if @collection.name =~ /^\$cmd/ || @collection.name =~ /^system/
|
106
|
-
@command = true
|
107
|
-
else
|
108
|
-
@command = false
|
109
|
-
end
|
110
|
-
|
111
|
-
@opts = opts
|
112
|
-
end
|
113
|
-
|
114
|
-
# Guess whether the cursor is alive on the server.
|
43
|
+
# @param [ CollectionView ] view The +CollectionView+ defining the query.
|
44
|
+
# @param [ Operation::Result ] result The result of the first execution.
|
45
|
+
# @param [ Server ] server The server this cursor is locked to.
|
115
46
|
#
|
116
|
-
#
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
def alive?
|
123
|
-
@cursor_id && @cursor_id != 0
|
47
|
+
# @since 2.0.0
|
48
|
+
def initialize(view, result, server)
|
49
|
+
@view = view
|
50
|
+
@server = server
|
51
|
+
@initial_result = result
|
52
|
+
@remaining = limit if limited?
|
124
53
|
end
|
125
54
|
|
126
|
-
|
127
|
-
@ns || "#{@collection.db.name}.#{@collection.name}"
|
128
|
-
end
|
129
|
-
|
130
|
-
# Get the next document specified the cursor options.
|
55
|
+
# Get a human-readable string representation of +Cursor+.
|
131
56
|
#
|
132
|
-
# @
|
133
|
-
|
134
|
-
if @cache.length == 0
|
135
|
-
if @query_run && exhaust?
|
136
|
-
close
|
137
|
-
return nil
|
138
|
-
else
|
139
|
-
refresh
|
140
|
-
end
|
141
|
-
end
|
142
|
-
doc = @cache.shift
|
143
|
-
|
144
|
-
if doc && (err = doc['errmsg'] || doc['$err']) # assignment
|
145
|
-
code = doc['code'] || doc['assertionCode']
|
146
|
-
|
147
|
-
# If the server has stopped being the master (e.g., it's one of a
|
148
|
-
# pair but it has died or something like that) then we close that
|
149
|
-
# connection. The next request will re-open on master server.
|
150
|
-
if err.include?("not master")
|
151
|
-
@connection.close
|
152
|
-
raise ConnectionFailure.new(err, code, doc)
|
153
|
-
end
|
154
|
-
|
155
|
-
# Handle server side operation execution timeout
|
156
|
-
if code == 50
|
157
|
-
raise ExecutionTimeout.new(err, code, doc)
|
158
|
-
end
|
159
|
-
|
160
|
-
raise OperationFailure.new(err, code, doc)
|
161
|
-
elsif doc && (write_concern_error = doc['writeConcernError']) # assignment
|
162
|
-
raise WriteConcernError.new(write_concern_error['errmsg'], write_concern_error['code'], doc)
|
163
|
-
end
|
164
|
-
|
165
|
-
if @transformer.nil?
|
166
|
-
doc
|
167
|
-
else
|
168
|
-
@transformer.call(doc) if doc
|
169
|
-
end
|
170
|
-
end
|
171
|
-
alias :next_document :next
|
172
|
-
|
173
|
-
# Reset this cursor on the server. Cursor options, such as the
|
174
|
-
# query string and the values for skip and limit, are preserved.
|
175
|
-
def rewind!
|
176
|
-
check_command_cursor
|
177
|
-
close
|
178
|
-
@cache.clear
|
179
|
-
@cursor_id = nil
|
180
|
-
@closed = false
|
181
|
-
@query_run = false
|
182
|
-
@n_received = nil
|
183
|
-
true
|
184
|
-
end
|
185
|
-
|
186
|
-
# Determine whether this cursor has any remaining results.
|
187
|
-
#
|
188
|
-
# @return [Boolean]
|
189
|
-
def has_next?
|
190
|
-
num_remaining > 0
|
191
|
-
end
|
192
|
-
|
193
|
-
# Get the size of the result set for this query.
|
57
|
+
# @example Inspect the cursor.
|
58
|
+
# cursor.inspect
|
194
59
|
#
|
195
|
-
# @
|
60
|
+
# @return [ String ] A string representation of a +Cursor+ instance.
|
196
61
|
#
|
197
|
-
# @
|
198
|
-
|
199
|
-
|
200
|
-
def count(skip_and_limit = false)
|
201
|
-
check_command_cursor
|
202
|
-
command = BSON::OrderedHash["count", @collection.name, "query", @selector]
|
203
|
-
|
204
|
-
if skip_and_limit
|
205
|
-
command.merge!(BSON::OrderedHash["limit", @limit]) if @limit != 0
|
206
|
-
command.merge!(BSON::OrderedHash["skip", @skip]) if @skip != 0
|
207
|
-
end
|
208
|
-
|
209
|
-
if @hint
|
210
|
-
hint = @hint.is_a?(String) ? @hint : generate_index_name(@hint)
|
211
|
-
end
|
212
|
-
|
213
|
-
command.merge!(BSON::OrderedHash["fields", @fields])
|
214
|
-
command.merge!(BSON::OrderedHash["hint", hint]) if hint
|
215
|
-
|
216
|
-
response = @db.command(command, :read => @read, :comment => @comment)
|
217
|
-
return response['n'].to_i if Mongo::Support.ok?(response)
|
218
|
-
return 0 if response['errmsg'] == "ns missing"
|
219
|
-
raise OperationFailure.new("Count failed: #{response['errmsg']}", response['code'], response)
|
220
|
-
end
|
221
|
-
|
222
|
-
# Sort this cursor's results.
|
223
|
-
#
|
224
|
-
# This method overrides any sort order specified in the Collection#find
|
225
|
-
# method, and only the last sort applied has an effect.
|
226
|
-
#
|
227
|
-
# @param [Symbol, Array, Hash, OrderedHash] order either 1) a key to sort by 2)
|
228
|
-
# an array of [key, direction] pairs to sort by or 3) a hash of
|
229
|
-
# field => direction pairs to sort by. Direction should be specified as
|
230
|
-
# Mongo::ASCENDING (or :ascending / :asc) or Mongo::DESCENDING
|
231
|
-
# (or :descending / :desc)
|
232
|
-
#
|
233
|
-
# @raise [InvalidOperation] if this cursor has already been used.
|
234
|
-
#
|
235
|
-
# @raise [InvalidSortValueError] if the specified order is invalid.
|
236
|
-
def sort(order, direction=nil)
|
237
|
-
check_modifiable
|
238
|
-
order = [[order, direction]] unless direction.nil?
|
239
|
-
@order = order
|
240
|
-
self
|
241
|
-
end
|
242
|
-
|
243
|
-
# Limit the number of results to be returned by this cursor.
|
244
|
-
#
|
245
|
-
# This method overrides any limit specified in the Collection#find method,
|
246
|
-
# and only the last limit applied has an effect.
|
247
|
-
#
|
248
|
-
# @return [Integer] the current number_to_return if no parameter is given.
|
249
|
-
#
|
250
|
-
# @raise [InvalidOperation] if this cursor has already been used.
|
251
|
-
def limit(number_to_return=nil)
|
252
|
-
return @limit unless number_to_return
|
253
|
-
check_modifiable
|
254
|
-
|
255
|
-
if (number_to_return != 0) && exhaust?
|
256
|
-
raise MongoArgumentError, "Limit is incompatible with exhaust option."
|
257
|
-
end
|
258
|
-
|
259
|
-
@limit = number_to_return
|
260
|
-
self
|
261
|
-
end
|
262
|
-
|
263
|
-
# Skips the first +number_to_skip+ results of this cursor.
|
264
|
-
# Returns the current number_to_skip if no parameter is given.
|
265
|
-
#
|
266
|
-
# This method overrides any skip specified in the Collection#find method,
|
267
|
-
# and only the last skip applied has an effect.
|
268
|
-
#
|
269
|
-
# @return [Integer]
|
270
|
-
#
|
271
|
-
# @raise [InvalidOperation] if this cursor has already been used.
|
272
|
-
def skip(number_to_skip=nil)
|
273
|
-
return @skip unless number_to_skip
|
274
|
-
check_modifiable
|
275
|
-
|
276
|
-
@skip = number_to_skip
|
277
|
-
self
|
278
|
-
end
|
279
|
-
|
280
|
-
# Instruct the server to abort queries after they exceed the specified
|
281
|
-
# wall-clock execution time.
|
282
|
-
#
|
283
|
-
# A query that completes in under its time limit will "roll over"
|
284
|
-
# remaining time to the first getmore op (which will then "roll over"
|
285
|
-
# its remaining time to the second getmore op and so on, until the
|
286
|
-
# time limit is hit).
|
287
|
-
#
|
288
|
-
# Cursors returned by successful time-limited queries will still obey
|
289
|
-
# the default cursor idle timeout (unless the "no cursor idle timeout"
|
290
|
-
# flag has been set).
|
291
|
-
#
|
292
|
-
# @note This will only have an effect in MongoDB 2.5+
|
293
|
-
#
|
294
|
-
# @param max_time_ms [Fixnum] max execution time (in milliseconds)
|
295
|
-
#
|
296
|
-
# @return [Fixnum, Cursor] either the current max_time_ms or cursor
|
297
|
-
def max_time_ms(max_time_ms=nil)
|
298
|
-
return @max_time_ms unless max_time_ms
|
299
|
-
check_modifiable
|
300
|
-
|
301
|
-
@max_time_ms = max_time_ms
|
302
|
-
self
|
303
|
-
end
|
304
|
-
|
305
|
-
# Set the batch size for server responses.
|
306
|
-
#
|
307
|
-
# Note that the batch size will take effect only on queries
|
308
|
-
# where the number to be returned is greater than 100.
|
309
|
-
#
|
310
|
-
# This can not override MongoDB's limit on the amount of data it will
|
311
|
-
# return to the client. Depending on server version this can be 4-16mb.
|
312
|
-
#
|
313
|
-
# @param [Integer] size either 0 or some integer greater than 1. If 0,
|
314
|
-
# the server will determine the batch size.
|
315
|
-
#
|
316
|
-
# @return [Cursor]
|
317
|
-
def batch_size(size=nil)
|
318
|
-
return @batch_size unless size
|
319
|
-
check_modifiable
|
320
|
-
if size < 0 || size == 1
|
321
|
-
raise ArgumentError, "Invalid value for batch_size #{size}; must be 0 or > 1."
|
322
|
-
else
|
323
|
-
@batch_size = @limit != 0 && size > @limit ? @limit : size
|
324
|
-
end
|
325
|
-
|
326
|
-
self
|
62
|
+
# @since 2.0.0
|
63
|
+
def inspect
|
64
|
+
"#<Mongo::Cursor:0x#{object_id} @view=#{@view.inspect}>"
|
327
65
|
end
|
328
66
|
|
329
|
-
# Iterate
|
330
|
-
# block, if provided. An Enumerator is returned if no block is given.
|
331
|
-
#
|
332
|
-
# Iterating over an entire cursor will close it.
|
67
|
+
# Iterate through documents returned from the query.
|
333
68
|
#
|
334
|
-
# @
|
335
|
-
#
|
336
|
-
#
|
337
|
-
# comments.find.each do |doc|
|
338
|
-
# puts doc['user']
|
69
|
+
# @example Iterate over the documents in the cursor.
|
70
|
+
# cursor.each do |doc|
|
71
|
+
# ...
|
339
72
|
# end
|
340
|
-
def each
|
341
|
-
if block_given? || !defined?(Enumerator)
|
342
|
-
while doc = self.next
|
343
|
-
yield doc
|
344
|
-
end
|
345
|
-
else
|
346
|
-
Enumerator.new do |yielder|
|
347
|
-
while doc = self.next
|
348
|
-
yielder.yield doc
|
349
|
-
end
|
350
|
-
end
|
351
|
-
end
|
352
|
-
end
|
353
|
-
# Receive all the documents from this cursor as an array of hashes.
|
354
|
-
#
|
355
|
-
# Notes:
|
356
|
-
#
|
357
|
-
# If you've already started iterating over the cursor, the array returned
|
358
|
-
# by this method contains only the remaining documents. See Cursor#rewind! if you
|
359
|
-
# need to reset the cursor.
|
360
|
-
#
|
361
|
-
# Use of this method is discouraged - in most cases, it's much more
|
362
|
-
# efficient to retrieve documents as you need them by iterating over the cursor.
|
363
|
-
#
|
364
|
-
# @return [Array] an array of documents.
|
365
|
-
def to_a
|
366
|
-
super
|
367
|
-
end
|
368
|
-
|
369
|
-
# Get the explain plan for this cursor.
|
370
|
-
#
|
371
|
-
# @return [Hash] a document containing the explain plan for this cursor.
|
372
|
-
def explain
|
373
|
-
check_command_cursor
|
374
|
-
c = Cursor.new(@collection,
|
375
|
-
query_options_hash.merge(:limit => -@limit.abs, :explain => true))
|
376
|
-
explanation = c.next_document
|
377
|
-
c.close
|
378
|
-
|
379
|
-
explanation
|
380
|
-
end
|
381
|
-
|
382
|
-
# Close the cursor.
|
383
|
-
#
|
384
|
-
# Note: if a cursor is read until exhausted (read until Mongo::Constants::OP_QUERY or
|
385
|
-
# Mongo::Constants::OP_GETMORE returns zero for the cursor id), there is no need to
|
386
|
-
# close it manually.
|
387
|
-
#
|
388
|
-
# Note also: Collection#find takes an optional block argument which can be used to
|
389
|
-
# ensure that your cursors get closed.
|
390
73
|
#
|
391
|
-
# @return [
|
392
|
-
def close
|
393
|
-
if @cursor_id && @cursor_id != 0
|
394
|
-
message = BSON::ByteBuffer.new([0, 0, 0, 0])
|
395
|
-
message.put_int(1)
|
396
|
-
message.put_long(@cursor_id)
|
397
|
-
log(:debug, "Cursor#close #{@cursor_id}")
|
398
|
-
@connection.send_message(
|
399
|
-
Mongo::Constants::OP_KILL_CURSORS,
|
400
|
-
message,
|
401
|
-
:pool => @pool
|
402
|
-
)
|
403
|
-
end
|
404
|
-
@cursor_id = 0
|
405
|
-
@closed = true
|
406
|
-
end
|
407
|
-
|
408
|
-
# Is this cursor closed?
|
74
|
+
# @return [ Enumerator ] The enumerator.
|
409
75
|
#
|
410
|
-
# @
|
411
|
-
def
|
412
|
-
@
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
#
|
417
|
-
# @return [Integer]
|
418
|
-
#
|
419
|
-
# @see http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-Mongo::Constants::OPQUERY
|
420
|
-
# The MongoDB wire protocol.
|
421
|
-
def query_opts
|
422
|
-
warn "The method Cursor#query_opts has been deprecated " +
|
423
|
-
"and will removed in v2.0. Use Cursor#options instead."
|
424
|
-
@options
|
425
|
-
end
|
426
|
-
|
427
|
-
# Add an option to the query options bitfield.
|
428
|
-
#
|
429
|
-
# @param opt a valid query option
|
430
|
-
#
|
431
|
-
# @raise InvalidOperation if this method is run after the cursor has bee
|
432
|
-
# iterated for the first time.
|
433
|
-
#
|
434
|
-
# @return [Integer] the current value of the options bitfield for this cursor.
|
435
|
-
#
|
436
|
-
# @see http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-Mongo::Constants::OPQUERY
|
437
|
-
def add_option(opt)
|
438
|
-
check_modifiable
|
439
|
-
|
440
|
-
if exhaust?(opt)
|
441
|
-
if @limit != 0
|
442
|
-
raise MongoArgumentError, "Exhaust is incompatible with limit."
|
443
|
-
elsif @connection.mongos?
|
444
|
-
raise MongoArgumentError, "Exhaust is incompatible with mongos."
|
445
|
-
end
|
76
|
+
# @since 2.0.0
|
77
|
+
def each
|
78
|
+
process(@initial_result).each { |doc| yield doc }
|
79
|
+
while more?
|
80
|
+
return kill_cursors if exhausted?
|
81
|
+
get_more.each { |doc| yield doc }
|
446
82
|
end
|
447
|
-
|
448
|
-
@options |= opt
|
449
|
-
@options
|
450
|
-
end
|
451
|
-
|
452
|
-
# Remove an option from the query options bitfield.
|
453
|
-
#
|
454
|
-
# @param opt a valid query option
|
455
|
-
#
|
456
|
-
# @raise InvalidOperation if this method is run after the cursor has bee
|
457
|
-
# iterated for the first time.
|
458
|
-
#
|
459
|
-
# @return [Integer] the current value of the options bitfield for this cursor.
|
460
|
-
#
|
461
|
-
# @see http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-Mongo::Constants::OPQUERY
|
462
|
-
def remove_option(opt)
|
463
|
-
check_modifiable
|
464
|
-
|
465
|
-
@options &= ~opt
|
466
|
-
@options
|
467
|
-
end
|
468
|
-
|
469
|
-
# Get the query options for this Cursor.
|
470
|
-
#
|
471
|
-
# @return [Hash]
|
472
|
-
def query_options_hash
|
473
|
-
BSON::OrderedHash[
|
474
|
-
:selector => @selector,
|
475
|
-
:fields => @fields,
|
476
|
-
:skip => @skip,
|
477
|
-
:limit => @limit,
|
478
|
-
:order => @order,
|
479
|
-
:hint => @hint,
|
480
|
-
:snapshot => @snapshot,
|
481
|
-
:timeout => @timeout,
|
482
|
-
:max_scan => @max_scan,
|
483
|
-
:return_key => @return_key,
|
484
|
-
:show_disk_loc => @show_disk_loc,
|
485
|
-
:comment => @comment ]
|
486
|
-
end
|
487
|
-
|
488
|
-
# Clean output for inspect.
|
489
|
-
def inspect
|
490
|
-
"<Mongo::Cursor:0x#{object_id.to_s(16)} namespace='#{full_collection_name}' " +
|
491
|
-
"@selector=#{@selector.inspect} @cursor_id=#{@cursor_id}>"
|
492
83
|
end
|
493
84
|
|
494
85
|
private
|
495
86
|
|
496
|
-
|
497
|
-
|
498
|
-
# value.
|
499
|
-
def convert_fields_for_query(fields)
|
500
|
-
case fields
|
501
|
-
when String, Symbol
|
502
|
-
{fields => 1}
|
503
|
-
when Array
|
504
|
-
return nil if fields.length.zero?
|
505
|
-
fields.inject({}) do |hash, field|
|
506
|
-
field.is_a?(Hash) ? hash.merge!(field) : hash[field] = 1
|
507
|
-
hash
|
508
|
-
end
|
509
|
-
when Hash
|
510
|
-
return fields
|
511
|
-
end
|
512
|
-
end
|
513
|
-
|
514
|
-
# Return the number of documents remaining for this cursor.
|
515
|
-
def num_remaining
|
516
|
-
if @cache.length == 0
|
517
|
-
if @query_run && exhaust?
|
518
|
-
close
|
519
|
-
return 0
|
520
|
-
else
|
521
|
-
refresh
|
522
|
-
end
|
523
|
-
end
|
524
|
-
|
525
|
-
@cache.length
|
526
|
-
end
|
527
|
-
|
528
|
-
# Refresh the documents in @cache. This means either
|
529
|
-
# sending the initial query or sending a GET_MORE operation.
|
530
|
-
def refresh
|
531
|
-
if !@query_run
|
532
|
-
send_initial_query
|
533
|
-
elsif !@cursor_id.zero?
|
534
|
-
send_get_more
|
535
|
-
end
|
536
|
-
end
|
537
|
-
|
538
|
-
# Sends initial query -- which is always a read unless it is a command
|
539
|
-
#
|
540
|
-
# Upon ConnectionFailure, tries query 3 times if socket was not provided
|
541
|
-
# and the query is either not a command or is a secondary_ok command.
|
542
|
-
#
|
543
|
-
# Pins pools upon successful read and unpins pool upon ConnectionFailure
|
544
|
-
#
|
545
|
-
def send_initial_query
|
546
|
-
tries = 0
|
547
|
-
instrument(:find, instrument_payload) do
|
548
|
-
begin
|
549
|
-
message = construct_query_message
|
550
|
-
socket = @socket || checkout_socket_from_connection
|
551
|
-
results, @n_received, @cursor_id = @connection.receive_message(
|
552
|
-
Mongo::Constants::OP_QUERY, message, nil, socket, @command,
|
553
|
-
nil, exhaust?, compile_regex?)
|
554
|
-
rescue ConnectionFailure => ex
|
555
|
-
socket.close if socket
|
556
|
-
@pool = nil
|
557
|
-
@connection.unpin_pool
|
558
|
-
@connection.refresh
|
559
|
-
if tries < 3 && !@socket && (!@command || Mongo::ReadPreference::secondary_ok?(@selector))
|
560
|
-
tries += 1
|
561
|
-
retry
|
562
|
-
else
|
563
|
-
raise ex
|
564
|
-
end
|
565
|
-
rescue OperationFailure, OperationTimeout => ex
|
566
|
-
raise ex
|
567
|
-
ensure
|
568
|
-
socket.checkin unless @socket || socket.nil?
|
569
|
-
end
|
570
|
-
|
571
|
-
if pin_pool?(results.first)
|
572
|
-
@connection.pin_pool(socket.pool, read_preference)
|
573
|
-
end
|
574
|
-
|
575
|
-
@returned += @n_received
|
576
|
-
@cache += results
|
577
|
-
@query_run = true
|
578
|
-
close_cursor_if_query_complete
|
579
|
-
end
|
580
|
-
end
|
581
|
-
|
582
|
-
def send_get_more
|
583
|
-
message = BSON::ByteBuffer.new([0, 0, 0, 0])
|
584
|
-
|
585
|
-
# DB name.
|
586
|
-
BSON::BSON_RUBY.serialize_cstr(message, full_collection_name)
|
587
|
-
|
588
|
-
# Number of results to return.
|
589
|
-
if @limit > 0
|
590
|
-
limit = @limit - @returned
|
591
|
-
if @batch_size > 0
|
592
|
-
limit = limit < @batch_size ? limit : @batch_size
|
593
|
-
end
|
594
|
-
message.put_int(limit)
|
595
|
-
else
|
596
|
-
message.put_int(@batch_size)
|
597
|
-
end
|
598
|
-
|
599
|
-
# Cursor id.
|
600
|
-
message.put_long(@cursor_id)
|
601
|
-
log(:debug, "cursor.refresh() for cursor #{@cursor_id}") if @logger
|
602
|
-
|
603
|
-
socket = @pool.checkout
|
604
|
-
|
605
|
-
begin
|
606
|
-
results, @n_received, @cursor_id = @connection.receive_message(
|
607
|
-
Mongo::Constants::OP_GET_MORE, message, nil, socket, @command,
|
608
|
-
nil, exhaust?, compile_regex?)
|
609
|
-
ensure
|
610
|
-
socket.checkin
|
611
|
-
end
|
612
|
-
|
613
|
-
@returned += @n_received
|
614
|
-
@cache += results
|
615
|
-
close_cursor_if_query_complete
|
87
|
+
def batch_size
|
88
|
+
@view.batch_size && @view.batch_size > 0 ? @view.batch_size : limit
|
616
89
|
end
|
617
90
|
|
618
|
-
def
|
619
|
-
|
620
|
-
if @pool
|
621
|
-
socket = @pool.checkout
|
622
|
-
elsif @command && !Mongo::ReadPreference::secondary_ok?(@selector)
|
623
|
-
socket = @connection.checkout_reader({:mode => :primary})
|
624
|
-
else
|
625
|
-
socket = @connection.checkout_reader(read_preference)
|
626
|
-
end
|
627
|
-
rescue SystemStackError, NoMemoryError, SystemCallError => ex
|
628
|
-
@connection.close
|
629
|
-
raise ex
|
630
|
-
end
|
631
|
-
@pool = socket.pool
|
632
|
-
socket
|
91
|
+
def exhausted?
|
92
|
+
limited? ? @remaining <= 0 : false
|
633
93
|
end
|
634
94
|
|
635
|
-
def
|
636
|
-
@
|
95
|
+
def get_more
|
96
|
+
process(get_more_operation.execute(@server.context))
|
637
97
|
end
|
638
98
|
|
639
|
-
def
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
query_message = BSON::BSON_CODER.serialize(@selector, false, false, @connection.max_bson_size + MongoClient::APPEND_HEADROOM)
|
647
|
-
query_message.grow(@bson)
|
648
|
-
query_spec = construct_query_spec
|
649
|
-
query_spec.delete('$query')
|
650
|
-
query_message.grow(BSON::BSON_CODER.serialize(query_spec, false, false, @connection.max_bson_size))
|
651
|
-
else # costs only one serialize call
|
652
|
-
spec = query_contains_special_fields? ? construct_query_spec : @selector
|
653
|
-
spec.merge!(@opts)
|
654
|
-
query_message = BSON::BSON_CODER.serialize(spec, false, false, @connection.max_bson_size + MongoClient::APPEND_HEADROOM)
|
655
|
-
query_message.grow(@bson) if @bson
|
656
|
-
end
|
657
|
-
message.put_binary(query_message.to_s)
|
658
|
-
message.put_binary(BSON::BSON_CODER.serialize(@fields, false, false, @connection.max_bson_size).to_s) if @fields
|
659
|
-
message
|
99
|
+
def get_more_operation
|
100
|
+
Operation::Read::GetMore.new({
|
101
|
+
:to_return => to_return,
|
102
|
+
:cursor_id => @cursor_id,
|
103
|
+
:db_name => database.name,
|
104
|
+
:coll_name => @coll_name || collection.name
|
105
|
+
})
|
660
106
|
end
|
661
107
|
|
662
|
-
def
|
663
|
-
|
664
|
-
log[:fields] = @fields if @fields
|
665
|
-
log[:skip] = @skip if @skip && (@skip != 0)
|
666
|
-
log[:limit] = @limit if @limit && (@limit != 0)
|
667
|
-
log[:order] = @order if @order
|
668
|
-
log
|
108
|
+
def kill_cursors
|
109
|
+
kill_cursors_operation.execute(@server.context)
|
669
110
|
end
|
670
111
|
|
671
|
-
def
|
672
|
-
|
673
|
-
spec = BSON::OrderedHash.new
|
674
|
-
spec['$query'] = @selector
|
675
|
-
spec['$orderby'] = Mongo::Support.format_order_clause(@order) if @order
|
676
|
-
spec['$hint'] = @hint if @hint && @hint.length > 0
|
677
|
-
spec['$explain'] = true if @explain
|
678
|
-
spec['$snapshot'] = true if @snapshot
|
679
|
-
spec['$maxScan'] = @max_scan if @max_scan
|
680
|
-
spec['$returnKey'] = true if @return_key
|
681
|
-
spec['$showDiskLoc'] = true if @show_disk_loc
|
682
|
-
spec['$comment'] = @comment if @comment
|
683
|
-
spec['$maxTimeMS'] = @max_time_ms if @max_time_ms
|
684
|
-
if needs_read_pref?
|
685
|
-
read_pref = Mongo::ReadPreference::mongos(@read, @tag_sets)
|
686
|
-
spec['$readPreference'] = read_pref if read_pref
|
687
|
-
end
|
688
|
-
spec
|
112
|
+
def kill_cursors_operation
|
113
|
+
Operation::KillCursors.new({ :cursor_ids => [ @cursor_id ]})
|
689
114
|
end
|
690
115
|
|
691
|
-
def
|
692
|
-
|
116
|
+
def limited?
|
117
|
+
limit ? limit > 0 : false
|
693
118
|
end
|
694
119
|
|
695
|
-
def
|
696
|
-
@
|
697
|
-
@max_scan || @return_key || @comment || @max_time_ms || needs_read_pref?
|
120
|
+
def more?
|
121
|
+
@cursor_id != 0
|
698
122
|
end
|
699
123
|
|
700
|
-
def
|
701
|
-
|
702
|
-
|
703
|
-
|
124
|
+
def process(result)
|
125
|
+
@remaining -= result.returned_count if limited?
|
126
|
+
@cursor_id = result.cursor_id
|
127
|
+
@coll_name ||= result.namespace.sub("#{database.name}.", '') if result.namespace
|
128
|
+
result.documents
|
704
129
|
end
|
705
130
|
|
706
|
-
|
707
|
-
|
708
|
-
# @return [true, false] The state of the exhaust flag.
|
709
|
-
def exhaust?(opts = options)
|
710
|
-
!(opts & OP_QUERY_EXHAUST).zero?
|
711
|
-
end
|
712
|
-
|
713
|
-
def check_modifiable
|
714
|
-
if @query_run || @closed
|
715
|
-
raise InvalidOperation, "Cannot modify the query once it has been run or closed."
|
716
|
-
end
|
717
|
-
end
|
718
|
-
|
719
|
-
def check_command_cursor
|
720
|
-
if @command_cursor
|
721
|
-
raise InvalidOperation, "Cannot call #{caller.first} on command cursors"
|
722
|
-
end
|
723
|
-
end
|
724
|
-
|
725
|
-
def compile_regex?
|
726
|
-
@compile_regex
|
727
|
-
end
|
728
|
-
|
729
|
-
def generate_index_name(spec)
|
730
|
-
indexes = []
|
731
|
-
spec.each_pair do |field, type|
|
732
|
-
indexes.push("#{field}_#{type}")
|
733
|
-
end
|
734
|
-
indexes.join("_")
|
131
|
+
def to_return
|
132
|
+
use_limit? ? @remaining : (batch_size || 0)
|
735
133
|
end
|
736
134
|
|
737
|
-
def
|
738
|
-
|
739
|
-
( !@socket && !@command )
|
135
|
+
def use_limit?
|
136
|
+
limited? && batch_size >= @remaining
|
740
137
|
end
|
741
138
|
end
|
742
139
|
end
|