From ff72aa4f15fcce2a1d4fdd33542970ef19927297 Mon Sep 17 00:00:00 2001 From: Enok <416828041@qq.com> Date: Wed, 4 Mar 2020 22:49:49 +0800 Subject: [PATCH] add insertMany deleteMany --- src/command/delete.rs | 24 +++++------ src/command/find_one.rs | 15 ++----- src/command/insert.rs | 60 ++++++++++++++++++++++++++++ src/command/insert_one.rs | 33 --------------- src/command/list_collection_names.rs | 2 +- src/command/list_database_names.rs | 4 +- src/command/mod.rs | 4 +- src/lib.rs | 2 + src/util.rs | 25 ++++++++++++ test.ts | 28 ++++++++++++- ts/collection.ts | 19 ++++++++- ts/types.ts | 1 + 12 files changed, 152 insertions(+), 65 deletions(-) create mode 100644 src/command/insert.rs delete mode 100644 src/command/insert_one.rs diff --git a/src/command/delete.rs b/src/command/delete.rs index 50f1d4d5..36c26dc2 100644 --- a/src/command/delete.rs +++ b/src/command/delete.rs @@ -1,5 +1,4 @@ use crate::*; -use bson::Bson; use serde_json::Value; #[derive(Deserialize, Debug)] @@ -19,24 +18,19 @@ pub fn delete(command: Command) -> CoreOp { let db_name = args.db_name; let collection_name = args.collection_name; let delete_one = args.delete_one; - let query = args.query; + let query = util::json_to_document(args.query).expect("query canot be null"); let database = client.database(&db_name); let collection = database.collection(&collection_name); - let query_doc: Bson = query.into(); - if let Bson::Document(query_doc) = query_doc { - let delete_result = if delete_one { - collection.delete_one(query_doc, None).unwrap() - } else { - collection.delete_many(query_doc, None).unwrap() - }; - Ok(util::async_result( - &command.args, - delete_result.deleted_count, - )) + let delete_result = if delete_one { + collection.delete_one(query, None).unwrap() } else { - Err(()) - } + collection.delete_many(query, None).unwrap() + }; + Ok(util::async_result( + &command.args, + delete_result.deleted_count, + )) }; CoreOp::Async(fut.boxed()) } diff --git a/src/command/find_one.rs b/src/command/find_one.rs index 32b13791..1f1b31ac 100644 --- a/src/command/find_one.rs +++ b/src/command/find_one.rs @@ -1,13 +1,13 @@ use crate::*; -use bson::Bson; use serde_json::Value; +use util::maybe_json_to_document; #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct FindOnetArgs { db_name: String, collection_name: String, - filter: Value, + filter: Option, } pub fn find_one(command: Command) -> CoreOp { @@ -17,17 +17,10 @@ pub fn find_one(command: Command) -> CoreOp { let args: FindOnetArgs = serde_json::from_slice(data.unwrap().as_ref()).unwrap(); let db_name = args.db_name; let collection_name = args.collection_name; - let filter = args.filter; + let filter = maybe_json_to_document(args.filter); let database = client.database(&db_name); let collection = database.collection(&collection_name); - - let filter_doc: Bson = filter.into(); - let filter_doc = match filter_doc { - Bson::Document(doc) => Some(doc), - _ => None, - }; - - let doc = collection.find_one(filter_doc, None).unwrap(); + let doc = collection.find_one(filter, None).unwrap(); Ok(util::async_result(&command.args, doc)) }; CoreOp::Async(fut.boxed()) diff --git a/src/command/insert.rs b/src/command/insert.rs new file mode 100644 index 00000000..1709a1c8 --- /dev/null +++ b/src/command/insert.rs @@ -0,0 +1,60 @@ +use crate::*; +use bson::Document; +use serde_json::Value; + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct InsertManyArgs { + db_name: String, + collection_name: String, + docs: Vec, +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct InsertOneArgs { + db_name: String, + collection_name: String, + doc: Value, +} + +pub fn insert_one(command: Command) -> CoreOp { + let fut = async move { + let client = command.get_client(); + let data = command.data; + let args: InsertOneArgs = serde_json::from_slice(data.unwrap().as_ref()).unwrap(); + let db_name = args.db_name; + let collection_name = args.collection_name; + let doc = util::json_to_document(args.doc).expect("doc canot be null"); + let database = client.database(&db_name); + let collection = database.collection(&collection_name); + + let insert_result = collection.insert_one(doc, None).unwrap(); + Ok(util::async_result(&command.args, insert_result.inserted_id)) + }; + CoreOp::Async(fut.boxed()) +} + +pub fn insert_many(command: Command) -> CoreOp { + let fut = async move { + let client = command.get_client(); + let data = command.data; + let args: InsertManyArgs = serde_json::from_slice(data.unwrap().as_ref()).unwrap(); + let db_name = args.db_name; + let collection_name = args.collection_name; + let docs: Vec = util::jsons_to_documents(args.docs); + + let database = client.database(&db_name); + let collection = database.collection(&collection_name); + + let insert_result = collection.insert_many(docs, None).unwrap(); + let ids: Vec = insert_result + .inserted_ids + .iter() + .map(|(_, id)| id.to_owned()) + .collect(); + + Ok(util::async_result(&command.args, ids)) + }; + CoreOp::Async(fut.boxed()) +} diff --git a/src/command/insert_one.rs b/src/command/insert_one.rs deleted file mode 100644 index 663b2620..00000000 --- a/src/command/insert_one.rs +++ /dev/null @@ -1,33 +0,0 @@ -use crate::*; -use bson::Bson; -use serde_json::Value; - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -struct InsertOnetArgs { - db_name: String, - collection_name: String, - doc: Value, -} - -pub fn insert_one(command: Command) -> CoreOp { - let fut = async move { - let client = command.get_client(); - let data = command.data; - let args: InsertOnetArgs = serde_json::from_slice(data.unwrap().as_ref()).unwrap(); - let db_name = args.db_name; - let collection_name = args.collection_name; - let doc = args.doc; - let database = client.database(&db_name); - let collection = database.collection(&collection_name); - - let insert_doc: Bson = doc.into(); - if let Bson::Document(insert_doc) = insert_doc { - let insert_result = collection.insert_one(insert_doc, None).unwrap(); - Ok(util::async_result(&command.args, insert_result.inserted_id)) - } else { - Err(()) - } - }; - CoreOp::Async(fut.boxed()) -} diff --git a/src/command/list_collection_names.rs b/src/command/list_collection_names.rs index fd4d1fea..0638e9ec 100644 --- a/src/command/list_collection_names.rs +++ b/src/command/list_collection_names.rs @@ -7,7 +7,7 @@ pub fn list_collection_names(command: Command) -> CoreOp { let db_name: Vec = data.unwrap().as_ref().to_vec(); let db_name = String::from_utf8(db_name).unwrap(); let database = client.database(&db_name); - let collection_names = database.list_collection_names(None); + let collection_names = database.list_collection_names(None::); Ok(util::async_result(&command.args, collection_names.unwrap())) }; diff --git a/src/command/list_database_names.rs b/src/command/list_database_names.rs index fb5a3e54..0092bda3 100644 --- a/src/command/list_database_names.rs +++ b/src/command/list_database_names.rs @@ -2,7 +2,9 @@ use crate::*; pub fn list_database_names(command: Command) -> CoreOp { let fut = async move { - let names = command.get_client().list_database_names(None); + let names = command + .get_client() + .list_database_names(None::); let data = names.unwrap(); Ok(util::async_result(&command.args, data)) }; diff --git a/src/command/mod.rs b/src/command/mod.rs index fe7bcb45..e2b3564f 100644 --- a/src/command/mod.rs +++ b/src/command/mod.rs @@ -1,13 +1,13 @@ mod connect; mod delete; mod find_one; -mod insert_one; +mod insert; mod list_collection_names; mod list_database_names; pub use connect::{connect_with_options, connect_with_uri}; pub use delete::delete; pub use find_one::find_one; -pub use insert_one::insert_one; +pub use insert::{insert_many, insert_one}; pub use list_collection_names::list_collection_names; pub use list_database_names::list_database_names; diff --git a/src/lib.rs b/src/lib.rs index 00da960e..47ac9051 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,7 @@ pub enum CommandType { ListDatabases, FindOne, ListCollectionNames, + InsertMany, InsertOne, Delete, } @@ -94,6 +95,7 @@ fn op_command(data: &[u8], zero_copy: Option) -> CoreOp { CommandType::ListCollectionNames => command::list_collection_names, CommandType::FindOne => command::find_one, CommandType::InsertOne => command::insert_one, + CommandType::InsertMany => command::insert_many, CommandType::Delete => command::delete, }; diff --git a/src/util.rs b/src/util.rs index 2be1a2b3..e12802fa 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,4 +1,6 @@ use crate::*; +use bson::{Bson, Document}; +use serde_json::Value; pub fn async_result(args: &CommandArgs, data: T) -> Buf where @@ -12,3 +14,26 @@ where let data = serde_json::to_vec(&json).unwrap(); Buf::from(data) } + +pub fn maybe_json_to_document(maybe_json: Option) -> Option { + if let Some(val) = maybe_json { + json_to_document(val) + } else { + None + } +} + +pub fn json_to_document(json: Value) -> Option { + let bson: Bson = json.into(); + match bson { + Bson::Document(doc) => Some(doc), + _ => None, + } +} + +pub fn jsons_to_documents(jsons: Vec) -> Vec { + jsons + .iter() + .filter_map(|json| json_to_document(json.to_owned())) + .collect() +} diff --git a/test.ts b/test.ts index cd81ae7d..f197a528 100644 --- a/test.ts +++ b/test.ts @@ -55,10 +55,27 @@ test(async function testInsertOne() { }); }); +test(async function testInsertMany() { + const db = getClient().database("test"); + const users = db.collection("mongo_test_users"); + const insertIds = await users.insertMany([ + { + username: "many", + password: "pass1" + }, + { + username: "many", + password: "pass1" + } + ]); + + assertEquals(insertIds.length, 2); +}); + test(async function testFindOne() { const db = getClient().database("test"); const users = db.collection("mongo_test_users"); - const user1 = await users.findOne({}); + const user1 = await users.findOne(); assert(user1 instanceof Object); assertEquals(Object.keys(user1), ["_id", "username", "password"]); @@ -73,6 +90,15 @@ test(async function testDeleteOne() { assertEquals(deleteCount, 1); }); +test(async function testDeleteMany() { + const db = getClient().database("test"); + const users = db.collection("mongo_test_users"); + const deleteCount = await users.deleteMany({ + username: "many" + }); + assertEquals(deleteCount, 2); +}); + await cargoBuild(); await init("master"); await runTests(); diff --git a/ts/collection.ts b/ts/collection.ts index 0e61b766..2c376251 100644 --- a/ts/collection.ts +++ b/ts/collection.ts @@ -9,7 +9,7 @@ export class Collection { private readonly collectionName: string ) {} - public async findOne(filter: Object): Promise { + public async findOne(filter?: Object): Promise { const doc = await dispatchAsync( { command_type: CommandType.FindOne, @@ -43,6 +43,23 @@ export class Collection { return _id; } + public async insertMany(docs: Object[]): Promise { + const _ids = await dispatchAsync( + { + command_type: CommandType.InsertMany, + client_id: this.client.clientId + }, + encode( + JSON.stringify({ + dbName: this.dbName, + collectionName: this.collectionName, + docs + }) + ) + ); + return _ids; + } + private async _delete( query: Object, deleteOne: boolean = false diff --git a/ts/types.ts b/ts/types.ts index 1494287d..39c27144 100644 --- a/ts/types.ts +++ b/ts/types.ts @@ -5,5 +5,6 @@ export enum CommandType { ListCollectionNames = "ListCollectionNames", FindOne = "FindOne", InsertOne = "InsertOne", + InsertMany = "InsertMany", Delete = "Delete" }