├── .github └── FUNDING.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── doc ├── feature_checklist.md └── manual │ ├── aggregate │ └── watch.md │ ├── bulk │ └── bulk.md │ ├── connection │ ├── script │ │ ├── authority-certificate.sh │ │ ├── client-certificate.sh │ │ └── server-certificate.sh │ ├── simple_connection_auth.md │ ├── simple_connection_no_auth.md │ ├── tls_connection_no_auth.md │ ├── tls_connection_no_auth_client_certificate.md │ ├── tls_connection_no_auth_self_signed_certificate.md │ └── x509_authentication.md │ └── crud │ ├── delete.md │ └── update.md ├── example ├── .gitignore ├── aggregation.dart ├── auth_source.dart ├── example.dart ├── insert.dart ├── manual │ ├── aggregate │ │ ├── union_with_aggregate.dart │ │ └── union_with_builder.dart │ ├── bulk │ │ ├── ordered_bulk.dart │ │ ├── ordered_collection_helper.dart │ │ ├── unordered_bulk.dart │ │ └── unordered_collection_helper.dart │ ├── commands │ │ ├── drop.dart │ │ ├── list_collections.dart │ │ ├── run_admin_command.dart │ │ └── run_command.dart │ ├── create_collection_schema.dart │ ├── crud │ │ ├── count.dart │ │ ├── cursor.dart │ │ ├── delete_many.dart │ │ ├── delete_one.dart │ │ ├── delete_one_collation.dart │ │ ├── find.dart │ │ ├── find_and_modify.dart │ │ ├── find_and_modify_aggregation_pipeline.dart │ │ ├── find_and_modify_collation.dart │ │ ├── find_and_modify_collation_array_filters.dart │ │ ├── find_and_modify_remove.dart │ │ ├── find_and_modify_return_new.dart │ │ ├── find_and_modify_upsert.dart │ │ ├── find_and_modify_upsert_return_new.dart │ │ ├── find_fluent.dart │ │ ├── find_fluent_in_array.dart │ │ ├── find_one.dart │ │ ├── find_one_by_date.dart │ │ ├── find_timeout.dart │ │ ├── insert_many.dart │ │ ├── insert_one.dart │ │ ├── replace_one.dart │ │ ├── update_many.dart │ │ ├── update_many_aggregate.dart │ │ ├── update_many_array_filters.dart │ │ └── update_one.dart │ ├── db_connection.dart │ ├── generic │ │ ├── zip_list.dart │ │ └── zips.dart │ ├── gridfs │ │ └── delete.dart │ └── watch │ │ ├── watch_on_collection.dart │ │ └── watch_on_collection_insert.dart ├── queries.dart ├── raw_queries.dart ├── russian.dart ├── tailable_cursor.dart ├── test_mongolab.dart ├── types.dart └── updates.dart ├── lib ├── mongo_dart.dart └── src │ ├── auth │ ├── auth.dart │ ├── mongodb_cr_authenticator.dart │ ├── sasl_authenticator.dart │ ├── scram_sha1_authenticator.dart │ ├── scram_sha256_authenticator.dart │ └── x509_authenticator.dart │ ├── connection_pool.dart │ ├── database │ ├── commands │ │ ├── administration_commands │ │ │ ├── create_command │ │ │ │ ├── create_command.dart │ │ │ │ └── create_options.dart │ │ │ ├── create_index_operation │ │ │ │ ├── create_index_operation.dart │ │ │ │ └── create_index_options.dart │ │ │ ├── drop_command │ │ │ │ ├── drop_command.dart │ │ │ │ └── drop_options.dart │ │ │ ├── drop_database_command │ │ │ │ ├── drop_database_command.dart │ │ │ │ └── drop_database_options.dart │ │ │ ├── drop_indexes_command │ │ │ │ ├── drop_indexes_command.dart │ │ │ │ └── drop_indexes_options.dart │ │ │ ├── get_all_parameters_command │ │ │ │ ├── get_all_parameters_command.dart │ │ │ │ └── get_all_parameters_options.dart │ │ │ ├── get_parameter_command │ │ │ │ ├── get_parameter_command.dart │ │ │ │ └── get_parameter_options.dart │ │ │ ├── kill_cursors_command │ │ │ │ ├── kill_cursors_command.dart │ │ │ │ ├── kill_cursors_options.dart │ │ │ │ └── kill_cursors_result.dart │ │ │ ├── list_collections_command │ │ │ │ ├── list_collections_command.dart │ │ │ │ └── list_collections_options.dart │ │ │ ├── listt_indexes_command │ │ │ │ ├── list_indexes_command.dart │ │ │ │ └── list_indexes_options.dart │ │ │ └── wrapper │ │ │ │ ├── create_collection │ │ │ │ ├── create_collection_command.dart │ │ │ │ └── create_collection_options.dart │ │ │ │ └── create_view │ │ │ │ ├── create_view_command.dart │ │ │ │ └── create_view_options.dart │ │ ├── aggregation_commands │ │ │ ├── aggregate │ │ │ │ ├── aggregate_operation.dart │ │ │ │ ├── aggregate_options.dart │ │ │ │ ├── aggregate_result.dart │ │ │ │ └── return_classes │ │ │ │ │ └── change_event.dart │ │ │ ├── count │ │ │ │ ├── count_operation.dart │ │ │ │ ├── count_options.dart │ │ │ │ ├── count_result.dart │ │ │ │ └── return_classes │ │ │ │ │ └── change_event.dart │ │ │ ├── distinct │ │ │ │ ├── distinct_operation.dart │ │ │ │ ├── distinct_options.dart │ │ │ │ ├── distinct_result.dart │ │ │ │ └── return_classes │ │ │ │ │ └── change_event.dart │ │ │ └── wrapper │ │ │ │ └── change_stream │ │ │ │ ├── change_stream_handler.dart │ │ │ │ ├── change_stream_operation.dart │ │ │ │ └── change_stream_options.dart │ │ ├── authentication_commands │ │ │ ├── sasl_continue_command │ │ │ │ ├── sasl_continue_command.dart │ │ │ │ └── sasl_continue_options.dart │ │ │ ├── sasl_start_command │ │ │ │ ├── sasl_start_command.dart │ │ │ │ └── sasl_start_options.dart │ │ │ └── x509_command.dart │ │ ├── base │ │ │ ├── command_operation.dart │ │ │ ├── cursor_result.dart │ │ │ ├── db_admin_command_operation.dart │ │ │ └── operation_base.dart │ │ ├── diagnostic_commands │ │ │ ├── ping_command │ │ │ │ └── ping_command.dart │ │ │ └── server_status_command │ │ │ │ ├── server_status_command.dart │ │ │ │ ├── server_status_options.dart │ │ │ │ └── server_status_result.dart │ │ ├── mixin │ │ │ ├── basic_result.dart │ │ │ └── timing_result.dart │ │ ├── operation.dart │ │ ├── parameters │ │ │ ├── collation_options.dart │ │ │ ├── read_concern.dart │ │ │ └── read_preference.dart │ │ ├── query_and_write_operation_commands │ │ │ ├── delete_operation │ │ │ │ ├── delete_operation.dart │ │ │ │ ├── delete_options.dart │ │ │ │ └── delete_statement.dart │ │ │ ├── find_and_modify_operation │ │ │ │ ├── find_and_modify_operation.dart │ │ │ │ ├── find_and_modify_options.dart │ │ │ │ └── find_and_modify_result.dart │ │ │ ├── find_operation │ │ │ │ ├── find_operation.dart │ │ │ │ ├── find_options.dart │ │ │ │ └── find_result.dart │ │ │ ├── get_last_error_command │ │ │ │ ├── get_last_error_command.dart │ │ │ │ └── get_last_error_options.dart │ │ │ ├── get_more_command │ │ │ │ ├── get_more_command.dart │ │ │ │ ├── get_more_options.dart │ │ │ │ └── get_more_result.dart │ │ │ ├── insert_operation │ │ │ │ ├── insert_operation.dart │ │ │ │ └── insert_options.dart │ │ │ ├── return_classes │ │ │ │ ├── abstract_write_result.dart │ │ │ │ ├── bulk_write_error.dart │ │ │ │ ├── bulk_write_result.dart │ │ │ │ ├── last_error_object.dart │ │ │ │ ├── upserted_info.dart │ │ │ │ ├── write_concern_error.dart │ │ │ │ ├── write_error.dart │ │ │ │ └── write_result.dart │ │ │ ├── update_operation │ │ │ │ ├── update_operation.dart │ │ │ │ ├── update_options.dart │ │ │ │ └── update_statement.dart │ │ │ └── wrapper │ │ │ │ ├── bulk │ │ │ │ ├── bulk.dart │ │ │ │ ├── bulk_options.dart │ │ │ │ ├── ordered_bulk.dart │ │ │ │ └── unordered_bulk.dart │ │ │ │ ├── delete_many │ │ │ │ ├── delete_many_operation.dart │ │ │ │ ├── delete_many_options.dart │ │ │ │ └── delete_many_statement.dart │ │ │ │ ├── delete_one │ │ │ │ ├── delete_one_operation.dart │ │ │ │ ├── delete_one_options.dart │ │ │ │ └── delete_one_statement.dart │ │ │ │ ├── insert_many │ │ │ │ ├── insert_many_operation.dart │ │ │ │ └── insert_many_options.dart │ │ │ │ ├── insert_one │ │ │ │ ├── insert_one_operation.dart │ │ │ │ └── insert_one_options.dart │ │ │ │ ├── replace_one │ │ │ │ ├── replace_one_operation.dart │ │ │ │ ├── replace_one_options.dart │ │ │ │ └── replace_one_statement.dart │ │ │ │ ├── update_many │ │ │ │ ├── update_many_operation.dart │ │ │ │ ├── update_many_options.dart │ │ │ │ └── update_many_statement.dart │ │ │ │ └── update_one │ │ │ │ ├── update_one_operation.dart │ │ │ │ ├── update_one_options.dart │ │ │ │ └── update_one_statement.dart │ │ └── replication_commands │ │ │ └── hello_command │ │ │ ├── client_metadata.dart │ │ │ ├── hello_command.dart │ │ │ └── hello_result.dart │ ├── cursor │ │ ├── cursor.dart │ │ └── modern_cursor.dart │ ├── db.dart │ ├── dbcollection.dart │ ├── dbcommand.dart │ ├── error.dart │ ├── info │ │ └── server_status.dart │ ├── message │ │ ├── additional │ │ │ ├── payload.dart │ │ │ └── section.dart │ │ ├── mongo_modern_message.dart │ │ └── mongo_response_message.dart │ ├── mongo_getmore_message.dart │ ├── mongo_insert_message.dart │ ├── mongo_kill_cursors_message.dart │ ├── mongo_message.dart │ ├── mongo_query_message.dart │ ├── mongo_remove_message.dart │ ├── mongo_reply_message.dart │ ├── mongo_update_message.dart │ ├── server_config.dart │ ├── state.dart │ └── utils │ │ ├── check_same_domain.dart │ │ ├── dns_lookup.dart │ │ ├── map_keys.dart │ │ ├── mongo_db_namespace.dart │ │ ├── parms_utils.dart │ │ ├── split_hosts.dart │ │ └── update_document_check.dart │ ├── extensions │ └── file_ext.dart │ ├── gridfs │ ├── chunk_handler.dart │ ├── grid_fs_file.dart │ ├── grid_in.dart │ ├── grid_out.dart │ └── gridfs.dart │ ├── network │ ├── connection.dart │ ├── connection_manager.dart │ ├── mongo_message_transformer.dart │ └── packet_converter.dart │ └── version.dart ├── pubspec.yaml └── test ├── .gitignore ├── all_tests.dart ├── auth_tests ├── authentication_test.dart ├── client_certificate_test.dart ├── client_x_509_test.dart ├── server_certificate_test.dart └── ssl_connection_test.dart ├── certificates_for_testing ├── client.mongo.crt ├── client.mongo.key ├── client.mongo.pem ├── instructions.txt ├── mongo-test-ca-full-chain.crt ├── mongo-test-ca.crt ├── mongo-test-ca.key ├── mongo-test-ia.crt ├── mongo-test-ia.key ├── server1.crt ├── server1.key ├── server1.pem ├── server2.crt ├── server2.key ├── server2.pem ├── server3.crt ├── server3.key ├── server3.pem ├── server4.crt ├── server4.key ├── server4.pem ├── server5.crt ├── server5.key └── server5.pem ├── client_metadata_test.dart ├── connection_pool_test.dart ├── database_test.dart ├── decimal_test.dart ├── file_ext_test.dart ├── gridfs_test.dart ├── gridfs_testdata_in.txt ├── legacy_uuid_test.dart ├── message_test.dart ├── mongo_actions.dart ├── mongo_dart_query_test.dart ├── op_msg_bulk_operation_test.dart ├── op_msg_collection_test.dart ├── op_msg_commands_test.dart ├── op_msg_read_operation_test.dart ├── op_msg_update_operation_test.dart ├── op_msg_write_operation_test.dart ├── packet_converter_test.dart ├── replica_tests.dart ├── test_binary_dump.dart ├── test_chunks.dart ├── test_connection.dart ├── utils ├── insert_cake_sales_db.dart ├── insert_data.dart ├── test_database.dart └── throw_utils.dart ├── utils_test.dart └── uuid_test.dart /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | #github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | #patreon: # Replace with a single Patreon username 5 | #open_collective: # Replace with a single Open Collective username 6 | #ko_fi: # Replace with a single Ko-fi username 7 | #tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | #community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | #liberapay: # Replace with a single Liberapay username 10 | #issuehunt: # Replace with a single IssueHunt username 11 | #otechie: # Replace with a single Otechie username 12 | #lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: https://www.paypal.com/donate?hosted_button_id=YRUNF9YWKX2NW 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | packages 2 | /null/ 3 | /pubspec.lock 4 | *.md.html 5 | *.dart.js.deps 6 | /*.project 7 | /.idea/ 8 | /out/ 9 | /.pub/ 10 | *.json 11 | .packages 12 | .dart_tool/ 13 | .vscode/ 14 | test/gridfs_testbigdata_in.txt 15 | test/gridfs_testbigdata_out.txt 16 | 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: dart 2 | dart: 3 | - stable 4 | - dev 5 | addons: 6 | apt: 7 | sources: 8 | - mongodb-3.0-precise 9 | packages: 10 | - mongodb-org-server 11 | services: mongodb 12 | before_script: 13 | - sleep 15 14 | sudo: false 15 | cache: 16 | directories: 17 | - $HOME/.pub-cache 18 | script: pub run test 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2012 Vadim Tsushko (vadimtsushko@gmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | 2 | analyzer: 3 | errors: 4 | unintended_html_in_doc_comment: ignore 5 | include: package:lints/recommended.yaml 6 | 7 | # For lint rules and documentation, see http://dart-lang.github.io/linter/lints. 8 | # Uncomment to specify additional rules. 9 | linter: 10 | rules: 11 | - await_only_futures 12 | - unawaited_futures 13 | 14 | 15 | # analyzer: 16 | ### exclude: 17 | ### - path/to/excluded/files/** -------------------------------------------------------------------------------- /doc/feature_checklist.md: -------------------------------------------------------------------------------- 1 | #Functionality Checklist 2 | 3 | From [Feature Checklist for Mongo Drivers](http://www.mongodb.org/display/DOCS/Feature+Checklist+for+Mongo+Drivers) 4 | 5 | ##Essential 6 | 7 | - BSON serialization/deserialization: **Done** 8 | - Basic operations: query, insert, update, remove, ensureIndex, findOne, limit, sort: **Done** 9 | - Fetch more data from a cursor when necessary (dbGetMore): **Done** 10 | - Sending of KillCursors operation when use of a cursor has completed (ideally for efficiently these are sent in batches): **Done** 11 | - Convert all strings to utf8: **Done** 12 | - Authentication: **Done** 13 | 14 | ##Recommended 15 | 16 | - automatic _id generation: **Done** 17 | - Database $cmd support and helpers 18 | - Detect { $err: ... } response from a db query and handle appropriately --see Error Handling in Mongo Drivers **Done** 19 | - Automatically connect to proper server, and failover, when connecting to a Replica Set 20 | - ensureIndex commands should be cached to prevent excessive communication with the database. (Or, the driver user should be informed that ensureIndex is not a lightweight operation for the particular driver.) 21 | - Support detecting max BSON size on connection (e.g., using buildinfo or isMaster commands) and allowing users to insert docs up to that size. 22 | 23 | 24 | ##More Recommended 25 | 26 | - lasterror helper functions: **Done** 27 | - count() helper function: **Done** 28 | - $where clause: **Done** 29 | - eval() 30 | - File chunking (GridFS) **Done** 31 | - hint fields **Done** 32 | - explain helper **Done** 33 | 34 | ##More Optional 35 | 36 | - addUser, logout helpers 37 | - Allow client user to specify Option_SlaveOk for a query 38 | - Tailable cursor support 39 | - In/out buffer pooling (if implementing in a garbage collected languages) 40 | 41 | ##More Optional 42 | 43 | - connection pooling 44 | - Automatic reconnect on connection failure 45 | - DBRef Support: 46 | - Ability to generate easily 47 | - Automatic traversal -------------------------------------------------------------------------------- /doc/manual/connection/simple_connection_auth.md: -------------------------------------------------------------------------------- 1 | 2 | # Authentication 3 | 4 | **Updated for Mongodb ver 4.4 and mongo_dart version 0.5.0** 5 | Authentication requires the creation of users in the nmongodb instance. 6 | Provided that we have a three members replica set: replica0, replica1 and replica2 with 7 | no authentication we have to perform the steps listed in [this tutorial](https://docs.mongodb.com/manual/tutorial/enable-authentication/). 8 | 9 | Once that the user have been created you have to activate authentication for the server. 10 | This is possible in two ways: 11 | 12 | - adding the --auth parameter to the mongod command line (Ex. "mongod --auth --port 27017 --dbpath /var/lib/mongodb") 13 | - enabling the authentication on the mongod.conf file (in linux normally it is under the etc folder) 14 | 15 | ```yaml 16 | security: 17 | authorization: enabled 18 | ``` 19 | 20 | Now that the server requires authentication you have to provide your user name and password 21 | You can do it in two ways: 22 | 23 | ```dart 24 | var db = Db('mongodb://:@replica0:27017/myDb'); 25 | ``` 26 | 27 | or asking for autentication after that the connection is open 28 | 29 | ```dart 30 | var db = Db('mongodb://replica0:27017/myDb'); 31 | await db.open(); 32 | await db.authenticate(, ); 33 | ``` 34 | 35 | [Prev doc.](simple_connection_no_auth.md) - [Next doc.](tls_connection_no_auth.md) 36 | -------------------------------------------------------------------------------- /doc/manual/connection/tls_connection_no_auth.md: -------------------------------------------------------------------------------- 1 | 2 | # Connection 3 | 4 | **Updated for Mongodb ver 4.4 and mongo_dart version 0.5.0** 5 | Connecting to a server with TLS is straigthforward, provided that the server is properly configured. 6 | 7 | You can connect in two ways: 8 | 9 | - passing the connection string parameter "tls" (example: `mongodb://replica0:27017/myDb?tls=true`). You can also use `ssl=true`, but it has been deprecated 10 | - requiring a secure connection when opening the db (ex. `await db.open(secure: true);`) 11 | 12 | If you have an internal/test server with a self signed certificate see next document. 13 | 14 | [Prev doc.](simple_connection_auth.md) - [Next doc.](tls_connection_no_auth_self_signed_certificate.md) -------------------------------------------------------------------------------- /doc/manual/connection/x509_authentication.md: -------------------------------------------------------------------------------- 1 | 2 | # X509 Authentication 3 | 4 | ## Prerequisites 5 | 6 | For X509 authentication, we have to pass the same parameters like fordar the connection with the client certificate. 7 | Be careful that at leat one in: 8 | 9 | - Organization (O) 10 | - Organizational Unit (OU) 11 | - Domain Component (DC) 12 | 13 | must be different between the client and the server certificates. 14 | 15 | When you insert the user in the db, you have to store in the "$external" database the credentials. The user must be the subject of the certificate, for example "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry". 16 | 17 | ```javaScript 18 | db.getSiblingDB("$external").runCommand( 19 | { 20 | createUser: "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry", 21 | roles: [ 22 | { role: "readWrite", db: "test" }, 23 | { role: "userAdminAnyDatabase", db: "admin" } 24 | ], 25 | writeConcern: { w: "majority" , wtimeout: 5000 } 26 | } 27 | ) 28 | ``` 29 | 30 | 31 | You can extract this from the certificate with the command: 32 | 33 | ```bash 34 | openssl x509 -in -inform PEM -subject -nameopt RFC2253 35 | ``` 36 | 37 | for more detail give a look to this two pages: 38 | 39 | - [Use certificates](https://www.mongodb.com/docs/manual/tutorial/configure-x509-client-authentication/). 40 | - [X509](https://www.mongodb.com/docs/manual/core/security-x.509/). 41 | 42 | ## How to Authenticate 43 | 44 | Then we have to options: 45 | 46 | - Authenticate immediately: for this you have to pass also the parameter `authMechanism=MONGODB-X509` in the connection string. You don't need to pass also the "$external" datbase as authsource because the driver authomatically will set it in case of X509 authentication. 47 | - Authenticate after connecting: you have to use the `db.authenticateX509()` method after that the connection is in place. 48 | 49 | [Prev doc.](tls_connection_no_auth_client_certificate.md) 50 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | /packages/ 2 | -------------------------------------------------------------------------------- /example/aggregation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import 'package:decimal/decimal.dart'; 3 | 4 | void main() async { 5 | final db = Db('mongodb://127.0.0.1/testdb'); 6 | await db.open(); 7 | var collection = db.collection('orders'); 8 | await collection.drop(); 9 | await collection.insertMany([ 10 | {'status': 'A', 'cust_id': 3, 'amount': Decimal.fromInt(128)}, 11 | {'status': 'B', 'cust_id': 2, 'amount': Decimal.fromInt(100)}, 12 | {'status': 'A', 'cust_id': 1, 'amount': Decimal.fromInt(80)}, 13 | {'status': 'A', 'cust_id': 3, 'amount': Decimal.fromInt(72)}, 14 | ]); 15 | final pipeline = AggregationPipelineBuilder() 16 | .addStage(Match(where.eq('status', 'A').map['\$query'])) 17 | .addStage( 18 | Group(id: Field('cust_id'), fields: {'total': Sum(Field('amount'))})) 19 | .build(); 20 | final result = 21 | await DbCollection(db, 'orders').modernAggregate(pipeline).toList(); 22 | result.forEach(print); 23 | } 24 | -------------------------------------------------------------------------------- /example/auth_source.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | void main() async { 4 | var db = Db('mongodb://user:pencil@localhost/auth2?authSource=admin'); 5 | await db.open(); 6 | var collection = db.collection('test'); 7 | print(await collection.find().toList()); 8 | await db.close(); 9 | } 10 | -------------------------------------------------------------------------------- /example/insert.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | void main() async { 4 | var db = Db('mongodb://127.0.0.1/test_insert'); // 5 | var stopwatch = Stopwatch()..start(); 6 | DbCollection test; 7 | await db.open(); 8 | test = db.collection('test'); 9 | var data = >[]; 10 | for (num i = 0; i < 1000; i++) { 11 | data.add({'value': i}); 12 | } 13 | await test.drop(); 14 | print('Sequentially inserting 1000 records with aknowledgment'); 15 | for (var elem in data) { 16 | await test.insertOne(elem, writeConcern: WriteConcern.acknowledged); 17 | } 18 | 19 | print(stopwatch.elapsed); 20 | print('Inserting array of 1000 records with aknowledgment'); 21 | 22 | await test.insertMany(data, writeConcern: WriteConcern.acknowledged); 23 | print(stopwatch.elapsed); 24 | print('Inserting array of 500 records with aknowledgment'); 25 | await test.insertMany(data.sublist(500), 26 | writeConcern: WriteConcern.acknowledged); 27 | print(stopwatch.elapsed); 28 | 29 | await db.close(); 30 | } 31 | -------------------------------------------------------------------------------- /example/manual/commands/drop.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.drop(); 14 | await db.close(); 15 | } 16 | 17 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 18 | return; 19 | } 20 | 21 | var collectionName = 'test-drop'; 22 | await db.dropCollection(collectionName); 23 | var ret = await db.modernListCollections().toList(); 24 | var retNum = ret.length; 25 | await db.createCollection(collectionName); 26 | 27 | ret = await db.modernListCollections().toList(); 28 | 29 | var retNum2 = ret.length; 30 | 31 | if (retNum2 != retNum + 1) { 32 | print('Sorry, some error occured'); 33 | return; 34 | } 35 | 36 | await db.dropCollection(collectionName); 37 | ret = await db.modernListCollections().toList(); 38 | 39 | if (retNum != ret.length) { 40 | print('Sorry, some error occured'); 41 | return; 42 | } 43 | 44 | print('Added collection has been correctly removed'); 45 | 46 | await cleanupDatabase(); 47 | } 48 | -------------------------------------------------------------------------------- /example/manual/commands/list_collections.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | await db.drop(); 12 | 13 | Future cleanupDatabase(String collectionName) async { 14 | await db.dropCollection(collectionName); 15 | await db.close(); 16 | } 17 | 18 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 19 | return; 20 | } 21 | 22 | var collectionName = 'test-list-collections'; 23 | await db.createCollection(collectionName); 24 | 25 | var ret = await db.getCollectionNames(); 26 | var retInfo = await db.getCollectionInfos(); 27 | 28 | if (ret.first != retInfo.first['name']) { 29 | print('Sorry, some error occured'); 30 | return; 31 | } 32 | 33 | print( 34 | 'First collection name: ${retInfo.first['name']}'); // 'test-list-collections'; 35 | 36 | await cleanupDatabase(collectionName); 37 | } 38 | -------------------------------------------------------------------------------- /example/manual/commands/run_admin_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import 'package:mongo_dart/src/database/commands/base/db_admin_command_operation.dart'; 3 | 4 | const dbName = 'mongo-dart-example'; 5 | const dbAddress = '127.0.0.1'; 6 | 7 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 8 | 9 | void main() async { 10 | var db = Db(defaultUri); 11 | await db.open(); 12 | 13 | Future cleanupDatabase() async { 14 | await db.close(); 15 | } 16 | 17 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 18 | return; 19 | } 20 | var command = DbAdminCommandOperation(db, {'listDatabases': 1}); 21 | var ret = await command.execute(); 22 | print(ret); 23 | 24 | await cleanupDatabase(); 25 | } 26 | -------------------------------------------------------------------------------- /example/manual/commands/run_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import 'package:mongo_dart/src/database/commands/base/command_operation.dart'; 3 | import 'package:mongo_dart/src/database/commands/diagnostic_commands/ping_command/ping_command.dart'; 4 | 5 | const dbName = 'mongo-dart-example'; 6 | const dbAddress = '127.0.0.1'; 7 | 8 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 9 | 10 | void main() async { 11 | var db = Db(defaultUri); 12 | await db.open(); 13 | await db.drop(); 14 | 15 | Future cleanupDatabase() async { 16 | await db.close(); 17 | } 18 | 19 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 20 | return; 21 | } 22 | 23 | var ret = await db.runCommand({'ping': 1}); 24 | print(ret); // {ok: 1.0}; 25 | 26 | ret = await CommandOperation(db, {}, command: {'ping': 1}) 27 | .execute(); 28 | print(ret); // {ok: 1.0}; 29 | 30 | ret = await PingCommand(db).execute(); 31 | print(ret); // {ok: 1.0}; 32 | 33 | ret = await db.pingCommand(); 34 | print(ret); // {ok: 1.0}; 35 | 36 | var result = await db.collection(r'$cmd').findOne({'ping': 1}); 37 | print(result); // {ok: 1.0}; 38 | 39 | try { 40 | await db.collection(r'$cmd').modernFind(filter: {'ping': 1}).toList(); 41 | } catch (error) { 42 | print( 43 | error); // "MongoDart Error: Invalid collection name specified 'mongo-dart-example.$cmd'"; 44 | } 45 | 46 | await cleanupDatabase(); 47 | } 48 | -------------------------------------------------------------------------------- /example/manual/create_collection_schema.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'create-collection-schema'; 21 | await db.dropCollection(collectionName); 22 | var resultMap = await db.createCollection(collectionName, 23 | createCollectionOptions: CreateCollectionOptions(validator: { 24 | r'$jsonSchema': { 25 | 'bsonType': 'object', 26 | 'required': ['phone'], 27 | 'properties': { 28 | 'phone': { 29 | 'bsonType': 'string', 30 | 'description': 'must be a string and is required' 31 | }, 32 | 'email': { 33 | 'bsonType': 'string', 34 | 'pattern': r'@mongodb\.com$', 35 | 'description': 36 | 'must be a string and match the regular expression pattern' 37 | }, 38 | 'status': { 39 | 'enum': ['Unknown', 'Incomplete'], 40 | 'description': 'can only be one of the enum values' 41 | } 42 | } 43 | } 44 | })); 45 | 46 | if (resultMap[keyOk] != 1.0) { 47 | print(resultMap[keyErrmsg]); 48 | await cleanupDatabase(); 49 | return; 50 | } 51 | var collection = db.collection(collectionName); 52 | 53 | var ret = await collection.insertOne( 54 | {'name': 'Anand', 'phone': '451 3874643', 'status': 'Incomplete'}, 55 | writeConcern: WriteConcern.majority); 56 | 57 | if (!ret.isSuccess) { 58 | print('Error detected in record insertion'); 59 | } 60 | 61 | ret = await collection.insertOne({'name': 'Amanda', 'status': 'Updated'}, 62 | writeConcern: WriteConcern.majority); 63 | 64 | if (!ret.isSuccess) { 65 | print(ret.writeError?.errmsg); 66 | } 67 | 68 | await cleanupDatabase(); 69 | } 70 | -------------------------------------------------------------------------------- /example/manual/crud/delete_many.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'delete-many'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany([ 25 | {'_id': 3, 'name': 'John', 'age': 32}, 26 | {'_id': 4, 'name': 'Mira', 'age': 27}, 27 | {'_id': 7, 'name': 'Luis', 'age': 42}, 28 | ]); 29 | if (!ret.isSuccess) { 30 | print('Error detected in record insertion'); 31 | } 32 | 33 | var res = await collection.deleteMany(where.lt('age', 40)); 34 | 35 | print('Removed documents: ${res.nRemoved}'); // 2 36 | 37 | var findResult = await collection.find().toList(); 38 | 39 | print('First record name: ${findResult.first['name']}'); // 'Luis'; 40 | 41 | await cleanupDatabase(); 42 | } 43 | -------------------------------------------------------------------------------- /example/manual/crud/delete_one.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'delete-one'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany([ 25 | {'_id': 3, 'name': 'John', 'age': 32}, 26 | {'_id': 4, 'name': 'Mira', 'age': 27}, 27 | {'_id': 7, 'name': 'Luis', 'age': 42}, 28 | ]); 29 | if (!ret.isSuccess) { 30 | print('Error detected in record insertion'); 31 | } 32 | 33 | var res = await collection.deleteOne({}); 34 | 35 | print('Removed documents: ${res.nRemoved}'); 36 | 37 | var findResult = await collection.find().toList(); 38 | 39 | print('First record name: ${findResult.first['name']}'); // 'Mira'; 40 | 41 | await cleanupDatabase(); 42 | } 43 | -------------------------------------------------------------------------------- /example/manual/crud/delete_one_collation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' 2 | show CollationOptions, Db, FindOptions, where; 3 | 4 | const dbName = 'mongo-dart-example'; 5 | const dbAddress = '127.0.0.1'; 6 | 7 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 8 | 9 | void main() async { 10 | var db = Db(defaultUri); 11 | await db.open(); 12 | 13 | Future cleanupDatabase() async { 14 | await db.close(); 15 | } 16 | 17 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 18 | return; 19 | } 20 | 21 | var collectionName = 'delete-one-collation'; 22 | await db.dropCollection(collectionName); 23 | var collection = db.collection(collectionName); 24 | 25 | var ret = await collection.insertMany(>[ 26 | {'_id': 1, 'category': 'café', 'status': 'A'}, 27 | {'_id': 2, 'category': 'cafE', 'status': 'a'}, 28 | {'_id': 3, 'category': 'cafe', 'status': 'a'}, 29 | ]); 30 | if (!ret.isSuccess) { 31 | print('Error detected in record insertion'); 32 | } 33 | 34 | var findResult = await collection 35 | .modernFind(selector: where.eq('category', 'cafe').eq('status', 'a')) 36 | .toList(); 37 | 38 | print('First record category without collation before deletion: ' 39 | '${findResult.first['category']}'); // 'cafe'; 40 | 41 | findResult = await collection 42 | .modernFind( 43 | selector: where.eq('category', 'cafe').eq('status', 'a'), 44 | findOptions: 45 | FindOptions(collation: CollationOptions('fr', strength: 1))) 46 | .toList(); 47 | 48 | print('First record category with collation before deletion: ' 49 | '${findResult.first['category']}'); // 'café'; 50 | 51 | var res = await collection.deleteOne( 52 | {'category': 'cafe', 'status': 'a'}, 53 | collation: CollationOptions('fr', strength: 1)); 54 | 55 | print('Removed documents: ${res.nRemoved}'); 56 | 57 | findResult = await collection.find().toList(); 58 | 59 | print('First record category after deletion with collation: ' 60 | '${findResult.first['category']}'); // 'cafE'; 61 | 62 | await cleanupDatabase(); 63 | } 64 | -------------------------------------------------------------------------------- /example/manual/crud/find.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'find'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany(>[ 25 | {'_id': 1, 'name': 'Tom', 'state': 'active', 'rating': 100, 'score': 5}, 26 | {'_id': 2, 'name': 'William', 'state': 'busy', 'rating': 80, 'score': 4}, 27 | {'_id': 3, 'name': 'Liz', 'state': 'on hold', 'rating': 70, 'score': 8}, 28 | {'_id': 4, 'name': 'George', 'state': 'active', 'rating': 95, 'score': 8}, 29 | {'_id': 5, 'name': 'Jim', 'state': 'idle', 'rating': 40, 'score': 3}, 30 | {'_id': 6, 'name': 'Laureen', 'state': 'busy', 'rating': 87, 'score': 8}, 31 | {'_id': 7, 'name': 'John', 'state': 'idle', 'rating': 72, 'score': 7} 32 | ]); 33 | 34 | if (!ret.isSuccess) { 35 | print('Error detected in record insertion'); 36 | } 37 | 38 | var res = await collection.find({ 39 | 'name': 'Tom', 40 | 'rating': {r'$gt': 10} 41 | }).toList(); 42 | 43 | print('First document fetched: ${res.first['name']} - ${res.first['state']}'); 44 | // Tom - active 45 | 46 | await cleanupDatabase(); 47 | } 48 | -------------------------------------------------------------------------------- /example/manual/crud/find_and_modify.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'find-modify'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany(>[ 25 | {'_id': 1, 'name': 'Tom', 'state': 'active', 'rating': 100, 'score': 5}, 26 | {'_id': 2, 'name': 'William', 'state': 'busy', 'rating': 80, 'score': 4}, 27 | {'_id': 3, 'name': 'Liz', 'state': 'on hold', 'rating': 70, 'score': 8}, 28 | {'_id': 4, 'name': 'George', 'state': 'active', 'rating': 95, 'score': 8}, 29 | {'_id': 5, 'name': 'Jim', 'state': 'idle', 'rating': 40, 'score': 3}, 30 | {'_id': 6, 'name': 'Laureen', 'state': 'busy', 'rating': 87, 'score': 8}, 31 | {'_id': 7, 'name': 'John', 'state': 'idle', 'rating': 72, 'score': 7} 32 | ]); 33 | 34 | if (!ret.isSuccess) { 35 | print('Error detected in record insertion'); 36 | } 37 | 38 | var res = await collection.modernFindAndModify( 39 | query: where 40 | .eq('name', 'Tom') 41 | .eq('state', 'active') 42 | .eq('rating', {r'$gt': 10}), 43 | sort: {'rating': 1}, 44 | update: ModifierBuilder().inc('score', 1)); 45 | 46 | print('Updated document: ${res.lastErrorObject?.updatedExisting}'); // true 47 | 48 | print('Modified element original score: ' 49 | '${res.value?['score']}'); // 5; 50 | 51 | await cleanupDatabase(); 52 | } 53 | -------------------------------------------------------------------------------- /example/manual/crud/find_and_modify_aggregation_pipeline.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var running4_2orGreater = false; 10 | 11 | var db = Db(defaultUri); 12 | await db.open(); 13 | var serverFcv = db.masterConnection.serverCapabilities.fcv ?? '0.0'; 14 | if (serverFcv.compareTo('4.2') != -1) { 15 | running4_2orGreater = true; 16 | } 17 | 18 | Future cleanupDatabase() async { 19 | await db.close(); 20 | } 21 | 22 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 23 | return; 24 | } 25 | if (!running4_2orGreater) { 26 | print('Not supported in this release'); 27 | return; 28 | } 29 | 30 | var collectionName = 'find-modify-aggregation-pipeline'; 31 | await db.dropCollection(collectionName); 32 | var collection = db.collection(collectionName); 33 | 34 | var ret = await collection.insertMany([ 35 | { 36 | '_id': 1, 37 | 'grades': [ 38 | {'grade': 80, 'mean': 75, 'std': 6}, 39 | {'grade': 85, 'mean': 90, 'std': 4}, 40 | {'grade': 85, 'mean': 85, 'std': 6} 41 | ], 42 | }, 43 | { 44 | '_id': 2, 45 | 'grades': [ 46 | {'grade': 90, 'mean': 75, 'std': 6}, 47 | {'grade': 87, 'mean': 90, 'std': 3}, 48 | {'grade': 85, 'mean': 85, 'std': 4} 49 | ] 50 | } 51 | ]); 52 | if (!ret.isSuccess) { 53 | print('Error detected in record insertion'); 54 | } 55 | 56 | var res = await collection.modernFindAndModify( 57 | query: where.eq('_id', 1), 58 | update: AggregationPipelineBuilder() 59 | .addStage(AddFields({ 60 | r'total': {r'$sum': r'$grades.grade'}, 61 | })) 62 | .build(), 63 | returnNew: true, 64 | ); 65 | print('Updated document: ${res.lastErrorObject?.updatedExisting}'); // true 66 | 67 | print('Modified element new total: ' 68 | '${res.value?['total']}'); // 250; 69 | 70 | await cleanupDatabase(); 71 | } 72 | -------------------------------------------------------------------------------- /example/manual/crud/find_and_modify_collation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'find-modify-collation'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany(>[ 25 | {'_id': 1, 'category': 'café', 'status': 'A'}, 26 | {'_id': 2, 'category': 'cafE', 'status': 'a'}, 27 | {'_id': 3, 'category': 'cafe', 'status': 'a'}, 28 | ]); 29 | if (!ret.isSuccess) { 30 | print('Error detected in record insertion'); 31 | } 32 | 33 | var res = await collection.modernFindAndModify( 34 | query: where.eq('category', 'cafe').eq('status', 'a'), 35 | sort: {'category': 1}, 36 | update: ModifierBuilder().set('status', 'updated'), 37 | findAndModifyOptions: 38 | FindAndModifyOptions(collation: CollationOptions('fr', strength: 1))); 39 | 40 | print('Updated document: ${res.lastErrorObject?.updatedExisting}'); // true 41 | 42 | print('Modified element original category: ' 43 | '${res.value?['category']}'); // 'café'; 44 | 45 | await cleanupDatabase(); 46 | } 47 | -------------------------------------------------------------------------------- /example/manual/crud/find_and_modify_collation_array_filters.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'find-modify-array-filters'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany([ 25 | { 26 | '_id': 1, 27 | 'grades': [95, 92, 90] 28 | }, 29 | { 30 | '_id': 2, 31 | 'grades': [98, 100, 102] 32 | }, 33 | { 34 | '_id': 3, 35 | 'grades': [95, 110, 100] 36 | } 37 | ]); 38 | if (!ret.isSuccess) { 39 | print('Error detected in record insertion'); 40 | } 41 | 42 | var res = await collection.modernFindAndModify( 43 | query: where.gte('grades', 100), 44 | update: ModifierBuilder().set(r'grades.$[element]', 100), 45 | returnNew: true, 46 | arrayFilters: [ 47 | { 48 | 'element': {r'$gte': 100} 49 | } 50 | ]); 51 | print('Updated document: ${res.lastErrorObject?.updatedExisting}'); // true 52 | 53 | print('Modified element new grades: ' 54 | '${res.value?['grades']}'); // [98, 100, 100]; 55 | 56 | await cleanupDatabase(); 57 | } 58 | -------------------------------------------------------------------------------- /example/manual/crud/find_and_modify_remove.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'find-modify-remove'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany(>[ 25 | {'_id': 1, 'name': 'Tom', 'state': 'active', 'rating': 100, 'score': 5}, 26 | {'_id': 2, 'name': 'William', 'state': 'busy', 'rating': 80, 'score': 4}, 27 | {'_id': 3, 'name': 'Liz', 'state': 'on hold', 'rating': 70, 'score': 8}, 28 | {'_id': 4, 'name': 'George', 'state': 'active', 'rating': 95, 'score': 8}, 29 | {'_id': 5, 'name': 'Jim', 'state': 'idle', 'rating': 40, 'score': 3}, 30 | {'_id': 6, 'name': 'Laureen', 'state': 'busy', 'rating': 87, 'score': 8}, 31 | {'_id': 7, 'name': 'John', 'state': 'idle', 'rating': 72, 'score': 7} 32 | ]); 33 | 34 | if (!ret.isSuccess) { 35 | print('Error detected in record insertion'); 36 | } 37 | 38 | var res = await collection.modernFindAndModify( 39 | query: where.eq('state', 'active'), 40 | sort: {'rating': 1}, 41 | remove: true); 42 | 43 | print('Updated document: ${res.lastErrorObject?.updatedExisting}'); // false 44 | 45 | print('Removed element name: "${res.value?['name']}"'); // 'George'; 46 | 47 | await cleanupDatabase(); 48 | } 49 | -------------------------------------------------------------------------------- /example/manual/crud/find_and_modify_return_new.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'find-modify-return-new'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany(>[ 25 | {'_id': 1, 'name': 'Tom', 'state': 'active', 'rating': 100, 'score': 5}, 26 | {'_id': 2, 'name': 'William', 'state': 'busy', 'rating': 80, 'score': 4}, 27 | {'_id': 3, 'name': 'Liz', 'state': 'on hold', 'rating': 70, 'score': 8}, 28 | {'_id': 4, 'name': 'George', 'state': 'active', 'rating': 95, 'score': 8}, 29 | {'_id': 5, 'name': 'Jim', 'state': 'idle', 'rating': 40, 'score': 3}, 30 | {'_id': 6, 'name': 'Laureen', 'state': 'busy', 'rating': 87, 'score': 8}, 31 | {'_id': 7, 'name': 'John', 'state': 'idle', 'rating': 72, 'score': 7} 32 | ]); 33 | 34 | if (!ret.isSuccess) { 35 | print('Error detected in record insertion'); 36 | } 37 | 38 | var res = await collection.modernFindAndModify( 39 | query: where 40 | .eq('name', 'Tom') 41 | .eq('state', 'active') 42 | .eq('rating', {r'$gt': 10}), 43 | sort: {'rating': 1}, 44 | update: ModifierBuilder().inc('score', 1), 45 | returnNew: true); 46 | 47 | print('Updated document: ${res.lastErrorObject?.updatedExisting}'); // true 48 | 49 | print('Modified element new score: ${res.value?['score']}'); // 6; 50 | 51 | await cleanupDatabase(); 52 | } 53 | -------------------------------------------------------------------------------- /example/manual/crud/find_and_modify_upsert.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'find-modify-upsert'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany(>[ 25 | {'_id': 1, 'name': 'Tom', 'state': 'active', 'rating': 100, 'score': 5}, 26 | {'_id': 2, 'name': 'William', 'state': 'busy', 'rating': 80, 'score': 4}, 27 | {'_id': 3, 'name': 'Liz', 'state': 'on hold', 'rating': 70, 'score': 8}, 28 | {'_id': 4, 'name': 'George', 'state': 'active', 'rating': 95, 'score': 8}, 29 | {'_id': 5, 'name': 'Jim', 'state': 'idle', 'rating': 40, 'score': 3}, 30 | {'_id': 6, 'name': 'Laureen', 'state': 'busy', 'rating': 87, 'score': 8}, 31 | {'_id': 7, 'name': 'John', 'state': 'idle', 'rating': 72, 'score': 7} 32 | ]); 33 | 34 | if (!ret.isSuccess) { 35 | print('Error detected in record insertion'); 36 | } 37 | 38 | var res = await collection.modernFindAndModify( 39 | query: where.eq('name', 'Gus').eq('state', 'active').eq('rating', 100), 40 | sort: {'rating': 1}, 41 | update: ModifierBuilder().inc('score', 1), 42 | upsert: true); 43 | print('Updated document: ${res.lastErrorObject?.updatedExisting}'); // false 44 | print('Upserted _id -> ${res.lastErrorObject?.upserted}'); // An ObjectId 45 | 46 | print('No retuned value (null): ${res.value}'); // null; 47 | 48 | await cleanupDatabase(); 49 | } 50 | -------------------------------------------------------------------------------- /example/manual/crud/find_and_modify_upsert_return_new.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'find-modify-upsert-return-new'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany(>[ 25 | {'_id': 1, 'name': 'Tom', 'state': 'active', 'rating': 100, 'score': 5}, 26 | {'_id': 2, 'name': 'William', 'state': 'busy', 'rating': 80, 'score': 4}, 27 | {'_id': 3, 'name': 'Liz', 'state': 'on hold', 'rating': 70, 'score': 8}, 28 | {'_id': 4, 'name': 'George', 'state': 'active', 'rating': 95, 'score': 8}, 29 | {'_id': 5, 'name': 'Jim', 'state': 'idle', 'rating': 40, 'score': 3}, 30 | {'_id': 6, 'name': 'Laureen', 'state': 'busy', 'rating': 87, 'score': 8}, 31 | {'_id': 7, 'name': 'John', 'state': 'idle', 'rating': 72, 'score': 7} 32 | ]); 33 | 34 | if (!ret.isSuccess) { 35 | print('Error detected in record insertion'); 36 | } 37 | 38 | var res = await collection.modernFindAndModify( 39 | query: where.eq('name', 'Gus').eq('state', 'active').eq('rating', 100), 40 | sort: {'rating': 1}, 41 | update: ModifierBuilder().inc('score', 1), 42 | upsert: true, 43 | returnNew: true); 44 | print('Updated document: ${res.lastErrorObject?.updatedExisting}'); // false 45 | print('Upserted _id -> ${res.lastErrorObject?.upserted}'); // An ObjectId 46 | 47 | print('Upserted document name: "${res.value?['name']}"'); // 'Gus' 48 | 49 | await cleanupDatabase(); 50 | } 51 | -------------------------------------------------------------------------------- /example/manual/crud/find_fluent.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'find'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany(>[ 25 | {'_id': 1, 'name': 'Tom', 'state': 'active', 'rating': 100, 'score': 5}, 26 | {'_id': 2, 'name': 'William', 'state': 'busy', 'rating': 80, 'score': 4}, 27 | {'_id': 3, 'name': 'Liz', 'state': 'on hold', 'rating': 70, 'score': 8}, 28 | {'_id': 4, 'name': 'George', 'state': 'active', 'rating': 95, 'score': 8}, 29 | {'_id': 5, 'name': 'Jim', 'state': 'idle', 'rating': 40, 'score': 3}, 30 | {'_id': 6, 'name': 'Laureen', 'state': 'busy', 'rating': 87, 'score': 8}, 31 | {'_id': 7, 'name': 'John', 'state': 'idle', 'rating': 72, 'score': 7} 32 | ]); 33 | 34 | if (!ret.isSuccess) { 35 | print('Error detected in record insertion'); 36 | } 37 | 38 | var res = 39 | await collection.find(where.eq('name', 'Tom').gt('rating', 10)).toList(); 40 | 41 | print('First document fetched: ${res.first['name']} - ${res.first['state']}'); 42 | // Tom - active 43 | 44 | await cleanupDatabase(); 45 | } 46 | -------------------------------------------------------------------------------- /example/manual/crud/find_one_by_date.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'find-one-by-date'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany(>[ 25 | { 26 | '_id': 1, 27 | 'name': 'Tom', 28 | 'state': 'active', 29 | 'timestamp': Timestamp(10, 12), 30 | 'since': DateTime(2020, 10, 01), 31 | }, 32 | { 33 | '_id': 2, 34 | 'name': 'William', 35 | 'state': 'busy', 36 | 'timestamp': Timestamp(100, 112), 37 | 'since': DateTime(2021, 10, 25) 38 | }, 39 | { 40 | '_id': 3, 41 | 'name': 'Liz', 42 | 'state': 'on hold', 43 | 'timestamp': Timestamp(200, 212), 44 | 'since': DateTime(2021, 04, 05) 45 | }, 46 | { 47 | '_id': 4, 48 | 'name': 'George', 49 | 'state': 'active', 50 | 'timestamp': Timestamp(300, 312), 51 | 'since': DateTime(2020, 12, 25) 52 | }, 53 | ]); 54 | 55 | if (!ret.isSuccess) { 56 | print('Error detected in record insertion'); 57 | } 58 | 59 | var res = await collection.findOne(where.lt('since', DateTime(2020, 10, 25))); 60 | 61 | if (res == null) { 62 | print('No document found'); 63 | } else { 64 | print('Document fetched: ' 65 | '${res['name']} - ${res['state']} - ${res['timestamp']}'); 66 | } // Tom - active - Timestamp(10, 12) 67 | 68 | await cleanupDatabase(); 69 | } 70 | -------------------------------------------------------------------------------- /example/manual/crud/find_timeout.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'find-timeout'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany(>[ 25 | {'_id': 1, 'name': 'Tom', 'state': 'active', 'rating': 100, 'score': 5}, 26 | {'_id': 2, 'name': 'William', 'state': 'busy', 'rating': 80, 'score': 4}, 27 | {'_id': 3, 'name': 'Liz', 'state': 'on hold', 'rating': 70, 'score': 8}, 28 | {'_id': 4, 'name': 'George', 'state': 'active', 'rating': 95, 'score': 8}, 29 | {'_id': 5, 'name': 'Jim', 'state': 'idle', 'rating': 40, 'score': 3}, 30 | {'_id': 6, 'name': 'Laureen', 'state': 'busy', 'rating': 87, 'score': 8}, 31 | {'_id': 7, 'name': 'John', 'state': 'idle', 'rating': 72, 'score': 7} 32 | ]); 33 | 34 | if (!ret.isSuccess) { 35 | print('Error detected in record insertion'); 36 | } 37 | 38 | var res = await collection.modernFind(filter: { 39 | 'rating': {r'$gt': 60} 40 | }, sort: { 41 | 'state': 1, 42 | 'name': 1 43 | }, findOptions: FindOptions(maxTimeMS: 5000)).toList(); 44 | 45 | print('First document fetched: ${res.first['name']} - ${res.first['state']}'); 46 | // George - active 47 | 48 | await cleanupDatabase(); 49 | } 50 | -------------------------------------------------------------------------------- /example/manual/crud/insert_many.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'insert-many'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany(>[ 25 | {'_id': 1, 'name': 'Tom', 'state': 'active', 'rating': 100, 'score': 5}, 26 | {'_id': 2, 'name': 'William', 'state': 'busy', 'rating': 80, 'score': 4}, 27 | {'_id': 3, 'name': 'Liz', 'state': 'on hold', 'rating': 70, 'score': 8}, 28 | {'_id': 4, 'name': 'George', 'state': 'active', 'rating': 95, 'score': 8}, 29 | {'_id': 5, 'name': 'Jim', 'state': 'idle', 'rating': 40, 'score': 3}, 30 | {'_id': 6, 'name': 'Laureen', 'state': 'busy', 'rating': 87, 'score': 8}, 31 | {'_id': 7, 'name': 'John', 'state': 'idle', 'rating': 72, 'score': 7} 32 | ]); 33 | 34 | if (!ret.isSuccess) { 35 | print('Error detected in record insertion'); 36 | } 37 | 38 | var res = await collection.find().toList(); 39 | 40 | print('Inserted ${res.length} elements'); 41 | // 7 42 | 43 | await cleanupDatabase(); 44 | } 45 | -------------------------------------------------------------------------------- /example/manual/crud/insert_one.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'insert-one'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertOne({ 25 | '_id': 1, 26 | 'name': 'Tom', 27 | 'state': 'active', 28 | 'rating': 100, 29 | 'score': 5 30 | }); 31 | 32 | if (!ret.isSuccess) { 33 | print('Error detected in record insertion'); 34 | } 35 | 36 | var res = await collection.findOne(); 37 | 38 | print('Fetched ${res?['name']}'); 39 | // Tom 40 | 41 | await cleanupDatabase(); 42 | } 43 | -------------------------------------------------------------------------------- /example/manual/crud/replace_one.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'replace-one'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany([ 25 | { 26 | '_id': 1, 27 | 'member': 'abc123', 28 | 'status': 'Pending', 29 | 'points': 0, 30 | 'misc1': 'note to self: confirm status', 31 | 'misc2': 'Need to activate' 32 | }, 33 | { 34 | '_id': 2, 35 | 'member': 'xyz123', 36 | 'status': 'D', 37 | 'points': 59, 38 | 'misc1': 'reminder: ping me at 100pts', 39 | 'misc2': 'Some random comment' 40 | }, 41 | ]); 42 | if (!ret.isSuccess) { 43 | print('Error detected in record insertion'); 44 | } 45 | 46 | var res = await collection.replaceOne( 47 | where.eq('member', 'abc123'), 48 | { 49 | '_id': 1, 50 | 'member': 'abc123', 51 | 'status': 'A', 52 | 'points': 1, 53 | 'misc1': 'note to self: confirm status', 54 | 'misc2': 'Need to activate' 55 | }, 56 | writeConcern: WriteConcern(w: 'majority', wtimeout: 5000)); 57 | 58 | print('Modified documents: ${res.nModified}'); // 1 59 | 60 | var findResult = await collection.find(where.eq('member', 'abc123')).toList(); 61 | 62 | print('Modified element status: ' 63 | '"${findResult.first['status']}"'); // 'A'; 64 | 65 | await cleanupDatabase(); 66 | } 67 | -------------------------------------------------------------------------------- /example/manual/crud/update_many.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'update-many'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany([ 25 | { 26 | '_id': 1, 27 | 'member': 'abc123', 28 | 'status': 'A', 29 | 'points': 1, 30 | 'misc1': 'note to self: confirm status', 31 | 'misc2': 'Need to activate' 32 | }, 33 | { 34 | '_id': 2, 35 | 'member': 'xyz123', 36 | 'status': 'D', 37 | 'points': 59, 38 | 'misc1': 'reminder: ping me at 100pts', 39 | 'misc2': 'Some random comment' 40 | }, 41 | ]); 42 | if (!ret.isSuccess) { 43 | print('Error detected in record insertion'); 44 | } 45 | 46 | var res = await collection.updateMany( 47 | where, ModifierBuilder().set('status', 'A').inc('points', 1), 48 | writeConcern: WriteConcern(w: 'majority', wtimeout: 5000)); 49 | 50 | print('Modified documents: ${res.nModified}'); // 2 51 | 52 | var findResult = await collection.find().toList(); 53 | 54 | print('Last record points: ${findResult.last['points']}'); // 60; 55 | 56 | await cleanupDatabase(); 57 | } 58 | -------------------------------------------------------------------------------- /example/manual/crud/update_many_aggregate.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'update-many-aggregate'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany([ 25 | { 26 | '_id': 1, 27 | 'member': 'abc123', 28 | 'status': 'A', 29 | 'points': 2, 30 | 'misc1': 'note to self: confirm status', 31 | 'misc2': 'Need to activate' 32 | }, 33 | { 34 | '_id': 2, 35 | 'member': 'xyz123', 36 | 'status': 'A', 37 | 'points': 60, 38 | 'misc1': 'reminder: ping me at 100pts', 39 | 'misc2': 'Some random comment' 40 | }, 41 | ]); 42 | if (!ret.isSuccess) { 43 | print('Error detected in record insertion'); 44 | } 45 | 46 | var res = await collection.updateMany( 47 | null, 48 | (AggregationPipelineBuilder() 49 | ..addStage(SetStage({ 50 | 'status': 'Modified', 51 | 'comments': [r'$misc1', r'$misc2'] 52 | })) 53 | ..addStage(Unset(['misc1', 'misc2']))) 54 | .build(), 55 | writeConcern: WriteConcern(w: 'majority', wtimeout: 5000)); 56 | 57 | print('Modified documents: ${res.nModified}'); // 2 58 | 59 | var findResult = await collection.find().toList(); 60 | 61 | print('Last record status: ${findResult.last['status']}'); // 'Modified'; 62 | 63 | await cleanupDatabase(); 64 | } 65 | -------------------------------------------------------------------------------- /example/manual/crud/update_many_array_filters.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'update-many-array-filters'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany([ 25 | { 26 | '_id': 1, 27 | 'grades': [95, 92, 90] 28 | }, 29 | { 30 | '_id': 2, 31 | 'grades': [98, 100, 102] 32 | }, 33 | { 34 | '_id': 3, 35 | 'grades': [95, 110, 100] 36 | } 37 | ]); 38 | if (!ret.isSuccess) { 39 | print('Error detected in record insertion'); 40 | } 41 | 42 | var res = await collection.updateMany(where.gte('grades', 100), 43 | ModifierBuilder().set(r'grades.$[element]', 100), 44 | arrayFilters: [ 45 | { 46 | 'element': {r'$gte': 100} 47 | } 48 | ]); 49 | 50 | print('Modified documents: ${res.nModified}'); // 2 51 | 52 | var findResult = await collection.find().toList(); 53 | 54 | print('Last record grades, last element: ' 55 | '${findResult.last['grades'].last}'); // 100; 56 | 57 | await cleanupDatabase(); 58 | } 59 | -------------------------------------------------------------------------------- /example/manual/crud/update_one.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | const dbName = 'mongo-dart-example'; 4 | const dbAddress = '127.0.0.1'; 5 | 6 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 7 | 8 | void main() async { 9 | var db = Db(defaultUri); 10 | await db.open(); 11 | 12 | Future cleanupDatabase() async { 13 | await db.close(); 14 | } 15 | 16 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 17 | return; 18 | } 19 | 20 | var collectionName = 'update-one'; 21 | await db.dropCollection(collectionName); 22 | var collection = db.collection(collectionName); 23 | 24 | var ret = await collection.insertMany([ 25 | { 26 | '_id': 1, 27 | 'member': 'abc123', 28 | 'status': 'Pending', 29 | 'points': 0, 30 | 'misc1': 'note to self: confirm status', 31 | 'misc2': 'Need to activate' 32 | }, 33 | { 34 | '_id': 2, 35 | 'member': 'xyz123', 36 | 'status': 'D', 37 | 'points': 59, 38 | 'misc1': 'reminder: ping me at 100pts', 39 | 'misc2': 'Some random comment' 40 | }, 41 | ]); 42 | if (!ret.isSuccess) { 43 | print('Error detected in record insertion'); 44 | } 45 | 46 | var res = await collection.updateOne(where.eq('member', 'abc123'), 47 | ModifierBuilder().set('status', 'A').inc('points', 1), 48 | writeConcern: WriteConcern(w: 'majority', wtimeout: 5000)); 49 | 50 | print('Modified documents: ${res.nModified}'); // 1 51 | 52 | var findResult = await collection.find(where.eq('member', 'abc123')).toList(); 53 | 54 | print('Modified element status: ' 55 | '"${findResult.first['status']}"'); // 'A'; 56 | 57 | await cleanupDatabase(); 58 | } 59 | -------------------------------------------------------------------------------- /example/manual/generic/zips.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | import 'zip_list.dart'; 4 | 5 | const dbName = 'mongo-dart-example'; 6 | const dbAddress = '127.0.0.1'; 7 | 8 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 9 | 10 | void displayZip(Map zip) { 11 | print('state: ${zip['state']}, city: ${zip['city']}, ' 12 | 'zip: ${zip['_id']}, population: ${zip['pop']}'); 13 | } 14 | 15 | void main() async { 16 | var db = Db(defaultUri); 17 | await db.open(); 18 | 19 | Future cleanupDatabase() async => await db.close(); 20 | 21 | if (!db.masterConnection.serverCapabilities.supportsOpMsg) { 22 | return; 23 | } 24 | 25 | var collectionName = 'zip'; 26 | await db.dropCollection(collectionName); 27 | var collection = db.collection(collectionName); 28 | 29 | print('Starting inserting data'); 30 | var ret = await collection.insertMany(zipList); 31 | 32 | print('Creating geospatial index'); 33 | await collection.createIndex(keys: {'loc': '2d'}); 34 | 35 | if (!ret.isSuccess) { 36 | print('Error detected in record insertion'); 37 | } 38 | print(''' 39 | ******************** Zips for state NY, with population between 14000 and 16000, 40 | ******************** reverse ordered by population'''); 41 | await collection 42 | .find(where 43 | .eq('state', 'NY') 44 | .inRange('pop', 14000, 16000) 45 | .sortBy('pop', descending: true)) 46 | .forEach(displayZip); 47 | print('\n******************** Find ZIP for code 78829 (BATESVILLE)'); 48 | var batesville = await collection.findOne(where.eq('_id', '78829')); 49 | if (batesville != null) { 50 | displayZip(batesville); 51 | print('******************** Find 10 ZIP closest to BATESVILLE'); 52 | await collection 53 | .find(where.near('loc', batesville['loc']).limit(10)) 54 | .forEach(displayZip); 55 | } 56 | 57 | await cleanupDatabase(); 58 | } 59 | -------------------------------------------------------------------------------- /example/raw_queries.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | void main() async { 4 | var db = Db('mongodb://127.0.0.1/mongo_dart-test'); 5 | DbCollection coll; 6 | ObjectId? id; 7 | await db.open(); 8 | print('connection open'); 9 | coll = db.collection('simple_data'); 10 | await coll.deleteMany({}); 11 | for (var n = 0; n < 1000; n++) { 12 | await coll.insert({'my_field': n, 'str_field': 'str_$n'}); 13 | } 14 | var val = await coll.findOne({'my_field': 17}); 15 | print('Filtered by my_field=17 $val'); 16 | id = val?['_id'] as ObjectId?; 17 | if (id == null) { 18 | print('Id not detected'); 19 | await db.close(); 20 | return; 21 | } 22 | val = await coll.findOne({'_id': id}); 23 | print('Filtered by _id=$id: $val'); 24 | print('Removing doc with _id=$id'); 25 | await coll.deleteOne({'_id': id}); 26 | val = await coll.findOne({'_id': id}); 27 | print('Filtered by _id=$id: $val. There more no such a doc'); 28 | print( 29 | "Filtered by {'str_field': {'\$regex': new BsonRegexp('^str_(5|7|8)17\$')}"); 30 | await coll.find({ 31 | 'str_field': {'\$regex': RegExp('^str_(5|7|8)17\$')} 32 | }).forEach((v) => print(v)); 33 | await db.close(); 34 | } 35 | -------------------------------------------------------------------------------- /example/russian.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | void main() async { 4 | var db = Db('mongodb://127.0.0.1/mongo_dart-test'); 5 | await db.open(); 6 | var collection = db.collection('test-utf8'); 7 | await collection.remove({}); 8 | await collection.insert({ 9 | 'Имя': 'Вадим', 10 | 'Фамилия': 'Цушко', 11 | 'Профессия': 'Брадобрей', 12 | 'Шаблон': RegExp('^.adim\$') 13 | }); 14 | var v = await collection.findOne(); 15 | print( 16 | 'Utf8 encoding demonstration. I18 strings may be used not only as values but also as keys'); 17 | print(v); 18 | v = await collection.findOne(where.eq('Имя', 'Вадим')); 19 | print('Filtered by query().eq(): $v'); 20 | v = await collection 21 | .findOne(where.match('Имя', '^..ДИМ\$', caseInsensitive: true)); 22 | print('Filtered by query().match(): $v'); 23 | await db.close(); 24 | } 25 | -------------------------------------------------------------------------------- /example/tailable_cursor.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import 'dart:async'; 3 | 4 | //////// I guess tailable cursor does not work in that example 5 | /// NJ: it works for me provide the collection is not empty... 6 | void main() async { 7 | var db = Db('mongodb://127.0.0.1/test'); 8 | 9 | await db.open(); 10 | var i = 0; 11 | await db.collection('log').insert({'index': i}); 12 | Timer.periodic(Duration(seconds: 10), (Timer t) async { 13 | i++; 14 | print('Insert $i'); 15 | await db.collection('log').insert({'index': i}); 16 | if (i == 10) { 17 | print('Stop inserting'); 18 | t.cancel(); 19 | } 20 | }); 21 | var oplog = DbCollection(db, 'log'); 22 | var cursor = oplog.createCursor() 23 | ..tailable = true 24 | ..timeout = false 25 | ..awaitData = false; 26 | while (true) { 27 | var doc = await cursor.nextObject(); 28 | if (doc == null) { 29 | print('.'); 30 | await Future.delayed(Duration(seconds: 1), () => null); 31 | } else { 32 | print('Fetched: $doc'); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /example/test_mongolab.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | final String mongoDbUri = 4 | // 'mongodb://test:test@ds031477.mongolab.com:31477/dart'; 5 | 'mongodb://user:pencil@localhost/auth1'; 6 | void main() async { 7 | // Db db = new Db(mongoDbUri, 'test scram sha1'); 8 | // 9 | // await db.open(); 10 | // print(await db.collection('test').find().toList()); 11 | // await db.close(); 12 | 13 | var db = Db('mongodb://ds031477.mongolab.com:31477/dart'); 14 | await db.open(); 15 | await db.authenticate('test', 'test'); 16 | var collection = db.collection('testAuthenticationWithUri'); 17 | await collection.remove({}); 18 | await collection.insert({'a': 1}); 19 | await collection.insert({'a': 2}); 20 | await collection.insert({'a': 3}); 21 | await collection.findOne(); 22 | await db.close(); 23 | } 24 | -------------------------------------------------------------------------------- /example/types.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | void main() async { 4 | var db = Db('mongodb://127.0.0.1/mongo_dart-blog'); 5 | await db.open(); 6 | var collection = db.collection('test-types'); 7 | await collection.remove({}); 8 | await collection.insert({ 9 | 'array': [1, 2, 3], 10 | 'string': 'hello', 11 | 'hash': {'a': 1, 'b': 2}, 12 | 'date': DateTime.now(), // Stores only milisecond resolution 13 | 'oid': ObjectId(), 14 | 'binary': BsonBinary.from([0x23, 0x24, 0x25]), 15 | 'int': 42, 16 | 'float': 33.3333, 17 | 'regexp': RegExp('.?dim'), 18 | 'boolean': true, 19 | 'where': JsCode('this.x == 3'), 20 | 'null': null 21 | }); 22 | var v = await collection.findOne(); 23 | print(v); 24 | await db.close(); 25 | } 26 | -------------------------------------------------------------------------------- /example/updates.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | void main() async { 4 | var db = Db('mongodb://127.0.0.1/mongo_dart-test'); 5 | await db.open(); 6 | ///// Simple update 7 | var coll = db.collection('collection-for-save'); 8 | await coll.remove({}); 9 | var toInsert = >[ 10 | {'name': 'a', 'value': 10}, 11 | {'name': 'b', 'value': 20}, 12 | {'name': 'c', 'value': 30}, 13 | {'name': 'd', 'value': 40} 14 | ]; 15 | await coll.insertAll(toInsert); 16 | var v1 = await coll.findOne({'name': 'c'}); 17 | if (v1 == null) { 18 | print('Record not found'); 19 | await db.close(); 20 | return; 21 | } 22 | print('Record c: $v1'); 23 | v1['value'] = 31; 24 | await coll.insertOne(v1); 25 | var v2 = await coll.findOne({'name': 'c'}); 26 | print('Record c after update: $v2'); 27 | 28 | /////// Field level update 29 | coll = db.collection('collection-for-save'); 30 | await coll.remove({}); 31 | toInsert = >[ 32 | {'name': 'a', 'value': 10}, 33 | {'name': 'b', 'value': 20}, 34 | {'name': 'c', 'value': 30}, 35 | {'name': 'd', 'value': 40} 36 | ]; 37 | await coll.insertAll(toInsert); 38 | v1 = await coll.findOne({'name': 'c'}); 39 | print('Record c: $v1'); 40 | await coll.legacyUpdate(where.eq('name', 'c'), modify.set('value', 31)); 41 | v2 = await coll.findOne({'name': 'c'}); 42 | print('Record c after field level update: $v2'); 43 | 44 | //// Field level increment 45 | 46 | coll = db.collection('collection-for-save'); 47 | await coll.remove({}); 48 | toInsert = >[ 49 | {'name': 'a', 'value': 10}, 50 | {'name': 'b', 'value': 20}, 51 | {'name': 'c', 'value': 30}, 52 | {'name': 'd', 'value': 40} 53 | ]; 54 | await coll.insertAll(toInsert); 55 | v1 = await coll.findOne({'name': 'c'}); 56 | print('Record c: $v1'); 57 | await coll.legacyUpdate(where.eq('name', 'c'), modify.inc('value', 1)); 58 | v2 = await coll.findOne({'name': 'c'}); 59 | print('Record c after field level increment by one: $v2'); 60 | await db.close(); 61 | } 62 | -------------------------------------------------------------------------------- /lib/src/auth/auth.dart: -------------------------------------------------------------------------------- 1 | //part of mongo_dart; 2 | import 'package:mongo_dart/mongo_dart.dart' show Connection, Db, MongoDartError; 3 | import 'package:sasl_scram/sasl_scram.dart' show UsernamePasswordCredential; 4 | 5 | import 'mongodb_cr_authenticator.dart'; 6 | import 'scram_sha1_authenticator.dart'; 7 | import 'scram_sha256_authenticator.dart'; 8 | import 'x509_authenticator.dart'; 9 | 10 | // ignore: constant_identifier_names 11 | enum AuthenticationScheme { MONGODB_CR, SCRAM_SHA_1, SCRAM_SHA_256, X509 } 12 | 13 | abstract class Authenticator { 14 | Authenticator(); 15 | 16 | factory Authenticator.create(AuthenticationScheme authenticationScheme, Db db, 17 | UsernamePasswordCredential credentials) { 18 | switch (authenticationScheme) { 19 | case AuthenticationScheme.MONGODB_CR: 20 | return MongoDbCRAuthenticator(db, credentials); 21 | case AuthenticationScheme.SCRAM_SHA_1: 22 | return ScramSha1Authenticator(credentials, db); 23 | case AuthenticationScheme.SCRAM_SHA_256: 24 | return ScramSha256Authenticator(credentials, db); 25 | case AuthenticationScheme.X509: 26 | return X509Authenticator(credentials.username, db); 27 | // ignore: unreachable_switch_default 28 | default: 29 | throw MongoDartError("Authenticator wasn't specified"); 30 | } 31 | } 32 | 33 | static String? name; 34 | 35 | Future authenticate(Connection connection); 36 | } 37 | 38 | abstract class RandomStringGenerator { 39 | static const String allowedCharacters = '!"#\'\$%&()*+-./0123456789:;<=>?@' 40 | 'ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; 41 | 42 | String generate(int length); 43 | } 44 | 45 | Map parsePayload(String payload) { 46 | var dict = {}; 47 | var parts = payload.split(','); 48 | 49 | for (var i = 0; i < parts.length; i++) { 50 | var key = parts[i][0]; 51 | var value = parts[i].substring(2); 52 | dict[key] = value; 53 | } 54 | 55 | return dict; 56 | } 57 | -------------------------------------------------------------------------------- /lib/src/auth/mongodb_cr_authenticator.dart: -------------------------------------------------------------------------------- 1 | //part of mongo_dart; 2 | // ignore_for_file: deprecated_member_use_from_same_package 3 | 4 | import 'package:crypto/crypto.dart' as crypto; 5 | import 'package:mongo_dart/mongo_dart.dart' 6 | show Connection, Db, DbCommand, MongoQueryMessage; 7 | import 'package:mongo_dart/src/auth/auth.dart'; 8 | import 'package:sasl_scram/sasl_scram.dart' show UsernamePasswordCredential; 9 | 10 | class MongoDbCRAuthenticator extends Authenticator { 11 | MongoDbCRAuthenticator(this.db, this.credentials) : super(); 12 | 13 | static final String name = 'MONGODB-CR'; 14 | 15 | final Db db; 16 | final UsernamePasswordCredential credentials; 17 | 18 | @override 19 | Future authenticate(Connection connection) { 20 | return db.getNonce(connection: connection).then((msg) { 21 | var nonce = msg['nonce']; 22 | var command = createMongoDbCrAuthenticationCommand( 23 | db, credentials, nonce.toString()); 24 | return db.executeDbCommand(command, connection: connection); 25 | }).then((res) => res['ok'] == 1); 26 | } 27 | 28 | static DbCommand createMongoDbCrAuthenticationCommand( 29 | Db db, UsernamePasswordCredential credentials, String nonce) { 30 | var hashedPassword = crypto.md5 31 | .convert( 32 | '${credentials.username}:mongo:${credentials.password}'.codeUnits) 33 | .toString(); 34 | var key = crypto.md5 35 | .convert('$nonce${credentials.username}$hashedPassword'.codeUnits) 36 | .toString(); 37 | var selector = { 38 | 'authenticate': 1, 39 | 'user': credentials.username, 40 | 'nonce': nonce, 41 | 'key': key 42 | }; 43 | return DbCommand(db.authSourceDb ?? db, DbCommand.SYSTEM_COMMAND_COLLECTION, 44 | MongoQueryMessage.OPTS_NONE, 0, -1, selector, null); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/auth/scram_sha1_authenticator.dart: -------------------------------------------------------------------------------- 1 | import 'package:crypto/crypto.dart' as crypto; 2 | import 'package:sasl_scram/sasl_scram.dart' 3 | show 4 | ScramMechanism, 5 | UsernamePasswordCredential, 6 | CryptoStrengthStringGenerator; 7 | 8 | import 'package:mongo_dart/mongo_dart.dart' show Db; 9 | 10 | import 'sasl_authenticator.dart'; 11 | 12 | class ScramSha1Authenticator extends SaslAuthenticator { 13 | static String name = 'SCRAM-SHA-1'; 14 | 15 | ScramSha1Authenticator(UsernamePasswordCredential credential, Db db) 16 | : super( 17 | ScramMechanism( 18 | 'SCRAM-SHA-1', // Optionally choose hash method from a list provided by the server 19 | crypto.sha1, 20 | credential, 21 | CryptoStrengthStringGenerator()), 22 | db) { 23 | this.db = db; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/src/auth/scram_sha256_authenticator.dart: -------------------------------------------------------------------------------- 1 | //part of mongo_dart; 2 | import 'package:crypto/crypto.dart' as crypto; 3 | import 'package:sasl_scram/sasl_scram.dart' 4 | show 5 | ScramMechanism, 6 | UsernamePasswordCredential, 7 | CryptoStrengthStringGenerator; 8 | 9 | import 'package:mongo_dart/mongo_dart.dart' show Db; 10 | 11 | import 'sasl_authenticator.dart'; 12 | 13 | class ScramSha256Authenticator extends SaslAuthenticator { 14 | static String name = 'SCRAM-SHA-256'; 15 | 16 | ScramSha256Authenticator(UsernamePasswordCredential credential, Db db) 17 | : super( 18 | ScramMechanism( 19 | 'SCRAM-SHA-256', // Optionally choose hash method from a list provided by the server 20 | crypto.sha256, 21 | credential, 22 | CryptoStrengthStringGenerator()), 23 | db) { 24 | this.db = db; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/auth/x509_authenticator.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' 2 | show 3 | Connection, 4 | Db, 5 | DbCommand, 6 | MongoDartError, 7 | MongoQueryMessage, 8 | keyCode, 9 | keyCodeName, 10 | keyErrmsg, 11 | keyOk; 12 | import 'package:mongo_dart/src/auth/auth.dart'; 13 | 14 | import '../database/commands/authentication_commands/x509_command.dart'; 15 | 16 | class X509Authenticator extends Authenticator { 17 | X509Authenticator(this.username, this.db) : super(); 18 | 19 | final String? username; 20 | Db db; 21 | static final String name = 'MONGODB-X509'; 22 | 23 | @override 24 | Future authenticate(Connection connection) async { 25 | if (connection.serverCapabilities.supportsOpMsg) { 26 | return modernAuthenticate(connection); 27 | } 28 | return legacyAuthenticate(connection); 29 | } 30 | 31 | Future legacyAuthenticate(Connection connection) async { 32 | var command = createMongoDbX509AuthenticationCommand(db, username); 33 | return db 34 | .executeDbCommand(command, connection: connection) 35 | .then((res) => res['ok'] == 1); 36 | } 37 | 38 | static DbCommand createMongoDbX509AuthenticationCommand( 39 | Db db, String? username) { 40 | var command = { 41 | 'authenticate': 1, 42 | 'mechanism': name, 43 | if (username != null && username.isNotEmpty) 'user': username, 44 | }; 45 | 46 | return DbCommand(db.authSourceDb ?? db, DbCommand.SYSTEM_COMMAND_COLLECTION, 47 | MongoQueryMessage.OPTS_NONE, 0, 1, command, null); 48 | } 49 | 50 | Future modernAuthenticate(Connection connection) async { 51 | var command = X509Command(db.authSourceDb ?? db, name, username, 52 | connection: connection); 53 | var result = await command.execute(); 54 | 55 | if (result[keyOk] == 0.0) { 56 | throw MongoDartError(result[keyErrmsg], 57 | mongoCode: result[keyCode], 58 | errorCode: result[keyCode] == null ? null : '${result[keyCode]}', 59 | errorCodeName: result[keyCodeName]); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/src/connection_pool.dart: -------------------------------------------------------------------------------- 1 | part of '../mongo_dart.dart'; 2 | 3 | /// A function that produces an instance of [Db], whether synchronously or asynchronously. 4 | /// 5 | /// This is used in the [ConnectionPool] class to connect to a database on-the-fly. 6 | typedef DbFactory = FutureOr Function(); 7 | 8 | /// A connection pool that limits the number of concurrent connections to a MongoDB server. 9 | /// 10 | /// The connection pool lazily connects to the database; that is to say, it only opens as many 11 | /// connections as it needs to. If it is only ever called once, then it will only ever connect once. 12 | class ConnectionPool { 13 | final List _connections = []; 14 | int _index = 0; 15 | final Pool _pool; 16 | 17 | /// The maximum number of concurrent connections allowed. 18 | final int maxConnections; 19 | 20 | /// A [DbFactory], a parameterless function that returns a [Db]. The function can be asynchronous if necessary. 21 | final DbFactory dbFactory; 22 | 23 | /// Initializes a connection pool. 24 | /// 25 | /// * `maxConnections`: The maximum amount of connections to keep open simultaneously. 26 | /// * `dbFactory*: a parameterless function that returns a [Db]. The function can be asynchronous if necessary. 27 | ConnectionPool(this.maxConnections, this.dbFactory) 28 | : _pool = Pool(maxConnections); 29 | 30 | /// Connects to the database, using an existent connection, only creating a new one if 31 | /// the number of active connections is less than [maxConnections]. 32 | Future connect() { 33 | return _pool.withResource(() async { 34 | var i = _index; 35 | if (++_index >= maxConnections) _index = 0; 36 | 37 | if (i < _connections.length) { 38 | return _connections[i]; 39 | } else { 40 | var db = await dbFactory(); 41 | await db.open(); 42 | _connections.add(db); 43 | return db; 44 | } 45 | }); 46 | } 47 | 48 | /// Closes all active database connections. 49 | Future close() => Future.wait(_connections.map((c) => c.close())) 50 | .then((_) => _pool.close()); 51 | } 52 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/create_command/create_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show Db; 2 | import 'package:mongo_dart/src/database/commands/base/command_operation.dart'; 3 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 4 | 5 | import 'create_options.dart'; 6 | 7 | /// create command. 8 | /// 9 | /// Explicitly creates a collection or view. 10 | /// 11 | /// **Note** 12 | /// The view created by this command does not refer to materialized views. 13 | /// For discussion of on-demand materialized views, see `$merge` instead. 14 | /// 15 | /// Starting in MongoDB 4.2 16 | /// MongoDB removes the MMAPv1 storage engine and the MMAPv1 specific option 17 | /// flags for create. 18 | /// 19 | /// The command accepts the following fields: 20 | /// - db [Db] 21 | /// The database on which create the collection or view 22 | /// - name [String] 23 | /// The collection or view name to be created. 24 | /// - createOptions [CreateOptions] - Optional 25 | /// a set of optional values for the command 26 | /// - rawOption [Map] 27 | /// An alternative way to creteOptions to specify command options 28 | /// (must be manually set) 29 | class CreateCommand extends CommandOperation { 30 | CreateCommand(Db db, String name, 31 | {CreateOptions? createOptions, Map? rawOptions}) 32 | : super(db, { 33 | ...?createOptions?.getOptions(db), 34 | ...?rawOptions 35 | }, command: { 36 | keyCreate: name, 37 | }) { 38 | /* if (name == null) { 39 | throw MongoDartError('Name required in call to createCommand'); 40 | } */ 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/drop_command/drop_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show Db; 2 | import 'package:mongo_dart/src/database/commands/base/command_operation.dart'; 3 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 4 | 5 | import 'drop_options.dart'; 6 | 7 | /// drop command. 8 | /// 9 | /// The drop command removes an entire collection from a database. 10 | /// 11 | /// The command accepts the following fields: 12 | /// - db [Db] 13 | /// The database on which drop the collection or view 14 | /// - collectionName [String] 15 | /// The collection or view name to be dropped. 16 | /// - dropOptions [DropOptions] - Optional 17 | /// a set of optional values for the command 18 | /// - rawOption [Map] 19 | /// An alternative way to dropOptions to specify command options 20 | /// (must be manually set) 21 | class DropCommand extends CommandOperation { 22 | DropCommand(Db db, String collectionName, 23 | {DropOptions? dropOptions, Map? rawOptions}) 24 | : super(db, { 25 | ...?dropOptions?.getOptions(db), 26 | ...?rawOptions 27 | }, command: { 28 | keyDrop: collectionName, 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/drop_command/drop_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | /// Drop command options; 4 | /// 5 | /// Optional parameters that can be used whith the drop command: 6 | class DropOptions { 7 | /// Optional. A document expressing the write concern of the drop command. 8 | /// Omit to use the default write concern. 9 | /// 10 | /// When issued on a sharded cluster, mongos converts the write concern of 11 | /// the drop command and its helper db.collection.drop() to "majority" 12 | final WriteConcern? writeConcern; 13 | 14 | /// A user-provided comment to attach to this command. Once set, 15 | /// this comment appears alongside records of this command in the following 16 | /// locations: 17 | /// - mongod log messages, in the attr.command.cursor.comment field. 18 | /// - Database profiler output, in the command.comment field. 19 | /// - currentOp output, in the command.comment field. 20 | /// 21 | /// Mongo db allows any comment type, but we restrict it to String 22 | /// 23 | /// New in version 4.4. 24 | final String? comment; 25 | 26 | DropOptions({ 27 | this.comment, 28 | this.writeConcern, 29 | }); 30 | 31 | Map getOptions(Db db) => { 32 | if (writeConcern != null) 33 | keyWriteConcern: 34 | writeConcern!.asMap(db.masterConnection.serverStatus), 35 | if (comment != null) keyComment: comment!, 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/drop_database_command/drop_database_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show Db; 2 | import 'package:mongo_dart/src/database/commands/base/command_operation.dart'; 3 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 4 | 5 | import 'drop_database_options.dart'; 6 | 7 | /// dropDatabase command. 8 | /// 9 | /// The dropDatabase command drops the current database, 10 | /// deleting the associated data files. 11 | /// 12 | /// The command accepts the following fields: 13 | /// - db [Db] 14 | /// The database to be dropped 15 | /// - dropDatabaseOptions [DropDatabaseOptions] - Optional 16 | /// a set of optional values for the command 17 | /// - rawOption [Map] 18 | /// An alternative way to dropDatabaseOptions to specify command options 19 | /// (must be manually set) 20 | class DropDatabaseCommand extends CommandOperation { 21 | DropDatabaseCommand(Db db, 22 | {DropDatabaseOptions? dropDatabaseOptions, 23 | Map? rawOptions}) 24 | : super(db, { 25 | ...?dropDatabaseOptions?.getOptions(db), 26 | ...?rawOptions 27 | }, command: { 28 | keyDropDatabase: 1, 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/drop_database_command/drop_database_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | /// DropDatabase command options; 4 | /// 5 | /// Optional parameters that can be used whith the drop command: 6 | class DropDatabaseOptions { 7 | /// Optional. A document expressing the write concern of the drop command. 8 | /// Omit to use the default write concern. 9 | /// 10 | /// When issued on a sharded cluster, mongos converts the write concern of 11 | /// the drop command and its helper db.collection.drop() to "majority" 12 | final WriteConcern? writeConcern; 13 | 14 | /// A user-provided comment to attach to this command. Once set, 15 | /// this comment appears alongside records of this command in the following 16 | /// locations: 17 | /// - mongod log messages, in the attr.command.cursor.comment field. 18 | /// - Database profiler output, in the command.comment field. 19 | /// - currentOp output, in the command.comment field. 20 | /// 21 | /// Mongo db allows any comment type, but we restrict it to String 22 | /// 23 | /// New in version 4.4. 24 | final String? comment; 25 | 26 | DropDatabaseOptions({ 27 | this.comment, 28 | this.writeConcern, 29 | }); 30 | 31 | Map getOptions(Db db) => { 32 | if (writeConcern != null) 33 | keyWriteConcern: 34 | writeConcern!.asMap(db.masterConnection.serverStatus), 35 | if (comment != null) keyComment: comment!, 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/drop_indexes_command/drop_indexes_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' 2 | show Connection, Db, DbCollection, MongoDartError; 3 | import 'package:mongo_dart/src/database/commands/base/command_operation.dart'; 4 | import 'package:mongo_dart/src/database/commands/base/operation_base.dart'; 5 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 6 | 7 | import 'drop_indexes_options.dart'; 8 | 9 | class DropIndexesCommand extends CommandOperation { 10 | Object index; 11 | late Map indexes; 12 | 13 | DropIndexesCommand(Db db, DbCollection collection, this.index, 14 | {DropIndexesOptions? dropIndexesOptions, 15 | Connection? connection, 16 | Map? rawOptions}) 17 | : super( 18 | db, 19 | { 20 | ...?dropIndexesOptions?.getOptions(collection), 21 | ...?rawOptions 22 | }, 23 | collection: collection, 24 | aspect: Aspect.writeOperation, 25 | connection: connection) { 26 | if (index is! String && index is! List && index is! Map) { 27 | throw MongoDartError( 28 | 'The index parameter is not String or List of string or an array'); 29 | } 30 | } 31 | 32 | @override 33 | Map $buildCommand() { 34 | return { 35 | keyDropIndexes: collection!.collectionName, 36 | keyIndex: index 37 | }; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/drop_indexes_command/drop_indexes_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | class DropIndexesOptions { 4 | /// The WriteConcern for this insert operation 5 | WriteConcern? writeConcern; 6 | 7 | /// A user-provided comment to attach to this command. Once set, 8 | /// this comment appears alongside records of this command in the following 9 | /// locations: 10 | /// - mongod log messages, in the attr.command.cursor.comment field. 11 | /// - Database profiler output, in the command.comment field. 12 | /// - currentOp output, in the command.comment field. 13 | /// We limit Comment to String only 14 | /// 15 | /// New in version 4.4. 16 | final String? comment; 17 | 18 | DropIndexesOptions({this.writeConcern, this.comment}); 19 | 20 | Map getOptions(DbCollection collection) => { 21 | if (writeConcern != null) 22 | keyWriteConcern: 23 | writeConcern!.asMap(collection.db.masterConnection.serverStatus), 24 | if (comment != null) keyComment: comment!, 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/get_all_parameters_command/get_all_parameters_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import 'package:mongo_dart/src/database/commands/base/db_admin_command_operation.dart'; 3 | import 'get_all_parameters_options.dart'; 4 | 5 | class GetAllParametersCommand extends DbAdminCommandOperation { 6 | GetAllParametersCommand(Db db, 7 | {GetAllParametersOptions? getAllParametersOptions, 8 | Map? rawOptions}) 9 | : super(db, { 10 | keyGetParameter: '*' 11 | }, options: { 12 | ...?getAllParametersOptions?.options, 13 | ...?rawOptions 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/get_all_parameters_command/get_all_parameters_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 2 | 3 | /// GetAllParameters command options; 4 | class GetAllParametersOptions { 5 | /// A user-provided comment to attach to this command. Once set, 6 | /// this comment appears alongside records of this command in the following 7 | /// locations: 8 | /// - mongod log messages, in the attr.command.cursor.comment field. 9 | /// - Database profiler output, in the command.comment field. 10 | /// - currentOp output, in the command.comment field. 11 | /// We limit Comment to String only 12 | /// 13 | /// New in version 4.4. 14 | final String? comment; 15 | 16 | const GetAllParametersOptions({this.comment}); 17 | 18 | Map get options => { 19 | if (comment != null) keyComment: comment!, 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/get_parameter_command/get_parameter_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import 'package:mongo_dart/src/database/commands/base/db_admin_command_operation.dart'; 3 | import 'get_parameter_options.dart'; 4 | 5 | class GetParameterCommand extends DbAdminCommandOperation { 6 | GetParameterCommand(Db db, String parameterName, 7 | {GetParameterOptions? getParameterOptions, 8 | Map? rawOptions}) 9 | : super(db, { 10 | keyGetParameter: 1, 11 | parameterName: 1 12 | }, options: { 13 | ...?getParameterOptions?.options, 14 | ...?rawOptions 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/get_parameter_command/get_parameter_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 2 | 3 | /// GetParameter command options; 4 | class GetParameterOptions { 5 | /// A user-provided comment to attach to this command. Once set, 6 | /// this comment appears alongside records of this command in the following 7 | /// locations: 8 | /// - mongod log messages, in the attr.command.cursor.comment field. 9 | /// - Database profiler output, in the command.comment field. 10 | /// - currentOp output, in the command.comment field. 11 | /// We limit Comment to String only 12 | /// 13 | /// New in version 4.4. 14 | final String? comment; 15 | 16 | const GetParameterOptions({this.comment}); 17 | 18 | Map get options => { 19 | if (comment != null) keyComment: comment!, 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/kill_cursors_command/kill_cursors_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 2 | 3 | /// KillCursors command options; 4 | /// 5 | /// Optional parameters that can be used whith the killCursors command: 6 | /// `comment` string - @Since 4.4 7 | /// - A user-provided comment to attach to this command. Once set, 8 | /// this comment appears alongside records of this command in the 9 | /// following locations: 10 | /// * mongod log messages, in the attr.command.cursor.comment field. 11 | /// * Database profiler output, in the command.comment field. 12 | /// * currentOp output, in the command.comment field. 13 | /// 14 | /// MongoDb allows any kind of BSON type for this option, but we are 15 | /// limiting it to String only. 16 | /// 17 | class KillCursorsOptions { 18 | final String? comment; 19 | 20 | KillCursorsOptions({this.comment}); 21 | Map get options => { 22 | if (comment != null) keyComment: comment!, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/kill_cursors_command/kill_cursors_result.dart: -------------------------------------------------------------------------------- 1 | import 'package:fixnum/fixnum.dart'; 2 | import 'package:mongo_dart/src/database/commands/mixin/basic_result.dart'; 3 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 4 | 5 | class KillCursorsResult with BasicResult { 6 | KillCursorsResult(Map document) { 7 | extractBasic(document); 8 | var docs = document[keyCursorsKilled] as List?; 9 | if (docs != null && docs.isNotEmpty) { 10 | cursorsKilled = []; 11 | for (var cursorKilled in docs) { 12 | cursorsKilled!.add(cursorKilled); 13 | } 14 | } 15 | 16 | docs = document[keyCursorsNotFound] as List?; 17 | if (docs != null && docs.isNotEmpty) { 18 | cursorsNotFound = []; 19 | for (var cursorNotFound in docs) { 20 | cursorsNotFound!.add(cursorNotFound); 21 | } 22 | } 23 | 24 | docs = document[keyCursorsAlive] as List?; 25 | if (docs != null && docs.isNotEmpty) { 26 | cursorsAlive = []; 27 | for (var cursorAlive in docs) { 28 | cursorsAlive!.add(cursorAlive); 29 | } 30 | } 31 | 32 | docs = document[keyCursorsUnknown] as List?; 33 | if (docs != null && docs.isNotEmpty) { 34 | cursorsUnknown = []; 35 | for (var cursorUnknown in docs) { 36 | cursorsUnknown!.add(cursorUnknown); 37 | } 38 | } 39 | } 40 | 41 | List? cursorsKilled; 42 | List? cursorsNotFound; 43 | List? cursorsAlive; 44 | List? cursorsUnknown; 45 | } 46 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/list_collections_command/list_collections_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import '../../base/command_operation.dart'; 3 | import 'list_collections_options.dart'; 4 | 5 | /// listCollections command. 6 | /// 7 | /// Retrieve information, i.e. the name and options, about the 8 | /// collections and views in a database. Specifically, 9 | /// the command returns a document that contains information with which 10 | /// to create a cursor to the collection information. mongosh provides the 11 | /// - db.getCollectionInfos() 12 | /// and the 13 | /// - db.getCollectionNames() 14 | /// helper methods. 15 | /// 16 | /// 17 | /// The command accepts the following fields: 18 | /// - db [Db] 19 | /// The database on which create the collection or view 20 | /// - filter [Map] 21 | /// Optional. A query expression to filter the list of collections. 22 | /// You can specify a query expression on any of the fields 23 | /// returned by listCollections 24 | /// - listCollectionsOptions [ListCollectionsOptions] - Optional 25 | /// a set of optional values for the command 26 | /// - rawOption [Map] 27 | /// An alternative way to listCollectionsOptions to specify command options 28 | /// (must be manually set) 29 | 30 | class ListCollectionsCommand extends CommandOperation { 31 | ListCollectionsCommand(Db db, 32 | {this.filter, 33 | ListCollectionsOptions? listCollectionsOptions, 34 | Map? rawOptions}) 35 | : super(db, { 36 | ...?listCollectionsOptions?.options, 37 | ...?rawOptions 38 | }, command: { 39 | keyListCollections: 1, 40 | }); 41 | 42 | /// Optional. A query expression to filter the list of collections. 43 | /// 44 | /// You can specify a query expression on any of the fields returned 45 | /// by listCollections 46 | Map? filter; 47 | 48 | @override 49 | Map $buildCommand() { 50 | return { 51 | keyListCollections: 1, 52 | if (filter != null) keyFilter: filter!, 53 | }; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/listt_indexes_command/list_indexes_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import '../../base/command_operation.dart'; 3 | import 'list_indexes_options.dart'; 4 | 5 | /// listIndexes command. 6 | /// 7 | /// Returns information about the indexes on the specified collection. 8 | /// Returned index information includes the keys and options used to create 9 | /// the index, as well as hidden indexes. You can optionally set the 10 | /// batch size for the first batch of results. 11 | /// 12 | /// The command accepts the following fields: 13 | /// - db [Db] 14 | /// The database on which to query the indexes info 15 | /// - collection [DbCollection] 16 | /// The collection of which to list the indexes 17 | /// - listIndexesOptions [ListIndexesOptions] - Optional 18 | /// a set of optional values for the command 19 | /// - rawOption [Map] 20 | /// An alternative way to listIndexesOptions to specify command options 21 | /// (must be manually set) 22 | 23 | class ListIndexesCommand extends CommandOperation { 24 | ListIndexesCommand(Db db, DbCollection collection, 25 | {ListIndexesOptions? listIndexesOptions, Map? rawOptions}) 26 | : super(db, 27 | {...?listIndexesOptions?.options, ...?rawOptions}, 28 | collection: collection); 29 | 30 | @override 31 | Map $buildCommand() { 32 | return { 33 | keyListIndexes: collection?.collectionName ?? '', 34 | }; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/listt_indexes_command/list_indexes_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 2 | 3 | /// ListCollections command options; 4 | class ListIndexesOptions { 5 | /// Optional. Specifies the cursor batch size. 6 | final int? batchSize; 7 | 8 | /// A user-provided comment to attach to this command. Once set, 9 | /// this comment appears alongside records of this command in the following 10 | /// locations: 11 | /// - mongod log messages, in the attr.command.cursor.comment field. 12 | /// - Database profiler output, in the command.comment field. 13 | /// - currentOp output, in the command.comment field. 14 | /// We limit Comment to String only 15 | /// 16 | /// New in version 4.4. 17 | final String? comment; 18 | 19 | const ListIndexesOptions({this.batchSize, this.comment}); 20 | 21 | Map get options => { 22 | if (batchSize != null) keyCursor: {keyBatchSize: batchSize}, 23 | if (comment != null) keyComment: comment!, 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/wrapper/create_collection/create_collection_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show Db; 2 | import 'package:mongo_dart/src/database/commands/administration_commands/create_command/create_command.dart'; 3 | 4 | import 'create_collection_options.dart'; 5 | 6 | /// createCollection command. 7 | /// 8 | /// Explicitly creates a collection. 9 | /// 10 | /// Because MongoDB creates a collection implicitly when the collection is 11 | /// first referenced in a command, this method is used primarily for creating 12 | /// new collections that use specific options. For example, 13 | /// you use db.createCollection() to create a capped collection, or to create 14 | /// a new collection that uses document validation. 15 | /// 16 | /// **Starting in MongoDB 4.2** 17 | /// 18 | /// MongoDB removes the MMAPv1 storage engine and the MMAPv1 specific options 19 | /// `paddingFactor`, `paddingBytes`, `preservePadding` for 20 | /// `db.createCollection()`. 21 | /// 22 | /// **Note** 23 | /// 24 | /// The Original shell command allows to create also views. 25 | /// We restrict this behavior and you will need the `db.createView()` (or 26 | /// directly the `CreateCommand`) to create one. 27 | /// 28 | /// 29 | /// The command accepts the following fields: 30 | /// - db [Db] 31 | /// The database on which create the collection 32 | /// - name [String] 33 | /// The collection name to be created. 34 | /// - createCollectionOptions [createCollectionOptions] - Optional 35 | /// a set of optional values for the command 36 | /// - rawOption [Map] 37 | /// An alternative way to creteCollectionOptions to specify command options 38 | /// (must be manually set) 39 | class CreateCollectionCommand extends CreateCommand { 40 | CreateCollectionCommand(super.db, super.name, 41 | {CreateCollectionOptions? createCollectionOptions, super.rawOptions}) 42 | : super(createOptions: createCollectionOptions); 43 | } 44 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/wrapper/create_collection/create_collection_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/administration_commands/create_command/create_options.dart'; 2 | 3 | class CreateCollectionOptions extends CreateOptions { 4 | CreateCollectionOptions({ 5 | super.capped, 6 | super.size, 7 | super.autoIndexId, 8 | super.max, 9 | super.storageEngine, 10 | super.validator, 11 | super.validationLevel, 12 | super.validationAction, 13 | Map? super.indexOptionDefaults, 14 | super.collation, 15 | super.writeConcern, 16 | super.comment, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/database/commands/administration_commands/wrapper/create_view/create_view_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/administration_commands/create_command/create_options.dart'; 2 | 3 | class CreateViewOptions extends CreateOptions { 4 | CreateViewOptions({super.collation, super.comment}); 5 | } 6 | -------------------------------------------------------------------------------- /lib/src/database/commands/aggregation_commands/aggregate/aggregate_result.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/base/cursor_result.dart'; 2 | import 'package:mongo_dart/src/database/commands/mixin/basic_result.dart'; 3 | import 'package:mongo_dart/src/database/commands/mixin/timing_result.dart'; 4 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 5 | 6 | class AggregateResult with BasicResult, TimingResult { 7 | AggregateResult(Map document) 8 | : cursor = CursorResult( 9 | document[keyCursor] as Map? ?? {}) { 10 | extractBasic(document); 11 | extractTiming(document); 12 | } 13 | CursorResult cursor; 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/database/commands/aggregation_commands/count/count_result.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/mixin/basic_result.dart'; 2 | import 'package:mongo_dart/src/database/commands/mixin/timing_result.dart'; 3 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 4 | 5 | class CountResult with BasicResult, TimingResult { 6 | CountResult(Map document) 7 | : count = document[keyN] as int? ?? 0 { 8 | extractBasic(document); 9 | extractTiming(document); 10 | } 11 | int count; 12 | } 13 | -------------------------------------------------------------------------------- /lib/src/database/commands/aggregation_commands/distinct/distinct_operation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show DbCollection; 2 | import 'package:mongo_dart/src/database/commands/base/operation_base.dart'; 3 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 4 | 5 | import 'distinct_options.dart'; 6 | import '../../base/command_operation.dart'; 7 | import 'distinct_result.dart'; 8 | 9 | /// Collection is the collection on which the operation is performed 10 | /// In case of admin/diagnostic pipeline which does not require an underlying 11 | /// collection, the db parameter must be passed instead. 12 | class DistinctOperation extends CommandOperation { 13 | DistinctOperation(DbCollection collection, this.key, 14 | {this.query, 15 | DistinctOptions? distinctOptions, 16 | Map? rawOptions}) 17 | : super(collection.db, 18 | {...?distinctOptions?.options, ...?rawOptions}, 19 | collection: collection, aspect: Aspect.readOperation); 20 | 21 | /// The field for which to return distinct values. 22 | String key; 23 | 24 | /// A query that specifies the documents from which to retrieve 25 | /// the distinct values. 26 | Map? query; 27 | 28 | @override 29 | Map $buildCommand() { 30 | return { 31 | keyDistinct: collection!.collectionName, 32 | keyKey: key, 33 | if (query != null) keyQuery: query!, 34 | }; 35 | } 36 | 37 | Future executeDocument() async { 38 | var result = await super.execute(); 39 | return DistinctResult(result); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/database/commands/aggregation_commands/distinct/distinct_result.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/mixin/basic_result.dart'; 2 | import 'package:mongo_dart/src/database/commands/mixin/timing_result.dart'; 3 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 4 | 5 | class DistinctResult with BasicResult, TimingResult { 6 | DistinctResult(Map document) 7 | : values = document[keyValues] as List? ?? [] { 8 | extractBasic(document); 9 | extractTiming(document); 10 | } 11 | List values; 12 | } 13 | -------------------------------------------------------------------------------- /lib/src/database/commands/aggregation_commands/wrapper/change_stream/change_stream_handler.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:mongo_dart/src/database/commands/aggregation_commands/aggregate/return_classes/change_event.dart'; 4 | 5 | class ChangeStreamHandler { 6 | void handleData( 7 | Map streamData, EventSink sink) => 8 | sink.add(ChangeEvent.fromMap(streamData)); 9 | 10 | void handleDone(EventSink sink) => sink.close(); 11 | void handleError(error, stacktrace, sink) => sink.addError(error); 12 | 13 | StreamTransformer, ChangeEvent> get transformer => 14 | StreamTransformer, ChangeEvent>.fromHandlers( 15 | handleData: handleData, 16 | handleError: handleError, 17 | handleDone: handleDone); 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/database/commands/aggregation_commands/wrapper/change_stream/change_stream_operation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/aggregation_commands/aggregate/aggregate_operation.dart'; 2 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 3 | 4 | import 'change_stream_options.dart'; 5 | 6 | class ChangeStreamOperation extends AggregateOperation { 7 | ChangeStreamOperation(super.pipeline, 8 | {super.collection, 9 | super.db, 10 | int? batchSize, 11 | super.hint, 12 | super.hintDocument, 13 | ChangeStreamOptions? changeStreamOptions, 14 | super.rawOptions}) 15 | : super( 16 | cursor: batchSize == null 17 | ? null 18 | : {keyBatchSize: batchSize}, 19 | aggregateOptions: changeStreamOptions, 20 | ) { 21 | pipeline.insert(0, { 22 | if (changeStreamOptions == null) 23 | aggregateChangeStream: {} 24 | else 25 | aggregateChangeStream: changeStreamOptions.changeStreamSpecificOptions() 26 | }); 27 | } 28 | 29 | //@override 30 | //Future executeDocument() async => super.executeDocument(); 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/database/commands/authentication_commands/sasl_continue_command/sasl_continue_command.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:typed_data'; 3 | 4 | import 'package:mongo_dart/mongo_dart.dart'; 5 | import 'package:mongo_dart/src/database/commands/base/command_operation.dart'; 6 | import 'package:mongo_dart/src/database/message/additional/section.dart'; 7 | import 'package:mongo_dart/src/database/message/mongo_modern_message.dart'; 8 | import 'sasl_continue_options.dart'; 9 | 10 | class SaslContinueCommand extends CommandOperation { 11 | SaslContinueCommand(Db db, int conversationId, Uint8List payload, 12 | {SaslContinueOptions? saslContinueOptions, 13 | Map? rawOptions, 14 | Connection? connection}) 15 | : super(db, 16 | {...?saslContinueOptions?.options, ...?rawOptions}, 17 | command: { 18 | keySaslContinue: 1, 19 | keyConversationId: conversationId, 20 | keyPayload: base64.encode(payload) 21 | }, 22 | connection: connection); 23 | 24 | /* @override 25 | Future> execute({bool skipStateCheck = false}) async => 26 | super.execute(skipStateCheck: true); */ 27 | @override 28 | Future> execute({bool skipStateCheck = false}) async { 29 | final db = this.db; 30 | 31 | var command = $buildCommand(); 32 | processOptions(command); 33 | command.addAll(options); 34 | 35 | var message = MongoModernMessage(command); 36 | 37 | connection ??= db.masterConnectionAnyState; 38 | 39 | var response = await connection!.executeModernMessage(message); 40 | 41 | var section = response.sections.firstWhere((Section section) => 42 | section.payloadType == MongoModernMessage.basePayloadType); 43 | return section.payload.content; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/src/database/commands/authentication_commands/sasl_continue_command/sasl_continue_options.dart: -------------------------------------------------------------------------------- 1 | /// SaslContinue command options; 2 | class SaslContinueOptions { 3 | /// Undocumented command 4 | /// Fields inferred from MongoDbDriver 5 | /// [see also:](https://github.com/mongodb/specifications/blob/master/source/auth/auth.rst) 6 | 7 | /// No Options at present 8 | const SaslContinueOptions(); 9 | 10 | Map get options => {}; 11 | } 12 | -------------------------------------------------------------------------------- /lib/src/database/commands/authentication_commands/sasl_start_command/sasl_start_command.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:typed_data'; 3 | 4 | import 'package:mongo_dart/mongo_dart.dart'; 5 | import 'package:mongo_dart/src/database/commands/base/command_operation.dart'; 6 | import 'package:mongo_dart/src/database/message/additional/section.dart'; 7 | import 'package:mongo_dart/src/database/message/mongo_modern_message.dart'; 8 | 9 | class SaslStartCommand extends CommandOperation { 10 | SaslStartCommand(Db db, String mechanism, Uint8List payload, 11 | {SaslStartOptions? saslStartOptions, 12 | Map? rawOptions, 13 | Connection? connection}) 14 | : super( 15 | db, {...?saslStartOptions?.options, ...?rawOptions}, 16 | command: { 17 | keySaslStart: 1, 18 | keyMechanism: mechanism, 19 | keyPayload: base64.encode(payload) 20 | }, 21 | connection: connection); 22 | 23 | /* @override 24 | Future> execute({bool skipStateCheck = false}) async => 25 | super.execute(skipStateCheck: true); */ 26 | 27 | @override 28 | Future> execute({bool skipStateCheck = false}) async { 29 | final db = this.db; 30 | 31 | var command = $buildCommand(); 32 | processOptions(command); 33 | command.addAll(options); 34 | 35 | var message = MongoModernMessage(command); 36 | 37 | connection ??= db.masterConnectionAnyState; 38 | 39 | var response = await connection!.executeModernMessage(message); 40 | 41 | var section = response.sections.firstWhere((Section section) => 42 | section.payloadType == MongoModernMessage.basePayloadType); 43 | return section.payload.content; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/src/database/commands/authentication_commands/sasl_start_command/sasl_start_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 2 | 3 | /// SaslStart command options; 4 | class SaslStartOptions { 5 | /// Undocumented command 6 | /// Fields inferred from MongoDbDriver 7 | /// [see also:](https://github.com/mongodb/specifications/blob/master/source/auth/auth.rst) 8 | final bool skipEmptyExchange; 9 | final int autoAuthorize; 10 | 11 | const SaslStartOptions( 12 | {this.skipEmptyExchange = true, this.autoAuthorize = 1}); 13 | 14 | Map get options => { 15 | keyOptions: {keySkipEmptyExchange: skipEmptyExchange}, 16 | keyAutoAuthorize: 1 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/database/commands/authentication_commands/x509_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import 'package:mongo_dart/src/database/commands/base/command_operation.dart'; 3 | import 'package:mongo_dart/src/database/message/additional/section.dart'; 4 | import 'package:mongo_dart/src/database/message/mongo_modern_message.dart'; 5 | 6 | class X509Command extends CommandOperation { 7 | X509Command(Db db, String mechanism, String? username, 8 | {Map? rawOptions, Connection? connection}) 9 | : super(db, {...?rawOptions}, 10 | command: { 11 | keyAuthenticate: 1, 12 | keyMechanism: mechanism, 13 | if (username != null && username.isNotEmpty) keyUser: username 14 | }, 15 | connection: connection); 16 | 17 | @override 18 | Future> execute({bool skipStateCheck = false}) async { 19 | final db = this.db; 20 | 21 | var command = $buildCommand(); 22 | processOptions(command); 23 | command.addAll(options); 24 | 25 | var message = MongoModernMessage(command); 26 | 27 | connection ??= db.masterConnectionAnyState; 28 | 29 | var response = await connection!.executeModernMessage(message); 30 | 31 | var section = response.sections.firstWhere((Section section) => 32 | section.payloadType == MongoModernMessage.basePayloadType); 33 | return section.payload.content; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/database/commands/base/cursor_result.dart: -------------------------------------------------------------------------------- 1 | import 'package:fixnum/fixnum.dart'; 2 | import 'package:mongo_dart/mongo_dart.dart'; 3 | import 'package:mongo_dart/src/database/utils/mongo_db_namespace.dart'; 4 | 5 | /// Contains the cursor information, 6 | /// including the cursor id and the firstBatch/nextBatch of documents. 7 | /// 8 | /// *Note* 9 | /// Starting in 4.4, if the operation against a sharded collection returns 10 | /// partial results due to the unavailability of the queried shard(s), 11 | /// the cursor document includes a partialResultsReturned field. 12 | /// To return partial results, rather than error, due to the unavailability 13 | /// of the queried shard(s), the find command must run with 14 | /// `allowPartialResults` set to `true`. See allowPartialResults. 15 | /// If the queried shards are initially available for the find command 16 | /// but one or more shards become unavailable in subsequent getMore commands, 17 | /// only the getMore commands run when a queried shard or shards are 18 | /// unavailable include the partialResultsReturned flag in the output. 19 | class CursorResult { 20 | late Int64 id; 21 | MongoDBNamespace? ns; 22 | 23 | /// alternative container for documents: 24 | /// * firstBatch in response to a find/aggreagate operation 25 | /// * nextBatch in response to a getMore command 26 | late List> firstBatch, nextBatch; 27 | late bool partialResultsReturned; 28 | 29 | CursorResult(Map document) { 30 | _extract(document); 31 | } 32 | 33 | void _extract(Map document) { 34 | //document ??= {}; 35 | if (document[keyId] == null) { 36 | throw MongoDartError('Missing cursor Id'); 37 | } 38 | id = document[keyId] as Int64; 39 | // on errors "ns is not returned" 40 | if (document[keyNs] != null) { 41 | ns = MongoDBNamespace.fromString(document[keyNs] as String); 42 | } 43 | firstBatch = [...(document[keyFirstBatch] as List? ?? [])]; 44 | nextBatch = [...(document[keyNextBatch] as List? ?? [])]; 45 | partialResultsReturned = 46 | document[keyPartialResultsReturned] as bool? ?? false; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/src/database/commands/base/db_admin_command_operation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show Connection, Db; 2 | import 'package:mongo_dart/src/database/message/mongo_modern_message.dart'; 3 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 4 | 5 | import 'operation_base.dart'; 6 | 7 | class DbAdminCommandOperation extends OperationBase { 8 | Db db; 9 | Map command; 10 | 11 | DbAdminCommandOperation(this.db, this.command, 12 | {Map? options, Connection? connection}) 13 | : super(options, connection: connection); 14 | 15 | Map $buildCommand() => command; 16 | 17 | @override 18 | Future> execute() async { 19 | final db = this.db; 20 | var command = { 21 | ...$buildCommand(), 22 | keyDatabaseName: 'admin' 23 | }; 24 | options.removeWhere((key, value) => command.containsKey(key)); 25 | 26 | command.addAll(options); 27 | 28 | var modernMessage = MongoModernMessage(command); 29 | return db.executeModernMessage(modernMessage, connection: connection); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/database/commands/base/operation_base.dart: -------------------------------------------------------------------------------- 1 | import '../../../../mongo_dart.dart'; 2 | 3 | enum Aspect { 4 | readOperation, 5 | noInheritOptions, 6 | writeOperation, 7 | retryable, 8 | } 9 | 10 | class OperationBase { 11 | Map options; 12 | final Set _aspects; 13 | Connection? connection; 14 | 15 | OperationBase(Map? options, 16 | {this.connection, Object? aspects}) 17 | : options = {...?options}, 18 | _aspects = defineAspects(aspects); 19 | 20 | bool hasAspect(Aspect aspect) => 21 | /* _aspects != null && */ _aspects.contains(aspect); 22 | 23 | Object? get session => options[keySession]; 24 | 25 | // Todo check if this was the meaning of: 26 | // Object.assign(this.options, { session }); 27 | set session(Object? value) => 28 | value == null ? null : options[keySession] = value; 29 | 30 | void clearSession() => options.remove(keySession); 31 | 32 | bool get canRetryRead => true; 33 | 34 | Future> execute() async => throw UnsupportedError( 35 | '"execute" must be implemented for OperationBase subclasses'); 36 | 37 | static Set defineAspects(aspects) { 38 | if (aspects is Aspect) { 39 | return {aspects}; 40 | } else if (aspects is List) { 41 | return {...aspects}; 42 | } 43 | return {Aspect.noInheritOptions}; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/src/database/commands/diagnostic_commands/ping_command/ping_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import 'package:mongo_dart/src/database/commands/base/command_operation.dart'; 3 | 4 | class PingCommand extends CommandOperation { 5 | PingCommand(Db db) : super(db, {}, command: {'ping': 1}); 6 | } 7 | -------------------------------------------------------------------------------- /lib/src/database/commands/diagnostic_commands/server_status_command/server_status_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import 'package:mongo_dart/src/database/commands/base/command_operation.dart'; 3 | import 'server_status_result.dart'; 4 | 5 | var _command = {keyServerStatus: 1}; 6 | 7 | class ServerStatusCommand extends CommandOperation { 8 | ServerStatusCommand(Db db, 9 | {ServerStatusOptions? serverStatusOptions, 10 | Map? rawOptions}) 11 | : super(db, 12 | {...?serverStatusOptions?.options, ...?rawOptions}, 13 | command: _command); 14 | 15 | Future executeDocument() async { 16 | var result = await super.execute(); 17 | return ServerStatusResult(result); 18 | } 19 | 20 | /// Update basic server info + FeatureCompatibilityVersion 21 | Future updateServerStatus(Connection masterConnection) async { 22 | if (!masterConnection.serverCapabilities.supportsOpMsg) { 23 | return; 24 | } 25 | var result = await super.execute(); 26 | // On error the ServerStatus class is not initialized 27 | // check the `isInitialized` flag. 28 | // 29 | // Possible errors are: older version or authorization (requires 30 | // `clusterMonitor` role if authorization is active) 31 | masterConnection.serverStatus.processServerStatus(result); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/database/commands/mixin/basic_result.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 2 | 3 | /// Basic communication from a MongoDb server 4 | /// 5 | /// returns the following fields: 6 | /// `ok` => 1.0 operation/command successful, 0.0 operation/command failed 7 | /// `errmsg` => Optional - if failed, is the error description 8 | /// `code` => Optional - if failed is the error code 9 | /// `codeName` => Optional - if failed is the error typology 10 | /// Ex. "IndexOptionsConflict" 11 | 12 | mixin BasicResult { 13 | /// Command status (1.0 Ok, 0.0 error) 14 | double ok = 0.0; 15 | 16 | /// Optional error fields 17 | String? errmsg; 18 | int? code; 19 | String? codeName; 20 | 21 | bool get success => ok == 1.0; 22 | bool get failure => ok == 0.0; 23 | 24 | void extractBasic(Map document) { 25 | //document ??= {}; 26 | var documentOk = document[keyOk]; 27 | if (documentOk is int) { 28 | ok = documentOk.toDouble(); 29 | } else { 30 | ok = documentOk as double; 31 | } 32 | errmsg = document[keyErrmsg] as String?; 33 | code = document[keyCode] as int?; 34 | codeName = document[keyCodeName] as String?; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/delete_operation/delete_operation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show DbCollection; 2 | import 'package:mongo_dart/src/database/commands/base/command_operation.dart'; 3 | import 'package:mongo_dart/src/database/commands/base/operation_base.dart'; 4 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/delete_operation/delete_statement.dart'; 5 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 6 | 7 | import 'delete_options.dart'; 8 | 9 | class DeleteOperation extends CommandOperation { 10 | DeleteOperation(DbCollection collection, this.deleteRequests, 11 | {DeleteOptions? deleteOptions, Map? rawOptions}) 12 | : super( 13 | collection.db, 14 | { 15 | ...?deleteOptions?.getOptions(collection.db), 16 | ...?rawOptions 17 | }, 18 | collection: collection, 19 | aspect: Aspect.writeOperation) { 20 | if (deleteRequests.isEmpty) { 21 | throw ArgumentError('Delete request required in delete operation'); 22 | } 23 | } 24 | List deleteRequests; 25 | 26 | @override 27 | Map $buildCommand() => { 28 | keyDelete: collection!.collectionName, 29 | keyDeletes: [for (var request in deleteRequests) request.toMap()] 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/delete_operation/delete_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show Db, WriteConcern; 2 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 3 | 4 | class DeleteOptions { 5 | /// The WriteConcern for this delete operation. 6 | /// Omit to use the default write concern 7 | final WriteConcern? writeConcern; 8 | 9 | /// If true, then when a delete statement fails, return without performing 10 | /// the remaining delete statements. If false, then when a delete statement 11 | /// fails, continue with the remaining delete statements, if any. 12 | /// 13 | /// Defaults to true. 14 | final bool ordered; 15 | 16 | /// A user-provided comment to attach to this command. Once set, 17 | /// this comment appears alongside records of this command in the 18 | /// following locations: 19 | /// - mongod log messages, in the attr.command.cursor.comment field. 20 | /// - Database profiler output, in the command.comment field. 21 | /// - currentOp output, in the command.comment field. 22 | /// 23 | /// We limit this field to String values only 24 | /// 25 | /// *New in version 4.4.* 26 | final String? comment; 27 | 28 | DeleteOptions({this.writeConcern, bool? ordered, this.comment}) 29 | : ordered = ordered ?? true; 30 | 31 | // The db parameter is used to transform the writeConcern into a Map 32 | /// When a writeConcern is given a Db object must be specified 33 | Map getOptions(Db db) { 34 | return { 35 | if (writeConcern != null) 36 | keyWriteConcern: writeConcern!.asMap(db.masterConnection.serverStatus), 37 | if (!ordered) keyOrdered: ordered, 38 | if (comment != null) keyComment: comment! 39 | }; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/find_and_modify_operation/find_and_modify_result.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/last_error_object.dart'; 2 | import 'package:mongo_dart/src/database/commands/mixin/basic_result.dart'; 3 | import 'package:mongo_dart/src/database/commands/mixin/timing_result.dart'; 4 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 5 | 6 | class FindAndModifyResult with BasicResult, TimingResult { 7 | FindAndModifyResult(Map document) 8 | : serverResponse = document { 9 | extractBasic(document); 10 | extractTiming(document); 11 | value = document[keyValue] as Map?; 12 | lastErrorObject = 13 | LastErrorObject.fromMap(document[keyLastErrorObject] as Map? ?? {}); 14 | } 15 | 16 | /// This is the original response from the server; 17 | Map serverResponse; 18 | 19 | /// Contains the command’s returned value. 20 | /// For remove operations, value contains the removed document if 21 | /// the query matches a document. If the query does not match a document 22 | /// to remove, value contains null. 23 | /// 24 | /// For update operations, the value embedded document contains the following: 25 | /// - If the new parameter is not set or is false: 26 | /// * the pre-modification document if the query matches a document; 27 | /// * otherwise, null. 28 | /// - If new is true: 29 | /// * the modified document if the query returns a match; 30 | /// * the inserted document if upsert: true and no document matches the query; 31 | /// * otherwise, null. 32 | Map? value; 33 | 34 | LastErrorObject? lastErrorObject; 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/find_operation/find_result.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/base/cursor_result.dart'; 2 | import 'package:mongo_dart/src/database/commands/mixin/basic_result.dart'; 3 | import 'package:mongo_dart/src/database/commands/mixin/timing_result.dart'; 4 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 5 | 6 | class FindResult with BasicResult, TimingResult { 7 | FindResult(Map document) 8 | : cursor = CursorResult( 9 | document[keyCursor] as Map? ?? {}) { 10 | extractBasic(document); 11 | extractTiming(document); 12 | } 13 | CursorResult cursor; 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/get_last_error_command/get_last_error_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 2 | 3 | /// GetLastError command options; 4 | /// 5 | /// Optional parameters that can be used whith the GetLastError command: 6 | /// `wtimeout` integer 7 | /// - Milliseconds. Specify a value in milliseconds to control how long to wait 8 | /// for write propagation to complete. If replication does not complete 9 | /// in the given timeframe, the getLastError command will return with an 10 | /// error status. 11 | /// `comment` string - @Since 4.4 12 | /// - A user-provided comment to attach to this command. Once set, 13 | /// this comment appears alongside records of this command in the 14 | /// following locations: 15 | /// * mongod log messages, in the attr.command.cursor.comment field. 16 | /// * Database profiler output, in the command.comment field. 17 | /// * currentOp output, in the command.comment field. 18 | /// 19 | /// MongoDb allows any kind of BSON type for this option, but we are 20 | /// limiting it to Strings only. 21 | /// 22 | class GetLastErrorOptions { 23 | final int? wtimeout; 24 | final String? comment; 25 | 26 | GetLastErrorOptions({this.wtimeout, this.comment}); 27 | 28 | Map get options => { 29 | if (wtimeout != null) keyWtimeout: wtimeout!, 30 | if (comment != null) keyComment: comment!, 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/get_more_command/get_more_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:fixnum/fixnum.dart'; 2 | import 'package:mongo_dart/mongo_dart.dart' show Db, DbCollection; 3 | import 'package:mongo_dart/src/database/commands/base/command_operation.dart'; 4 | import 'get_more_options.dart'; 5 | import 'get_more_result.dart'; 6 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 7 | 8 | /// getMore command. 9 | /// 10 | /// Use in conjunction with commands that return a cursor, 11 | /// e.g. find and aggregate, to return subsequent batches of documents 12 | /// currently pointed to by the cursor. 13 | /// 14 | /// The command accepts the following fields: 15 | /// * collection [DbCollection] 16 | /// - The collection over which the cursor is operating. 17 | /// * cursorId int 18 | /// - The cursor id of the original find or aggregate operations. 19 | /// * getMoreOptions [GetMoreOptions] - Optional 20 | /// - a set of optional values for the command 21 | class GetMoreCommand extends CommandOperation { 22 | GetMoreCommand(DbCollection? collection, Int64 cursorId, 23 | {Db? db, 24 | String? collectionName, 25 | GetMoreOptions? getMoreOptions, 26 | Map? rawOptions}) 27 | : super(db ?? collection?.db, 28 | {...?getMoreOptions?.options, ...?rawOptions}, 29 | collection: collection, 30 | command: { 31 | keyGetMore: cursorId, 32 | keyCollection: collection?.collectionName ?? collectionName ?? '', 33 | }) { 34 | // In case of aggregate collection agnostic commands, collection is 35 | // not needed 36 | if (collection == null) { 37 | options[keyDbName] = 'admin'; 38 | } 39 | if (!options.containsKey(keyBatchSize)) { 40 | options[keyBatchSize] = 101; 41 | } 42 | } 43 | 44 | Future executeDocument() async { 45 | var result = await super.execute(); 46 | return GetMoreResult(result); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/get_more_command/get_more_result.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/base/cursor_result.dart'; 2 | import 'package:mongo_dart/src/database/commands/mixin/basic_result.dart'; 3 | import 'package:mongo_dart/src/database/commands/mixin/timing_result.dart'; 4 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 5 | 6 | class GetMoreResult with BasicResult, TimingResult { 7 | GetMoreResult(Map document) 8 | : cursor = 9 | CursorResult({...?(document[keyCursor] as Map?)}) { 10 | extractBasic(document); 11 | extractTiming(document); 12 | } 13 | 14 | CursorResult cursor; 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/insert_operation/insert_operation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show DbCollection, ObjectId; 2 | import 'package:mongo_dart/src/database/commands/base/command_operation.dart'; 3 | import 'package:mongo_dart/src/database/commands/base/operation_base.dart'; 4 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 5 | 6 | import 'insert_options.dart'; 7 | 8 | class InsertOperation extends CommandOperation { 9 | InsertOperation(DbCollection collection, this.documents, 10 | {InsertOptions? insertOptions, Map? rawOptions}) 11 | : ids = List.filled(documents.length, null), 12 | super( 13 | collection.db, 14 | { 15 | ...?insertOptions?.getOptions(collection.db), 16 | ...?rawOptions 17 | }, 18 | collection: collection, 19 | aspect: Aspect.writeOperation) { 20 | if (documents.isEmpty) { 21 | throw ArgumentError('Documents required in insert operation'); 22 | } 23 | 24 | for (var idx = 0; idx < documents.length; idx++) { 25 | documents[idx][key_id] ??= ObjectId(); 26 | ids[idx] = documents[idx][key_id]; 27 | } 28 | } 29 | List> documents; 30 | List ids; 31 | 32 | @override 33 | Map $buildCommand() => { 34 | keyInsert: collection!.collectionName, 35 | keyDocuments: documents 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/insert_operation/insert_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show Db, WriteConcern; 2 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 3 | 4 | class InsertOptions { 5 | /// The WriteConcern for this insert operation 6 | final WriteConcern? writeConcern; 7 | 8 | /// If true, perform an ordered insert of the documents in the array, 9 | /// and if an error occurs with one of documents, MongoDB will return without 10 | /// processing the remaining documents in the array. 11 | /// 12 | /// If false, perform an unordered insert, and if an error occurs with one of 13 | /// documents, continue processing the remaining documents in the array. 14 | /// 15 | /// Defaults to true. 16 | final bool ordered; 17 | 18 | /// Enables insert to bypass document validation during the operation. 19 | /// This lets you insert documents that do not meet the validation 20 | /// requirements. 21 | /// 22 | /// **New in version 3.2.** 23 | final bool bypassDocumentValidation; 24 | 25 | InsertOptions( 26 | {this.writeConcern, 27 | bool? ordered = true, 28 | bool? bypassDocumentValidation = false}) 29 | : ordered = ordered ?? true, 30 | bypassDocumentValidation = bypassDocumentValidation ?? false; 31 | 32 | // The db parameter is used to transform the writeConcern into a Map 33 | /// When a writeConcern is given a Db object must be specified 34 | Map getOptions(Db db) { 35 | return { 36 | if (writeConcern != null) 37 | keyWriteConcern: writeConcern!.asMap(db.masterConnection.serverStatus), 38 | if (!ordered) keyOrdered: ordered, 39 | if (bypassDocumentValidation) 40 | keyBypassDocumentValidation: bypassDocumentValidation, 41 | }; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/return_classes/bulk_write_error.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 2 | 3 | import 'write_error.dart'; 4 | 5 | class BulkWriteError extends WriteError { 6 | int? index; 7 | int? operationInputIndex; 8 | 9 | BulkWriteError.fromMap(super.bulkWriteErrorMap) 10 | : index = bulkWriteErrorMap[keyIndex] as int?, 11 | operationInputIndex = bulkWriteErrorMap[keyOperationInputIndex] as int?, 12 | super.fromMap(); 13 | } 14 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/return_classes/last_error_object.dart: -------------------------------------------------------------------------------- 1 | import 'package:bson/bson.dart'; 2 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 3 | 4 | class LastErrorObject { 5 | /// Contains true if an update operation modified an existing document. 6 | bool updatedExisting; 7 | 8 | /// Contains the ObjectId of the inserted document if an update 9 | /// operation with upsert: true resulted in a new document. 10 | ObjectId? upserted; 11 | 12 | int? n; 13 | 14 | LastErrorObject.fromMap(Map document) 15 | : updatedExisting = document[keyUpdatedExisting] as bool? ?? false { 16 | upserted = document[keyUpserted] as ObjectId?; 17 | n = document[keyN] as int?; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/return_classes/upserted_info.dart: -------------------------------------------------------------------------------- 1 | class UpsertedInfo { 2 | int? index; 3 | dynamic id; 4 | } 5 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/return_classes/write_concern_error.dart: -------------------------------------------------------------------------------- 1 | import 'write_error.dart'; 2 | 3 | class WriteConcernError extends WriteError { 4 | Map? errInfo; 5 | 6 | WriteConcernError.fromMap(super.writeConcernErrorMap) : super.fromMap(); 7 | } 8 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/return_classes/write_error.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 2 | 3 | /// contains information regarding any error, excluding write concern errors, 4 | /// encountered during the write operation. 5 | class WriteError { 6 | /// An integer value identifying the error. 7 | final int? code; 8 | 9 | /// A description of the error. 10 | final String? errmsg; 11 | 12 | WriteError(this.code, this.errmsg); 13 | 14 | WriteError.fromMap(Map writeErrorMap) 15 | : code = writeErrorMap[keyCode] as int?, 16 | errmsg = writeErrorMap[keyErrmsg] as String?; 17 | } 18 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/return_classes/write_result.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 2 | 3 | import 'abstract_write_result.dart'; 4 | import 'write_error.dart'; 5 | 6 | /// A wrapper that contains the result status of the mongo shell write methods: 7 | /// - insert 8 | /// - update 9 | /// - remove 10 | /// - save 11 | class WriteResult extends AbstractWriteResult { 12 | dynamic id; 13 | Map? document; 14 | WriteError? writeError; 15 | 16 | WriteResult.fromMap( 17 | WriteCommandType writeCommandType, Map result) 18 | : super.fromMap(writeCommandType, result) { 19 | if (result[keyWriteErrors] != null && 20 | (result[keyWriteErrors] as List).isNotEmpty) { 21 | writeError = WriteError.fromMap( 22 | {...?(result[keyWriteErrors] as List).first}); 23 | } 24 | } 25 | 26 | @override 27 | bool get hasWriteErrors => writeError != null; 28 | 29 | @override 30 | int get writeErrorsNumber => hasWriteErrors ? 1 : 0; 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/update_operation/update_operation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show DbCollection; 2 | import 'package:mongo_dart/src/database/commands/base/operation_base.dart'; 3 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/update_operation/update_statement.dart'; 4 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 5 | 6 | import 'update_options.dart'; 7 | import '../../base/command_operation.dart'; 8 | 9 | class UpdateOperation extends CommandOperation { 10 | UpdateOperation(DbCollection collection, this.updates, 11 | {bool? ordered, 12 | UpdateOptions? updateOptions, 13 | Map? rawOptions}) 14 | : ordered = ordered ?? true, 15 | super( 16 | collection.db, 17 | { 18 | ...?updateOptions?.getOptions(collection.db), 19 | ...?rawOptions 20 | }, 21 | collection: collection, 22 | aspect: Aspect.writeOperation); 23 | 24 | /// An array of one or more update statements to perform on the 25 | /// named collection. 26 | List updates; 27 | 28 | /// If true, then when an update statement fails, return without performing 29 | /// the remaining update statements. If false, then when an update fails, 30 | /// continue with the remaining update statements, if any. 31 | /// Defaults to true. 32 | bool ordered; 33 | 34 | @override 35 | Map $buildCommand() => { 36 | keyUpdate: collection!.collectionName, 37 | keyUpdates: [for (var request in updates) request.toMap()], 38 | if (ordered) keyOrdered: ordered, 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/update_operation/update_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | class UpdateOptions { 4 | /// A document expressing the [write concern](https://docs.mongodb.com/manual/reference/write-concern/). 5 | /// of the update operation. Omit to use the default write concern. 6 | /// 7 | /// Do not explicitly set the write concern for the operation if run 8 | /// in a transaction. To use write concern with transactions, 9 | /// see [Transactions and Write Concern.](https://docs.mongodb.com/manual/core/transactions/#transactions-write-concern) 10 | WriteConcern? writeConcern; 11 | 12 | /// Enables update to bypass document validation during the operation. 13 | /// This lets you update documents that do not meet the validation 14 | /// requirements. 15 | /// 16 | /// New in version 3.2. 17 | bool bypassDocumentValidation; 18 | 19 | /// A user-provided comment to attach to this command. Once set, 20 | /// this comment appears alongside records of this command in the 21 | /// following locations: 22 | /// * mongod log messages, in the attr.command.cursor.comment field. 23 | /// * Database profiler output, in the command.comment field. 24 | /// * currentOp output, in the command.comment field. 25 | /// 26 | /// A comment can be only of type String unlike MongoDb that allows 27 | /// any valid BSON type 28 | /// 29 | /// New in version 4.4. 30 | final String? comment; 31 | 32 | UpdateOptions( 33 | {this.writeConcern, bool? bypassDocumentValidation, this.comment}) 34 | : bypassDocumentValidation = bypassDocumentValidation ?? false; 35 | Map getOptions(Db db) => { 36 | if (bypassDocumentValidation) 37 | keyBypassDocumentValidation: bypassDocumentValidation, 38 | if (writeConcern != null) 39 | keyWriteConcern: 40 | writeConcern!.asMap(db.masterConnection.serverStatus), 41 | if (comment != null) keyComment: comment!, 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/bulk/bulk_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show Db, WriteConcern; 2 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 3 | 4 | class BulkOptions { 5 | /// The WriteConcern for this insert operation 6 | final WriteConcern? writeConcern; 7 | 8 | /// If true, perform an ordered insert of the documents in the array, 9 | /// and if an error occurs with one of documents, MongoDB will return without 10 | /// processing the remaining documents in the array. 11 | /// 12 | /// If false, perform an unordered insert, and if an error occurs with one of 13 | /// documents, continue processing the remaining documents in the array. 14 | /// 15 | /// Defaults to true. 16 | final bool ordered; 17 | 18 | /// Enables insert to bypass document validation during the operation. 19 | /// This lets you insert documents that do not meet the validation 20 | /// requirements. 21 | /// 22 | /// **New in version 3.2.** 23 | final bool bypassDocumentValidation; 24 | 25 | BulkOptions( 26 | {this.writeConcern, bool? ordered, bool? bypassDocumentValidation}) 27 | : ordered = ordered ?? true, 28 | bypassDocumentValidation = bypassDocumentValidation ?? false; 29 | 30 | // The db parameter is used to transform the writeConcern into a Map 31 | /// When a writeConcern is given a Db object must be specified 32 | Map getOptions(Db db) { 33 | return { 34 | if (writeConcern != null) 35 | keyWriteConcern: writeConcern!.asMap(db.masterConnection.serverStatus), 36 | if (!ordered) keyOrdered: ordered, 37 | if (bypassDocumentValidation) 38 | keyBypassDocumentValidation: bypassDocumentValidation, 39 | }; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/delete_many/delete_many_operation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show DbCollection; 2 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/delete_operation/delete_operation.dart'; 3 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/abstract_write_result.dart'; 4 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/write_result.dart'; 5 | 6 | import 'delete_many_options.dart'; 7 | import 'delete_many_statement.dart'; 8 | 9 | class DeleteManyOperation extends DeleteOperation { 10 | //DeleteManyStatement deleteRequest; 11 | 12 | DeleteManyOperation( 13 | DbCollection collection, DeleteManyStatement deleteRequest, 14 | {DeleteManyOptions? deleteManyOptions, Map? rawOptions}) 15 | : super( 16 | collection, 17 | [deleteRequest], 18 | deleteOptions: deleteManyOptions, 19 | rawOptions: rawOptions, 20 | ); 21 | 22 | Future executeDocument() async { 23 | var ret = await super.execute(); 24 | return WriteResult.fromMap(WriteCommandType.delete, ret); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/delete_many/delete_many_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/delete_operation/delete_options.dart'; 2 | 3 | class DeleteManyOptions extends DeleteOptions { 4 | DeleteManyOptions({super.writeConcern, super.comment}); 5 | } 6 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/delete_many/delete_many_statement.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/delete_operation/delete_statement.dart'; 2 | 3 | class DeleteManyStatement extends DeleteStatement { 4 | DeleteManyStatement(super.filter, 5 | {super.collation, super.hint, super.hintDocument}) 6 | : super(limit: 0); 7 | } 8 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/delete_one/delete_one_operation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show DbCollection; 2 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/delete_operation/delete_operation.dart'; 3 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/abstract_write_result.dart'; 4 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/write_result.dart'; 5 | 6 | import 'delete_one_options.dart'; 7 | import 'delete_one_statement.dart'; 8 | 9 | class DeleteOneOperation extends DeleteOperation { 10 | //DeleteOneStatement deleteRequest; 11 | 12 | DeleteOneOperation(DbCollection collection, DeleteOneStatement deleteRequest, 13 | {DeleteOneOptions? deleteOneOptions, Map? rawOptions}) 14 | : super( 15 | collection, 16 | [deleteRequest], 17 | deleteOptions: deleteOneOptions, 18 | rawOptions: rawOptions, 19 | ); 20 | 21 | Future executeDocument() async { 22 | var ret = await super.execute(); 23 | return WriteResult.fromMap(WriteCommandType.delete, ret); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/delete_one/delete_one_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/delete_operation/delete_options.dart'; 2 | 3 | class DeleteOneOptions extends DeleteOptions { 4 | DeleteOneOptions({super.writeConcern, super.comment}); 5 | } 6 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/delete_one/delete_one_statement.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/delete_operation/delete_statement.dart'; 2 | 3 | class DeleteOneStatement extends DeleteStatement { 4 | DeleteOneStatement(super.filter, 5 | {super.collation, super.hint, super.hintDocument}) 6 | : super(limit: 1); 7 | } 8 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/insert_many/insert_many_operation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show DbCollection; 2 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/insert_operation/insert_operation.dart'; 3 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/abstract_write_result.dart'; 4 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/bulk_write_result.dart'; 5 | 6 | import 'insert_many_options.dart'; 7 | 8 | class InsertManyOperation extends InsertOperation { 9 | InsertManyOperation( 10 | DbCollection collection, List> documents, 11 | {InsertManyOptions? insertManyOptions, Map? rawOptions}) 12 | : super( 13 | collection, 14 | documents, 15 | insertOptions: insertManyOptions, 16 | rawOptions: rawOptions, 17 | ) { 18 | if (documents.isEmpty) { 19 | throw ArgumentError( 20 | 'At least one document required in InsertManyOperation'); 21 | } 22 | } 23 | 24 | Future executeDocument() async { 25 | var ret = await super.execute(); 26 | return BulkWriteResult.fromMap(WriteCommandType.insert, ret) 27 | ..ids = ids 28 | ..documents = documents; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/insert_many/insert_many_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/insert_operation/insert_options.dart'; 2 | 3 | class InsertManyOptions extends InsertOptions { 4 | InsertManyOptions( 5 | {super.writeConcern, 6 | super.ordered = null, 7 | super.bypassDocumentValidation = null}); 8 | } 9 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/insert_one/insert_one_operation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show DbCollection; 2 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/insert_operation/insert_operation.dart'; 3 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/abstract_write_result.dart'; 4 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/write_result.dart'; 5 | 6 | import 'insert_one_options.dart'; 7 | 8 | class InsertOneOperation extends InsertOperation { 9 | Map document; 10 | 11 | InsertOneOperation(DbCollection collection, this.document, 12 | {InsertOneOptions? insertOneOptions, Map? rawOptions}) 13 | : super( 14 | collection, 15 | [document], 16 | insertOptions: insertOneOptions, 17 | rawOptions: rawOptions, 18 | ); 19 | 20 | Future executeDocument() async { 21 | var ret = await super.execute(); 22 | return WriteResult.fromMap(WriteCommandType.insert, ret) 23 | ..id = ids.first 24 | ..document = documents.first; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/insert_one/insert_one_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/insert_operation/insert_options.dart'; 2 | 3 | class InsertOneOptions extends InsertOptions { 4 | InsertOneOptions({super.writeConcern, super.bypassDocumentValidation = null}); 5 | } 6 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/replace_one/replace_one_operation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show DbCollection; 2 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/abstract_write_result.dart'; 3 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/write_result.dart'; 4 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/update_operation/update_operation.dart'; 5 | 6 | import 'replace_one_options.dart'; 7 | import 'replace_one_statement.dart'; 8 | 9 | class ReplaceOneOperation extends UpdateOperation { 10 | //ReplaceOneStatement replaceOneStatement; 11 | 12 | ReplaceOneOperation( 13 | DbCollection collection, ReplaceOneStatement replaceOneStatement, 14 | {ReplaceOneOptions? replaceOneOptions, Map? rawOptions}) 15 | : super( 16 | collection, 17 | [replaceOneStatement], 18 | ordered: false, 19 | updateOptions: replaceOneOptions, 20 | rawOptions: rawOptions, 21 | ); 22 | 23 | Future executeDocument() async { 24 | var ret = await super.execute(); 25 | return WriteResult.fromMap(WriteCommandType.update, ret); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/replace_one/replace_one_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/update_operation/update_options.dart'; 2 | 3 | class ReplaceOneOptions extends UpdateOptions { 4 | ReplaceOneOptions( 5 | {super.writeConcern, super.bypassDocumentValidation, super.comment}); 6 | } 7 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/replace_one/replace_one_statement.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/update_operation/update_statement.dart'; 3 | import 'package:mongo_dart/src/database/utils/update_document_check.dart'; 4 | 5 | class ReplaceOneStatement extends UpdateStatement { 6 | ReplaceOneStatement(Map q, Map u, 7 | {bool? upsert, 8 | CollationOptions? collation, 9 | String? hint, 10 | Map? hintDocument}) 11 | : super(q, u, 12 | upsert: upsert, 13 | multi: false, 14 | collation: collation, 15 | hint: hint, 16 | hintDocument: hintDocument) { 17 | if (!isPureDocument(u)) { 18 | throw MongoDartError('Invalid document in ReplaceOneStatement. ' 19 | 'The document is either null or contains update operators'); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/update_many/update_many_operation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show DbCollection; 2 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/abstract_write_result.dart'; 3 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/write_result.dart'; 4 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/update_operation/update_operation.dart'; 5 | 6 | import 'update_many_options.dart'; 7 | import 'update_many_statement.dart'; 8 | 9 | class UpdateManyOperation extends UpdateOperation { 10 | //UpdateManyStatement updateRequest; 11 | 12 | UpdateManyOperation( 13 | DbCollection collection, UpdateManyStatement updateManyStatement, 14 | {bool? ordered, 15 | UpdateManyOptions? updateManyOptions, 16 | Map? rawOptions}) 17 | : super( 18 | collection, 19 | [updateManyStatement], 20 | ordered: ordered, 21 | updateOptions: updateManyOptions, 22 | rawOptions: rawOptions, 23 | ); 24 | 25 | Future executeDocument() async { 26 | var ret = await super.execute(); 27 | return WriteResult.fromMap(WriteCommandType.update, ret); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/update_many/update_many_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/update_operation/update_options.dart'; 2 | 3 | class UpdateManyOptions extends UpdateOptions { 4 | UpdateManyOptions( 5 | {super.writeConcern, super.bypassDocumentValidation, super.comment}); 6 | } 7 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/update_many/update_many_statement.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/update_operation/update_statement.dart'; 2 | 3 | class UpdateManyStatement extends UpdateStatement { 4 | UpdateManyStatement(super.q, super.u, 5 | {super.upsert, 6 | super.collation, 7 | super.arrayFilters, 8 | super.hint, 9 | super.hintDocument}) 10 | : super(multi: true); 11 | } 12 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/update_one/update_one_operation.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show DbCollection; 2 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/abstract_write_result.dart'; 3 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/return_classes/write_result.dart'; 4 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/update_operation/update_operation.dart'; 5 | 6 | import 'update_one_options.dart'; 7 | import 'update_one_statement.dart'; 8 | 9 | class UpdateOneOperation extends UpdateOperation { 10 | //UpdateOneStatement updateRequest; 11 | 12 | UpdateOneOperation( 13 | DbCollection collection, UpdateOneStatement updateOneStatement, 14 | {UpdateOneOptions? updateOneOptions, Map? rawOptions}) 15 | : super( 16 | collection, 17 | [updateOneStatement], 18 | ordered: false, 19 | updateOptions: updateOneOptions, 20 | rawOptions: rawOptions, 21 | ); 22 | 23 | Future executeDocument() async { 24 | var ret = await super.execute(); 25 | return WriteResult.fromMap(WriteCommandType.update, ret); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/update_one/update_one_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/update_operation/update_options.dart'; 2 | 3 | class UpdateOneOptions extends UpdateOptions { 4 | UpdateOneOptions( 5 | {super.writeConcern, super.bypassDocumentValidation, super.comment}); 6 | } 7 | -------------------------------------------------------------------------------- /lib/src/database/commands/query_and_write_operation_commands/wrapper/update_one/update_one_statement.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import 'package:mongo_dart/src/database/commands/query_and_write_operation_commands/update_operation/update_statement.dart'; 3 | import 'package:mongo_dart/src/database/utils/update_document_check.dart'; 4 | 5 | class UpdateOneStatement extends UpdateStatement { 6 | UpdateOneStatement(Map q, Object u, 7 | {bool? upsert, 8 | CollationOptions? collation, 9 | List? arrayFilters, 10 | String? hint, 11 | Map? hintDocument}) 12 | : super(q, u, 13 | upsert: upsert, 14 | multi: false, 15 | collation: collation, 16 | arrayFilters: arrayFilters, 17 | hint: hint, 18 | hintDocument: hintDocument) { 19 | if (u is Map && !containsOnlyUpdateOperators(u)) { 20 | throw MongoDartError('Invalid document in UpdateOneStatement. ' 21 | 'The document is either null or contains invalid update operators'); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/src/database/commands/replication_commands/hello_command/client_metadata.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io' show Platform; 2 | import 'package:mongo_dart/src/version.dart'; 3 | import 'package:mongo_dart/src/database/utils/map_keys.dart'; 4 | 5 | /// Represents the client metadata that can be provided to the initial 6 | /// handshake (hello). 7 | class ClientMetadata { 8 | final DriverMetadata driver = DriverMetadata(); 9 | final OsMetadata os = OsMetadata(); 10 | final String platform = 'dart ${Platform.version}'; 11 | final ApplicationMetadata application; 12 | 13 | ClientMetadata(this.application); 14 | 15 | Map get options => { 16 | keyClient: { 17 | keyDriver: driver.asMap(), 18 | keyOs: os.asMap(), 19 | keyPlatform: platform, 20 | keyApplication: application.asMap(), 21 | } 22 | }; 23 | } 24 | 25 | /// Information about the driver itself. 26 | class DriverMetadata { 27 | final String name = mongoDartName; 28 | final String version = mongoDartVersion; 29 | 30 | Map asMap() { 31 | return {keyName: name, keyVersion: version}; 32 | } 33 | } 34 | 35 | /// Information about the operating system. 36 | class OsMetadata { 37 | final String type = Platform.operatingSystem; 38 | // We cannot get these 3 without some I/O, so they are always left out. 39 | final String? name; 40 | final String? architecture; 41 | final String? version; 42 | 43 | OsMetadata({this.name, this.architecture, this.version}); 44 | 45 | Map asMap() { 46 | return {keyType: type}; 47 | } 48 | } 49 | 50 | /// Application information, only a descriptive name. 51 | class ApplicationMetadata { 52 | final String name; 53 | 54 | ApplicationMetadata(String name) 55 | : name = name.length > 128 ? name.substring(0, 128) : name; 56 | 57 | Map asMap() { 58 | return {keyName: name}; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /lib/src/database/error.dart: -------------------------------------------------------------------------------- 1 | part of '../../mongo_dart.dart'; 2 | 3 | class MongoDartError extends Error { 4 | final String message; 5 | final int? mongoCode; 6 | final String? errorCode; 7 | final String? errorCodeName; 8 | 9 | MongoDartError(this.message, 10 | {this.mongoCode, String? errorCode, this.errorCodeName}) 11 | : errorCode = errorCode ?? (mongoCode != null ? '$mongoCode' : null); 12 | 13 | @override 14 | String toString() => 'MongoDart Error: $message'; 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/database/message/mongo_response_message.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' 2 | show BsonBinary, MongoDartError, MongoMessage; 3 | 4 | class MongoResponseMessage extends MongoMessage { 5 | MongoMessage deserialize(BsonBinary buffer) { 6 | throw MongoDartError('Must be implemented'); 7 | } 8 | 9 | static int extractOpcode(BsonBinary buffer) { 10 | buffer.readInt32(); 11 | buffer.readInt32(); 12 | buffer.readInt32(); 13 | var opcodeFromWire = buffer.readInt32(); 14 | buffer.offset -= 16; 15 | return opcodeFromWire; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/src/database/mongo_getmore_message.dart: -------------------------------------------------------------------------------- 1 | part of '../../mongo_dart.dart'; 2 | 3 | class MongoGetMoreMessage extends MongoMessage { 4 | final BsonCString _collectionFullName; 5 | int cursorId; 6 | int numberToReturn; 7 | 8 | MongoGetMoreMessage(String collectionFullName, this.cursorId, 9 | [this.numberToReturn = 20]) 10 | : _collectionFullName = BsonCString(collectionFullName) { 11 | opcode = MongoMessage.getMore; 12 | } 13 | 14 | @override 15 | int get messageLength { 16 | return 16 + 4 + _collectionFullName.totalByteLength + 4 + 8; 17 | } 18 | 19 | @override 20 | BsonBinary serialize() { 21 | var buffer = BsonBinary(messageLength); 22 | writeMessageHeaderTo(buffer); 23 | buffer.writeInt(0); 24 | _collectionFullName.packValue(buffer); 25 | buffer.writeInt(numberToReturn); 26 | buffer.writeInt64(cursorId); 27 | buffer.offset = 0; 28 | return buffer; 29 | } 30 | 31 | @override 32 | String toString() => 'MongoGetMoreMessage($requestId, ' 33 | '${_collectionFullName.value}, $cursorId)'; 34 | } 35 | -------------------------------------------------------------------------------- /lib/src/database/mongo_insert_message.dart: -------------------------------------------------------------------------------- 1 | part of '../../mongo_dart.dart'; 2 | 3 | class MongoInsertMessage extends MongoMessage { 4 | final BsonCString _collectionFullName; 5 | int flags; 6 | final List _documents; 7 | MongoInsertMessage( 8 | String collectionFullName, List> documents, 9 | [this.flags = 0]) 10 | : _collectionFullName = BsonCString(collectionFullName), 11 | _documents = [] { 12 | for (var document in documents) { 13 | _documents.add(BsonMap(document)); 14 | } 15 | opcode = MongoMessage.insert; 16 | } 17 | 18 | @override 19 | int get messageLength { 20 | var docsSize = 0; 21 | for (var doc in _documents) { 22 | docsSize += doc.totalByteLength; 23 | } 24 | var result = 16 + 4 + _collectionFullName.totalByteLength + docsSize; 25 | return result; 26 | } 27 | 28 | @override 29 | BsonBinary serialize() { 30 | var buffer = BsonBinary(messageLength); 31 | writeMessageHeaderTo(buffer); 32 | buffer.writeInt(flags); 33 | _collectionFullName.packValue(buffer); 34 | for (var doc in _documents) { 35 | doc.packValue(buffer); 36 | } 37 | buffer.offset = 0; 38 | return buffer; 39 | } 40 | 41 | @override 42 | String toString() { 43 | if (_documents.length == 1) { 44 | return 'MongoInserMessage($requestId, ' 45 | '${_collectionFullName.value}, ${_documents[0].value})'; 46 | } 47 | return 'MongoInserMessage($requestId, ' 48 | '${_collectionFullName.value}, ${_documents.length} documents)'; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/src/database/mongo_kill_cursors_message.dart: -------------------------------------------------------------------------------- 1 | part of '../../mongo_dart.dart'; 2 | 3 | class MongoKillCursorsMessage extends MongoMessage { 4 | int cursorId; 5 | 6 | MongoKillCursorsMessage(this.cursorId) { 7 | opcode = MongoMessage.killCursors; 8 | } 9 | 10 | @override 11 | int get messageLength { 12 | return 16 + 4 + 4 + 8; 13 | } 14 | 15 | @override 16 | BsonBinary serialize() { 17 | var buffer = BsonBinary(messageLength); 18 | writeMessageHeaderTo(buffer); 19 | buffer.writeInt(0); 20 | buffer.writeInt(1); 21 | buffer.writeInt64(cursorId); 22 | buffer.offset = 0; 23 | return buffer; 24 | } 25 | 26 | @override 27 | String toString() { 28 | return 'MongoKillCursorsMessage($requestId, $cursorId)'; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/database/mongo_message.dart: -------------------------------------------------------------------------------- 1 | part of '../../mongo_dart.dart'; 2 | 3 | class _Statics { 4 | static int? _requestId; 5 | static int get nextRequestId { 6 | _requestId ??= 1; 7 | _requestId = _requestId! + 1; 8 | return _requestId!; 9 | } 10 | } 11 | 12 | class MongoMessage { 13 | static final reply = 1; 14 | static final message = 1000; 15 | static final update = 2001; 16 | static final insert = 2002; 17 | static final query = 2004; 18 | static final getMore = 2005; 19 | static final delete = 2006; 20 | static final killCursors = 2007; 21 | static final modernMessage = 2013; 22 | 23 | int? _requestId; 24 | int _messageLength = 0; 25 | 26 | int get messageLength => _messageLength; 27 | 28 | int get requestId { 29 | _requestId ??= _Statics.nextRequestId; 30 | 31 | return _requestId!; 32 | } 33 | 34 | int responseTo = 0; 35 | int opcode = MongoMessage.reply; 36 | 37 | BsonBinary serialize() => throw MongoDartError('Must be implemented'); 38 | 39 | /* void deserialize(BsonBinary buffer) { 40 | throw MongoDartError('Must be implemented'); 41 | }*/ 42 | 43 | void readMessageHeaderFrom(BsonBinary buffer) { 44 | _messageLength = buffer.readInt32(); 45 | _requestId = buffer.readInt32(); 46 | responseTo = buffer.readInt32(); 47 | var opcodeFromWire = buffer.readInt32(); 48 | if (opcodeFromWire != opcode) { 49 | throw MongoDartError( 50 | 'Expected $opcode in Message header. Got $opcodeFromWire'); 51 | } 52 | } 53 | 54 | void writeMessageHeaderTo(BsonBinary buffer) { 55 | buffer.writeInt(messageLength); // messageLength will be backpatched later 56 | buffer.writeInt(requestId); 57 | buffer.writeInt(0); // responseTo not used in requests sent by client 58 | buffer.writeInt(opcode); 59 | if (messageLength < 0) { 60 | throw MongoDartError('Error in message length'); 61 | } 62 | } 63 | 64 | @override 65 | String toString() => throw MongoDartError('must be implemented'); 66 | } 67 | -------------------------------------------------------------------------------- /lib/src/database/mongo_query_message.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: non_constant_identifier_names 2 | 3 | part of '../../mongo_dart.dart'; 4 | 5 | class MongoQueryMessage extends MongoMessage { 6 | static final OPTS_NONE = 0; 7 | static final OPTS_TAILABLE_CURSOR = 2; 8 | static final OPTS_SLAVE = 4; 9 | static final OPTS_OPLOG_REPLY = 8; 10 | static final OPTS_NO_CURSOR_TIMEOUT = 16; 11 | static final OPTS_AWAIT_DATA = 32; 12 | static final OPTS_EXHAUST = 64; 13 | static final OPTS_PARTIAL = 128; 14 | 15 | BsonCString? _collectionFullName; 16 | int flags; 17 | int numberToSkip; 18 | int numberToReturn; 19 | late BsonMap _query; 20 | BsonMap? _fields; 21 | BsonCString? get collectionNameBson => _collectionFullName; 22 | 23 | MongoQueryMessage( 24 | String? collectionFullName, 25 | this.flags, 26 | this.numberToSkip, 27 | this.numberToReturn, 28 | Map query, 29 | Map? fields) { 30 | if (collectionFullName != null) { 31 | _collectionFullName = BsonCString(collectionFullName); 32 | } 33 | _query = BsonMap(query); 34 | if (fields != null) { 35 | _fields = BsonMap(fields); 36 | } 37 | opcode = MongoMessage.query; 38 | } 39 | 40 | @override 41 | int get messageLength { 42 | var result = 16 + 43 | 4 + 44 | (_collectionFullName?.totalByteLength ?? 0) + 45 | 4 + 46 | 4 + 47 | _query.totalByteLength; 48 | if (_fields != null) { 49 | result += _fields!.totalByteLength; 50 | } 51 | return result; 52 | } 53 | 54 | @override 55 | BsonBinary serialize() { 56 | var buffer = BsonBinary(messageLength); 57 | writeMessageHeaderTo(buffer); 58 | buffer.writeInt(flags); 59 | _collectionFullName?.packValue(buffer); 60 | buffer.writeInt(numberToSkip); 61 | buffer.writeInt(numberToReturn); 62 | _query.packValue(buffer); 63 | if (_fields != null) { 64 | _fields!.packValue(buffer); 65 | } 66 | buffer.offset = 0; 67 | return buffer; 68 | } 69 | 70 | @override 71 | String toString() => 'MongoQueryMessage($requestId, ' 72 | '${_collectionFullName?.value ?? ''},numberToReturn:$numberToReturn, ' 73 | '${_query.value})'; 74 | } 75 | -------------------------------------------------------------------------------- /lib/src/database/mongo_remove_message.dart: -------------------------------------------------------------------------------- 1 | part of '../../mongo_dart.dart'; 2 | 3 | class MongoRemoveMessage extends MongoMessage { 4 | final BsonCString _collectionFullName; 5 | int flags; 6 | final BsonMap _selector; 7 | 8 | MongoRemoveMessage(String collectionFullName, 9 | [Map selector = const {}, this.flags = 0]) 10 | : _collectionFullName = BsonCString(collectionFullName), 11 | _selector = BsonMap(selector) { 12 | opcode = MongoMessage.delete; 13 | } 14 | 15 | @override 16 | int get messageLength { 17 | return 16 + 18 | 4 + 19 | _collectionFullName.totalByteLength + 20 | 4 + 21 | _selector.totalByteLength; 22 | } 23 | 24 | @override 25 | BsonBinary serialize() { 26 | var buffer = BsonBinary(messageLength); 27 | writeMessageHeaderTo(buffer); 28 | buffer.writeInt(0); 29 | _collectionFullName.packValue(buffer); 30 | buffer.writeInt(flags); 31 | _selector.packValue(buffer); 32 | buffer.offset = 0; 33 | return buffer; 34 | } 35 | 36 | @override 37 | String toString() => 'MongoRemoveMessage($requestId, ' 38 | '${_collectionFullName.value}, ${_selector.value})'; 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/database/mongo_update_message.dart: -------------------------------------------------------------------------------- 1 | part of '../../mongo_dart.dart'; 2 | 3 | class MongoUpdateMessage extends MongoMessage { 4 | final BsonCString _collectionFullName; 5 | int flags; 6 | //int numberToSkip; 7 | //int numberToReturn; 8 | final BsonMap _selector; 9 | late BsonMap _document; 10 | 11 | MongoUpdateMessage(String collectionFullName, Map selector, 12 | document, this.flags) 13 | : _collectionFullName = BsonCString(collectionFullName), 14 | _selector = BsonMap(selector) { 15 | if (document is ModifierBuilder) { 16 | document = document.map; 17 | } 18 | _document = BsonMap(document as Map); 19 | opcode = MongoMessage.update; 20 | } 21 | 22 | @override 23 | int get messageLength { 24 | return 16 + 25 | 4 + 26 | _collectionFullName.totalByteLength + 27 | 4 + 28 | _selector.totalByteLength + 29 | _document.totalByteLength; 30 | } 31 | 32 | @override 33 | BsonBinary serialize() { 34 | var buffer = BsonBinary(messageLength); 35 | writeMessageHeaderTo(buffer); 36 | buffer.writeInt(0); 37 | _collectionFullName.packValue(buffer); 38 | buffer.writeInt(flags); 39 | _selector.packValue(buffer); 40 | _document.packValue(buffer); 41 | buffer.offset = 0; 42 | return buffer; 43 | } 44 | 45 | @override 46 | String toString() => 'MongoUpdateMessage($requestId, ' 47 | '${_collectionFullName.value}, ${_selector.value}, ${_document.value})'; 48 | } 49 | -------------------------------------------------------------------------------- /lib/src/database/server_config.dart: -------------------------------------------------------------------------------- 1 | part of '../../mongo_dart.dart'; 2 | 3 | class ServerConfig { 4 | String host; 5 | int port; 6 | bool isSecure; 7 | bool tlsAllowInvalidCertificates; 8 | Uint8List? tlsCAFileContent; 9 | Uint8List? tlsCertificateKeyFileContent; 10 | String? tlsCertificateKeyFilePassword; 11 | 12 | String? userName; 13 | String? password; 14 | 15 | bool isAuthenticated = false; 16 | ClientMetadata? clientMetadata; 17 | 18 | ServerConfig( 19 | {this.host = '127.0.0.1', 20 | this.port = Db.mongoDefaultPort, 21 | bool? isSecure, 22 | bool? tlsAllowInvalidCertificates, 23 | this.tlsCAFileContent, 24 | this.tlsCertificateKeyFileContent, 25 | this.tlsCertificateKeyFilePassword, 26 | this.clientMetadata}) 27 | : isSecure = isSecure ?? false, 28 | tlsAllowInvalidCertificates = tlsAllowInvalidCertificates ?? false; 29 | String get hostUrl => '$host:${port.toString()}'; 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/database/state.dart: -------------------------------------------------------------------------------- 1 | part of '../../mongo_dart.dart'; 2 | 3 | class State { 4 | final String _value; 5 | const State._internal(this._value); 6 | @override 7 | String toString() => 'State.$_value'; 8 | 9 | static const init = State._internal('INIT'); 10 | static const opening = State._internal('OPENING'); 11 | static const open = State._internal('OPEN'); 12 | static const closing = State._internal('CLOSING'); 13 | static const closed = State._internal('CLOSED'); 14 | 15 | // For compatibility reasons 16 | 17 | @Deprecated('Use init instead') 18 | // ignore: constant_identifier_names 19 | static const INIT = init; 20 | 21 | @Deprecated('Use opening instead') 22 | // ignore: constant_identifier_names 23 | static const OPENING = opening; 24 | 25 | @Deprecated('Use open instead') 26 | // ignore: constant_identifier_names 27 | static const OPEN = open; 28 | 29 | @Deprecated('Use closing instead') 30 | // ignore: constant_identifier_names 31 | static const CLOSING = closing; 32 | 33 | @Deprecated('Use closed instead') 34 | // ignore: constant_identifier_names 35 | static const CLOSED = closed; 36 | } 37 | -------------------------------------------------------------------------------- /lib/src/database/utils/check_same_domain.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | bool checkSameDomain(Uri uri, Uri checkUri) { 4 | var uriParts = uri.host.split('.'); 5 | var checkParts = checkUri.host.split('.'); 6 | if (uriParts.length < 2) { 7 | throw MongoDartError('At list a domain is required, but got "${uri.host}"'); 8 | } 9 | if (checkParts.length < 2) { 10 | throw MongoDartError( 11 | 'At list a domain is required, but got "${checkUri.host}"'); 12 | } 13 | return uriParts.last == checkParts.last && 14 | uriParts[uriParts.length - 2] == checkParts[checkParts.length - 2]; 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/database/utils/mongo_db_namespace.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | class MongoDBNamespace { 4 | final String db; 5 | final String? collection; 6 | 7 | MongoDBNamespace(this.db, {this.collection}); 8 | 9 | factory MongoDBNamespace.fromString(String namespace) { 10 | var parts = namespace.split('.'); 11 | return MongoDBNamespace(parts.first, 12 | collection: parts.length > 1 ? parts[1] : null); 13 | } 14 | 15 | factory MongoDBNamespace.fromMap(Map namespaceMap) { 16 | if (namespaceMap[keyDb] == null) { 17 | throw MongoDartError('Missing database name (element $keyDb) in Map'); 18 | } 19 | return MongoDBNamespace(namespaceMap[keyDb] as String, 20 | collection: namespaceMap[keyColl] as String?); 21 | } 22 | 23 | @override 24 | String toString() { 25 | var collectionName = collection ?? ''; 26 | if (collectionName.isEmpty) { 27 | return db; 28 | } 29 | return '$db.$collectionName'; 30 | } 31 | 32 | MongoDBNamespace withCollection(String collection) => 33 | MongoDBNamespace(db, collection: collection); 34 | } 35 | -------------------------------------------------------------------------------- /lib/src/database/utils/parms_utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | Map extractfilterMap(filter) { 4 | if (filter == null) { 5 | return {}; 6 | } 7 | if (filter is SelectorBuilder) { 8 | return {...?filter.map[key$Query]}; 9 | } else if (filter is Map) { 10 | return {...filter}; 11 | } 12 | throw MongoDartError( 13 | 'Filter can only be a Map or a SelectorBuilder instance'); 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/database/utils/split_hosts.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | List splitHosts(String uriString) { 4 | String prefix, suffix; 5 | int startHostsIndex, endServersIndex; 6 | if (uriString.startsWith('mongodb://')) { 7 | startHostsIndex = 'mongodb://'.length; 8 | } else { 9 | throw MongoDartError('Unexpected scheme in url "$uriString". ' 10 | 'The url is expected to start with "mongodb://"'); 11 | } 12 | endServersIndex = uriString.indexOf('/', startHostsIndex); 13 | if (endServersIndex == -1) { 14 | endServersIndex = uriString.length; 15 | suffix = ''; 16 | } else { 17 | suffix = uriString.substring(endServersIndex).trim(); 18 | } 19 | var hostsString = uriString.substring(startHostsIndex, endServersIndex); 20 | var credentialsIndex = hostsString.indexOf('@'); 21 | if (credentialsIndex != -1) { 22 | startHostsIndex += credentialsIndex + 1; 23 | hostsString = uriString.substring(startHostsIndex, endServersIndex); 24 | } 25 | prefix = uriString.substring(0, startHostsIndex).trim(); 26 | var parts = hostsString.split(','); 27 | return [for (var server in parts) '$prefix${server.trim()}$suffix']; 28 | } 29 | -------------------------------------------------------------------------------- /lib/src/database/utils/update_document_check.dart: -------------------------------------------------------------------------------- 1 | /// This method returns true if all the top keys are update operators 2 | /// (start with "$"). 3 | /// If the document is null or empty returns false; 4 | /// It is used to check the update document in operations like updateOne() 5 | bool containsOnlyUpdateOperators(Map updateDocument) => 6 | updateDocument.isNotEmpty && 7 | updateDocument.keys 8 | .firstWhere((element) => element[0] != r'$', orElse: () => r'$') == 9 | r'$'; 10 | 11 | /// This method returns true if none of the top keys are update operators 12 | /// (start with "$"). 13 | /// If the document is null or empty returns false; 14 | /// It is used to check the replace document in operations like replaceOne() 15 | bool isPureDocument(Map updateDocument) => 16 | updateDocument.isNotEmpty && 17 | updateDocument.keys 18 | .firstWhere((element) => element[0] == r'$', orElse: () => '#') == 19 | '#'; 20 | -------------------------------------------------------------------------------- /lib/src/extensions/file_ext.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'package:path/path.dart' as p; 3 | 4 | extension FileExt on File { 5 | String get name => 6 | path.substring(path.lastIndexOf(Platform.pathSeparator) + 1); 7 | 8 | String newPathByName(String newFileName) => 9 | path.substring(0, path.lastIndexOf(Platform.pathSeparator) + 1) + 10 | newFileName; 11 | 12 | Future get safePath async => toSafePath(path); 13 | 14 | Future toSafePath(String newPath) async { 15 | var basename = p.basenameWithoutExtension(newPath); 16 | var dirname = p.dirname(newPath) + Platform.pathSeparator; 17 | var ext = p.extension(newPath); 18 | 19 | String tryPath = newPath; 20 | File newFile = File(tryPath); 21 | var count = 1; 22 | while (await newFile.exists()) { 23 | tryPath = '$dirname$basename($count)$ext'; 24 | count++; 25 | newFile = File(tryPath); 26 | } 27 | return tryPath; 28 | } 29 | 30 | Future changeFileNameOnly(String newFileName) async => 31 | rename(newPathByName(newFileName)); 32 | 33 | Future changeFileNameOnlySafe(String newFileName) async => 34 | renameSafe(newPathByName(newFileName)); 35 | 36 | Future renameSafe(String newPath) async => 37 | rename(await toSafePath(newPath)); 38 | } 39 | -------------------------------------------------------------------------------- /lib/src/gridfs/gridfs.dart: -------------------------------------------------------------------------------- 1 | part of '../../mongo_dart.dart'; 2 | 3 | class GridFS { 4 | static Int32 defaultChunkSize = Int32(256 * 1024); 5 | static int maxChunkSize = (3.5 * 1000 * 1000).toInt(); 6 | 7 | Db database; 8 | DbCollection files; 9 | DbCollection chunks; 10 | String bucketName; 11 | 12 | GridFS(this.database, [String collection = 'fs']) 13 | : files = database.collection('$collection.files'), 14 | chunks = database.collection('$collection.chunks'), 15 | bucketName = collection; 16 | 17 | // T O D O (tsander): Ensure index. 18 | 19 | Stream> getFileList(SelectorBuilder selectorBuilder) => 20 | files.find(selectorBuilder.sortBy('filename', descending: true)); 21 | 22 | Future findOne(selector) async { 23 | //var completer = Completer(); 24 | var file = await files.findOne(selector); //.then((file) { 25 | 26 | if (file == null) { 27 | return null; 28 | } 29 | return GridOut(this, file); //..setGridFS(this); 30 | //GridOut? result; 31 | //if (file != null) { 32 | // result = GridOut(file); 33 | // result.setGridFS(this); 34 | //} 35 | // completer.complete(result); 36 | //}); 37 | //return completer.future; 38 | } 39 | 40 | Future getFile(String fileName) async => 41 | findOne(where.eq('filename', fileName)); 42 | 43 | GridIn createFile(Stream> input, String filename, 44 | [Map? extraData]) => 45 | GridIn._(this, filename, input, extraData); 46 | 47 | /// **Beware!** This method removes all the documents in this bucket 48 | Future clearBucket() async { 49 | await files.deleteMany({}); 50 | await chunks.deleteMany({}); 51 | } 52 | 53 | /// **Beware!** This method drops this bucket 54 | Future dropBucket() async { 55 | await files.drop(); 56 | await chunks.drop(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /lib/src/network/mongo_message_transformer.dart: -------------------------------------------------------------------------------- 1 | part of '../../mongo_dart.dart'; 2 | 3 | class MongoMessageHandler { 4 | final _log = Logger('MongoMessageTransformer'); 5 | final converter = PacketConverter(); 6 | 7 | void handleData( 8 | /* List */ Uint8List data, EventSink sink) { 9 | converter.addPacket(data); 10 | while (!converter.messages.isEmpty) { 11 | var buffer = BsonBinary.from(converter.messages.removeFirst()); 12 | var opcodeFromWire = MongoResponseMessage.extractOpcode(buffer); 13 | MongoResponseMessage reply; 14 | if (opcodeFromWire == MongoMessage.reply) { 15 | reply = MongoReplyMessage()..deserialize(buffer); 16 | } else { 17 | reply = MongoModernMessage.fromBuffer(buffer); 18 | } 19 | _log.fine(() => reply.toString()); 20 | sink.add(reply); 21 | } 22 | } 23 | 24 | void handleDone(EventSink sink) { 25 | if (!converter.isClear) { 26 | _log.warning( 27 | 'Invalid state of PacketConverter in handleDone: $converter'); 28 | } 29 | sink.close(); 30 | } 31 | 32 | StreamTransformer get transformer => 33 | StreamTransformer.fromHandlers( 34 | handleData: handleData, handleDone: handleDone); 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/version.dart: -------------------------------------------------------------------------------- 1 | const mongoDartVersion = '0.10.5'; 2 | const mongoDartName = 'mongo_dart'; 3 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: mongo_dart 2 | version: 0.10.5 3 | description: MongoDB driver, implemented in pure Dart. All CRUD operations, aggregation pipeline and more! 4 | homepage: https://github.com/mongo-dart/mongo_dart 5 | 6 | environment: 7 | sdk: ">=3.3.0 <4.0.0" 8 | 9 | dependencies: 10 | bson: ^5.0.0 11 | crypto: ^3.0.0 12 | fixnum: ^1.1.0 13 | logging: ^1.0.0 14 | mongo_dart_query: ^5.0.1 15 | collection: ^1.15.0 16 | path: ^1.8.0 17 | pool: ^1.5.0 18 | basic_utils: ^5.2.0 19 | decimal: ^3.1.0 20 | uuid: ^4.0.0 21 | sasl_scram: ^0.1.0 22 | vy_string_utils: ^0.4.0 23 | 24 | dev_dependencies: 25 | test: ^1.16.4 26 | lints: ^5.1.0 27 | 28 | false_secrets: 29 | - /test/certificates_for_testing/*.key 30 | - /test/certificates_for_testing/*.pem 31 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | /packages/ 2 | /gridfs_testdata_out.txt 3 | -------------------------------------------------------------------------------- /test/all_tests.dart: -------------------------------------------------------------------------------- 1 | @Timeout(Duration(minutes: 10)) 2 | library; 3 | 4 | import 'package:test/test.dart'; 5 | 6 | import 'database_test.dart' as database; 7 | import 'gridfs_test.dart' as gridfs; 8 | import 'packet_converter_test.dart' as converter; 9 | import 'mongo_dart_query_test.dart' as mongo_dart_query; 10 | import 'auth_tests/authentication_test.dart' as auth_tests; 11 | //import 'ssl_connection_test.dart' as ssl_tests; 12 | import 'utils_test.dart' as utils_tests; 13 | import 'decimal_test.dart' as decimal; 14 | import 'message_test.dart' as message; 15 | import 'op_msg_bulk_operation_test.dart' as bulk; 16 | import 'op_msg_collection_test.dart' as collection; 17 | import 'op_msg_commands_test.dart' as commands; 18 | import 'op_msg_read_operation_test.dart' as read_op; 19 | import 'op_msg_write_operation_test.dart' as write_op; 20 | 21 | //import 'replica_tests.dart' as replica; 22 | 23 | void main() { 24 | converter.main(); 25 | database.main(); 26 | gridfs.main(); 27 | mongo_dart_query.main(); 28 | auth_tests.main(); 29 | //ssl_tests.main(); 30 | utils_tests.main(); 31 | //replica.main(); 32 | decimal.main(); 33 | message.main(); 34 | bulk.main(); 35 | collection.main(); 36 | commands.main(); 37 | read_op.main(); 38 | write_op.main(); 39 | } 40 | -------------------------------------------------------------------------------- /test/certificates_for_testing/client.mongo.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFrTCCA5WgAwIBAgIUHEn9ONoBjP7VXBQxPdS/USzGVZEwDQYJKoZIhvcNAQEL 3 | BQAwMDELMAkGA1UEBhMCSVQxEzARBgNVBAoMCm1vbmdvLWRhcnQxDDAKBgNVBAsM 4 | A2RldjAeFw0yNTA1MDMwOTI5MjJaFw0yNjA1MDMwOTI5MjJaMEIxCzAJBgNVBAYT 5 | AklUMRMwEQYDVQQKDAptb25nby1kYXJ0MQ8wDQYDVQQLDAZjbGllbnQxDTALBgNV 6 | BAMMBHRlc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCcEmWrio8m 7 | nfJfSjf6IAMncYOESd9zn51OhOpgUqnrSKmCJ9K0d3Z9O9JyGFuDduSsddsmP3cv 8 | 9iG+sJbZZmnYb0CANR/WL9n3hKFjck+7fIRaZvuLseqV7ThDbN29FhXFx8PptnFi 9 | hiJDSqkAaNJ6xIGTdGwC3IMwRZk9Ui1HDNe5arXjMjrCMGdzYg7JovVxWT5pJlbz 10 | wXGwNxJTtTUNDdY603U8Hrmus6Dl88afiHm9xnmTeVjqNTf4YZkKJoTgwKaIQwUo 11 | J1AEMrGTih2qEDPEAiztyC35P39zC0bdeLVoaUVh7Bo/nGrs7X/8CdHha2C3I/jz 12 | 0ufGV0TkDdrMI+TVv77a+NNId00Pdpg6L6B8diZVQ958XhrOf9kJgoosTdDxd4MV 13 | BkkFtIB2s72+F2v+ejDEVivOi2rDB7FxMyTd+qSc5sCMmrPN4SDjgCQgavciwiTS 14 | dmwM/dx05xUxyqkdhA0IWn5RbjTnMAAXwUv1x1HuYPPBqc7BosNwF7CTvyAjyz60 15 | SEDDEMJWNGUJ9nfg6uEDzA8wtekURMnoOAjA2IHQOHnwBfMDLBLdEYQHB9Ad8D0Z 16 | Ne5kgcj+f0L0NsV4OLAa0sTFxlh2yRlWNQ5lxNoLu8OMb9SLdsivCd8t8G5diPzs 17 | P/yh11lBYr4SLXCg0zpx1hO/Bl+YrYNt6wIDAQABo4GsMIGpMB0GA1UdDgQWBBSF 18 | XlV91f6brn7PSGY5UsqR0ClQPjAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIFoDAt 19 | BglghkgBhvhCAQ0EIBYeT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUuMB0G 20 | A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAfBgNVHSMEGDAWgBR8IPV1yw+q 21 | F88hQsLVl+Xy8hV11jANBgkqhkiG9w0BAQsFAAOCAgEAed5X4al0w7fdLluiy8Zg 22 | //uBNY+VUF2B4AwR25jTAnnwPJ1vtXeJnTSZ/6T1qdKE1ItRtDcCOFlNx9vEDksq 23 | PjzngNtuRVSAuilq5+BGp4eoTkakcqz5nr7EBCzemCJqdpSoicnyaxg0dFBsmD35 24 | R3tqMb6XwJESpamHlw53p3113mq6i0IPMBYK2Qf5Y9+X+7BhdWmELgtJRFId3zAU 25 | 2SvqouHp4Ofgsgjfa/JtSLV9dhOxoVUuwSXojnad58rrqbbZot1TrtT/u8Q/Tz7P 26 | 7mECrf9WGinMTsXrCd2k1mgyJGfXy0F2dGlxzkCmbsuaq8jjX0ntFPg+/LuqWh3i 27 | 8nl722w1B/QuWKFz60tIG9vjzmFKBAwfsKI9qDQBASVu5dLBoLf+C4/gj//c2rNX 28 | PKM/NCaa8xg5o5cL2ETSfhnISjPxx14PzuF8YkY3CPpJC+fvDvrOeWqyT1z9SI7+ 29 | NfavA9yD4StMnZv8SmoO7nkcI8izbUaTY+aRLVXhac+9PTttm1Eoj7wkvVgjCETl 30 | 6u9YCOEXiClNFGZI5lk+e8rWSqPb1y0xnGT/3I0ITdypWl2TY15pgHmpwH6fynsj 31 | whO+XFkuqVZPz04Jp4TMLX9UU9+P9/wZwANy9+0L5amWnlzTZhZrqL5yRh0hoMyb 32 | 2lLD6o2CYRHOUtdnd40B+1s= 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /test/certificates_for_testing/instructions.txt: -------------------------------------------------------------------------------- 1 | Action to do for creating test certificates. 2 | 3 | - Copy scripts in a Linux folder. 4 | - Make them executable (ex. chmod u+x authority-certificate.sh) 5 | - run the authority script ./authority-certificate.sh mongo-test 6 | * Answer No (1) for crypt 7 | * Answer IT for country 8 | * Enter (".") for state. 9 | * Enter (".") for locality 10 | * Answer mongo-dart for Organization 11 | * Answer dev for unit name 12 | * Enter (blank) for common name 13 | The data is asked two times. 14 | at the end we should see: 15 | *** 16 | - Create the intermediate certificate .crt. 17 | Certificate request self-signature ok 18 | subject=C = IT, O = mongo-dart, OU = dev 19 | *** 20 | The system creates the cert folder, and inside the following files: 21 | \cert\mongo-test-ia.key 22 | \cert\mongo-test-ca.crt 23 | \cert\mongo-test-ca.key 24 | \cert\mongo-test-ca-full-chain.crt 25 | \cert\mongo-test-ia.crt 26 | 27 | move to the cert folder (cd cert) 28 | - run the server script for 5 servers (server1 server2, etc.) 29 | ../server-certificate.sh mongo-test 127.0.0.1 server1 30 | * Answer No (1) for crypt 31 | * Answer IT for country 32 | * Enter (".") for state. 33 | * Enter (".") for locality 34 | * Answer mongo-dart for Organization 35 | * Answer dev for unit name 36 | * Enter (blank) for common name 37 | 38 | now we create the client certificate. 39 | from inside the cert folder run the following command: 40 | ../client-certificate.sh mongo-test mongo 41 | * Answer No (1) for crypt 42 | * Answer IT for country 43 | * Enter (".") for state. 44 | * Enter (".") for locality 45 | * Answer mongo-dart for Organization 46 | * Answer client for unit name 47 | * Answer test for unit name 48 | 49 | As a result we will see: 50 | Certificate request self-signature ok 51 | subject=C = IT, O = mongo-dart, OU = client, CN = test 52 | 53 | -------------------------------------------------------------------------------- /test/certificates_for_testing/mongo-test-ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /test/certificates_for_testing/mongo-test-ia.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | qQP+2/G96bllpgTLyf2LxA== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /test/certificates_for_testing/server1.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | Lr6qN6VKKCud3UXMoSVpvcAxuPHOsvN8NA== 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /test/certificates_for_testing/server2.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | cwGDEu/A/8pkwwHSnaK2wVKVnWjfbTFy7A== 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /test/certificates_for_testing/server3.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | YkFhRLSqzxCidQcdfjkvTLeTgsGkfZgJaA== 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /test/certificates_for_testing/server4.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | Xa2uUHs6eJ4DZmqEDMhoC71aWt/KwZZZNA== 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /test/certificates_for_testing/server5.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | xbwAnj8dz3Pcw27ecnr0lzSQJxD2RZR/yA== 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /test/client_metadata_test.dart: -------------------------------------------------------------------------------- 1 | @Timeout(Duration(minutes: 1)) 2 | library; 3 | 4 | import 'dart:io' show Platform; 5 | import 'package:mongo_dart/src/version.dart'; 6 | import 'package:mongo_dart/mongo_dart.dart'; 7 | import 'package:mongo_dart/src/database/commands/replication_commands/hello_command/client_metadata.dart'; 8 | import 'package:test/test.dart'; 9 | 10 | void main() async { 11 | group('ClientMetadata', () { 12 | group('#options', () { 13 | var application = ApplicationMetadata('mongo_dart app'); 14 | var clientMetadata = ClientMetadata(application); 15 | var options = clientMetadata.options; 16 | var client = options[keyClient] as Map; 17 | 18 | test('it returns an application name', () { 19 | expect((client[keyApplication] as Map)[keyName], 20 | 'mongo_dart app'); 21 | }); 22 | 23 | test('it returns driver information', () { 24 | expect( 25 | (client[keyDriver] as Map)[keyName], mongoDartName); 26 | expect((client[keyDriver] as Map)[keyVersion], 27 | mongoDartVersion); 28 | }); 29 | 30 | test('it returns os information', () { 31 | expect((client[keyOs] as Map)[keyType], 32 | Platform.operatingSystem); 33 | }); 34 | 35 | test('it returns platform imformation', () { 36 | expect(client[keyPlatform], 'dart ${Platform.version}'); 37 | }); 38 | }); 39 | }); 40 | 41 | group('ApplicationMetadata', () { 42 | group('when the string is under 128 bytes', () { 43 | var appName = 'Application'; 44 | var application = ApplicationMetadata(appName); 45 | 46 | test('it does not truncate the string', () { 47 | expect(application.name, appName); 48 | }); 49 | }); 50 | 51 | group('when the string is over 128 bytes', () { 52 | var longString = '€' * 150; 53 | var application = ApplicationMetadata(longString); 54 | 55 | test('it truncates the string to 128 bytes', () { 56 | expect(application.name.length, 128); 57 | }); 58 | }); 59 | }); 60 | } 61 | -------------------------------------------------------------------------------- /test/connection_pool_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import 'package:test/test.dart'; 3 | import 'database_test.dart'; 4 | 5 | void main() { 6 | late ConnectionPool pool; 7 | 8 | setUp(() { 9 | pool = ConnectionPool(3, () => Db(defaultUri)); 10 | }); 11 | 12 | tearDown(() => pool.close()); 13 | 14 | test('recycles connections', () async { 15 | var db1 = await pool.connect(); 16 | var db2 = await pool.connect(); 17 | var db3 = await pool.connect(); 18 | expect(await pool.connect(), db1); 19 | expect(await pool.connect(), db2); 20 | expect(await pool.connect(), db3); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /test/gridfs_testdata_in.txt: -------------------------------------------------------------------------------- 1 | Filet mignon leberkas pig pork chop biltong, short loin strip steak turkey brisket 2 | venison. Pastrami venison pancetta, leberkas pork chop chicken prosciutto beef ribs 3 | bresaola kielbasa swine biltong capicola. Hamburger beef ribs ball tip drumstick salami 4 | pig. Capicola pork loin shank, salami chicken hamburger tail. Sirloin spare ribs 5 | ground round cow strip steak prosciutto swine bacon corned beef. -------------------------------------------------------------------------------- /test/replica_tests.dart: -------------------------------------------------------------------------------- 1 | library; 2 | 3 | import 'package:mongo_dart/mongo_dart.dart'; 4 | import 'dart:async'; 5 | //import 'package:logging/logging.dart'; 6 | import 'package:test/test.dart'; 7 | 8 | const defaultUri1 = 'mongodb://127.0.0.1:27001'; 9 | const defaultUri2 = 'mongodb://127.0.0.1:27002'; 10 | const defaultUri3 = 'mongodb://127.0.0.1:27003'; 11 | 12 | Future testCollectionInfoCursor() async { 13 | var db = Db.pool([ 14 | '$defaultUri1/mongo_dart-test', 15 | '$defaultUri2/mongo_dart-test', 16 | '$defaultUri3/mongo_dart-test' 17 | ], 'testCollectionInfoCursor'); 18 | DbCollection newColl; 19 | await db.open(writeConcern: WriteConcern.journaled); 20 | 21 | newColl = db.collection('new_collecion'); 22 | await newColl.remove({}); 23 | 24 | await newColl.insertAll([ 25 | {'a': 1} 26 | ]); 27 | 28 | var v = await db.getCollectionInfos({'name': 'new_collecion'}); 29 | 30 | expect(v, hasLength(1)); 31 | await db.close(); 32 | } 33 | 34 | void main() { 35 | // hierarchicalLoggingEnabled = true; 36 | // Logger.root.level = Level.OFF; 37 | // new Logger('ConnectionManager').level = Level.ALL; 38 | // var listener = (LogRecord r) { 39 | // var name = r.loggerName; 40 | // if (name.length > 15) { 41 | // name = name.substring(0, 15); 42 | // } 43 | // while (name.length < 15) { 44 | // name = "$name "; 45 | // } 46 | // print("${r.time}: $name: ${r.message}"); 47 | // }; 48 | // Logger.root.onRecord.listen(listener); 49 | 50 | group('DbCollection tests:', () { 51 | test('testCollectionInfoCursor', testCollectionInfoCursor); 52 | }); 53 | } 54 | -------------------------------------------------------------------------------- /test/test_binary_dump.dart: -------------------------------------------------------------------------------- 1 | library; 2 | 3 | import 'package:mongo_dart/mongo_dart.dart'; 4 | import 'dart:io'; 5 | 6 | void main() { 7 | var raf = File(r'c:\projects\mongo_dart\debug_data1.bin').openSync(); 8 | var len = raf.lengthSync(); 9 | var lenBuffer = BsonBinary(4); 10 | var readPos = 0; 11 | var counter = 0; 12 | while (raf.positionSync() < len) { 13 | raf.readIntoSync(lenBuffer.byteList); 14 | lenBuffer.rewind(); 15 | var messageLen = lenBuffer.readInt32(); 16 | print('$messageLen'); 17 | readPos += messageLen; 18 | counter++; 19 | print('counter: $counter readPos $readPos'); 20 | raf.setPositionSync(readPos); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/test_chunks.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | class ChunkHandler { 4 | int chunkSize; 5 | List? carry; 6 | 7 | ChunkHandler([this.chunkSize = 1024 * 256]); 8 | 9 | void _handle(List data, EventSink> sink, bool isClosing) { 10 | if (carry != null) { 11 | carry!.addAll(data); 12 | data = carry!; 13 | carry = null; 14 | } 15 | var pos = 0; 16 | while (pos + chunkSize < data.length) { 17 | sink.add(data.sublist(pos, pos + chunkSize)); 18 | pos += chunkSize; 19 | } 20 | if (data.length > pos) { 21 | carry = []; 22 | carry!.addAll(data.sublist(pos)); 23 | if (isClosing) { 24 | sink.add(carry!); 25 | } 26 | } 27 | } 28 | 29 | void handleData(List data, EventSink> sink) => 30 | _handle(data, sink, false); 31 | 32 | void handleError( 33 | Object error, StackTrace stackTrace, EventSink> sink) { 34 | print(error); 35 | print(stackTrace); 36 | } 37 | 38 | void handleDone(EventSink> sink) { 39 | _handle([], sink, true); 40 | sink.close(); 41 | } 42 | 43 | StreamTransformer, List> get transformer => 44 | StreamTransformer, List>.fromHandlers( 45 | handleData: handleData, handleDone: handleDone); 46 | } 47 | 48 | StreamTransformer, List> chunkTransformer(int chunkSize) { 49 | var chunkHandler = ChunkHandler(chunkSize); 50 | return StreamTransformer, List>.fromHandlers( 51 | handleData: chunkHandler.handleData, handleDone: chunkHandler.handleDone); 52 | } 53 | 54 | void main() { 55 | var data = [ 56 | [1, 3, 5, 6, 7, 8, 9, 3, 4, 5, 6, 1, 7], 57 | [2, 3, 6, 1] 58 | ]; 59 | var stream = Stream.fromIterable(data); 60 | stream.transform(ChunkHandler(4).transformer).listen(print); 61 | } 62 | -------------------------------------------------------------------------------- /test/test_connection.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | import 'package:logging/logging.dart'; 3 | 4 | const dbName = 'test-mongo-dart'; 5 | const dbAddress = '127.0.0.1'; 6 | 7 | const defaultUri = 'mongodb://$dbAddress:27017/$dbName'; 8 | 9 | // This test must be run manually with mongoDb dowm, 10 | // Then, while it is running, start mongo db. 11 | // If ok, it should print the ('Is connected!') message 12 | void main() async { 13 | Logger.root.level = Level.INFO; // defaults to Level.INFO 14 | Logger.root.onRecord.listen((record) { 15 | print('${record.level.name}: ${record.time}: ${record.message}'); 16 | }); 17 | 18 | var db = Db(defaultUri); 19 | var count = 0; 20 | while (count < 10) { 21 | try { 22 | await db.open(); 23 | print('Is connected!'); 24 | await db.close(); 25 | break; 26 | } catch (e) { 27 | count++; 28 | print(e); 29 | await Future.delayed(Duration(seconds: 2)); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/utils/insert_cake_sales_db.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | Future insertCakeSales(DbCollection collection) async { 4 | return collection.insertMany([ 5 | { 6 | '_id': 0, 7 | 'type': 'chocolate', 8 | 'orderDate': DateTime.parse('2020-05-18T14:10:30Z'), 9 | 'state': "CA", 10 | 'price': 13, 11 | 'quantity': 120 12 | }, 13 | { 14 | '_id': 1, 15 | 'type': 'chocolate', 16 | 'orderDate': DateTime.parse('2021-03-20T11:30:05Z'), 17 | 'state': "WA", 18 | 'price': 14, 19 | 'quantity': 140 20 | }, 21 | { 22 | '_id': 2, 23 | 'type': 'vanilla', 24 | 'orderDate': DateTime.parse('2021-01-11T06:31:15Z'), 25 | 'state': "CA", 26 | 'price': 12, 27 | 'quantity': 145 28 | }, 29 | { 30 | '_id': 3, 31 | 'type': 'vanilla', 32 | 'orderDate': DateTime.parse('2020-02-08T13:13:23Z'), 33 | 'state': "WA", 34 | 'price': 13, 35 | 'quantity': 104 36 | }, 37 | { 38 | '_id': 4, 39 | 'type': 'strawberry', 40 | 'orderDate': DateTime.parse('2019-05-18T16:09:01Z'), 41 | 'state': "CA", 42 | 'price': 41, 43 | 'quantity': 162 44 | }, 45 | { 46 | '_id': 5, 47 | 'type': 'strawberry', 48 | 'orderDate': DateTime.parse('2019-01-08T06:12:03Z'), 49 | 'state': "WA", 50 | 'price': 43, 51 | 'quantity': 134 52 | } 53 | ]); 54 | } 55 | -------------------------------------------------------------------------------- /test/utils/test_database.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart'; 2 | 3 | Future testDatabase(String uriString) async { 4 | var db = Db(uriString); 5 | Uri uri = Uri.parse(uriString); 6 | try { 7 | await db.open(); 8 | await db.close(); 9 | return true; 10 | } on MongoDartError catch (e) { 11 | if (e.mongoCode == 18) { 12 | return false; 13 | } 14 | rethrow; 15 | } on Map catch (e) { 16 | if (e.containsKey(keyCode)) { 17 | if (e[keyCode] == 18) { 18 | return false; 19 | } 20 | } 21 | throw StateError('Unknown error $e'); 22 | // When the server is not reachable on the required address (port!?) 23 | } on ConnectionException catch (e) { 24 | if (e.message.contains(':${uri.port}')) { 25 | return false; 26 | } 27 | throw StateError('Unknown error $e'); 28 | } catch (e) { 29 | throw StateError('Unknown error $e'); 30 | } 31 | } 32 | 33 | Future getFcv(String uri) async { 34 | var db = Db(uri); 35 | try { 36 | await db.open(); 37 | var fcv = db.masterConnection.serverCapabilities.fcv; 38 | 39 | await db.close(); 40 | return fcv; 41 | } on Map catch (e) { 42 | if (e.containsKey(keyCode)) { 43 | if (e[keyCode] == 18) { 44 | return null; 45 | } 46 | } 47 | throw StateError('Unknown error $e'); 48 | } catch (e) { 49 | throw StateError('Unknown error $e'); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test/utils/throw_utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:mongo_dart/mongo_dart.dart' show MongoDartError; 2 | import 'package:test/test.dart' show throwsA; 3 | 4 | var throwsMongoDartError = throwsA((e) => e is MongoDartError); 5 | --------------------------------------------------------------------------------