From 88ad579a273b758d34f0142fb38d070e07baa3bc Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Thu, 14 May 2026 14:43:26 +0800 Subject: [PATCH] feat(mongo): add filter/sort support and fix table view editing - Add filter and sort parameters to MongoDB find_documents across the full stack (driver, ops, tauri cmd, web routes, frontend API) - Add find/sort input bar to MongoDocBrowser table view via DataGrid search-bar slot, matching WHERE/ORDER BY positioning - Fix table view editing: allow cell editing when customSave is provided (bypasses primary key requirement for MongoDB) - Fix replace_one WriteError 66 by removing _id from replacement doc - Align action buttons (refresh, add row, commit) to the right in grid --- crates/dbx-core/src/db/mongo_driver.rs | 23 ++++++++- crates/dbx-core/src/mongo_ops.rs | 6 ++- src-tauri/src/commands/mongo_cmd.rs | 14 ++++- src-web/src/routes/mongo.rs | 4 ++ src/components/grid/DataGrid.vue | 10 ++-- src/components/mongo/MongoDocBrowser.vue | 65 ++++++++++++++++++++++-- src/i18n/locales/en.ts | 2 + src/i18n/locales/zh-CN.ts | 2 + src/lib/http.ts | 4 +- src/lib/tauri.ts | 4 +- 10 files changed, 121 insertions(+), 13 deletions(-) diff --git a/crates/dbx-core/src/db/mongo_driver.rs b/crates/dbx-core/src/db/mongo_driver.rs index 81023859a..5ad4d4531 100644 --- a/crates/dbx-core/src/db/mongo_driver.rs +++ b/crates/dbx-core/src/db/mongo_driver.rs @@ -41,12 +41,31 @@ pub async fn find_documents( collection: &str, skip: u64, limit: i64, + filter: Option<&str>, + sort: Option<&str>, ) -> Result { let col = client.database(database).collection::(collection); - let total = col.count_documents(doc! {}).await.map_err(|e| e.to_string())?; + let filter_doc: Document = match filter { + Some(f) if !f.trim().is_empty() => { + let json: serde_json::Value = serde_json::from_str(f).map_err(|e| format!("Invalid filter JSON: {e}"))?; + mongodb::bson::to_document(&json).map_err(|e| format!("Invalid filter: {e}"))? + } + _ => doc! {}, + }; - let mut cursor = col.find(doc! {}).skip(skip).limit(limit).await.map_err(|e| e.to_string())?; + let total = col.count_documents(filter_doc.clone()).await.map_err(|e| e.to_string())?; + + let mut find = col.find(filter_doc).skip(skip).limit(limit); + if let Some(s) = sort { + if !s.trim().is_empty() { + let json: serde_json::Value = serde_json::from_str(s).map_err(|e| format!("Invalid sort JSON: {e}"))?; + let sort_doc = mongodb::bson::to_document(&json).map_err(|e| format!("Invalid sort: {e}"))?; + find = find.sort(sort_doc); + } + } + + let mut cursor = find.await.map_err(|e| e.to_string())?; let mut documents = Vec::new(); while cursor.advance().await.map_err(|e| e.to_string())? { diff --git a/crates/dbx-core/src/mongo_ops.rs b/crates/dbx-core/src/mongo_ops.rs index b9ede1ac5..1c11a0d17 100644 --- a/crates/dbx-core/src/mongo_ops.rs +++ b/crates/dbx-core/src/mongo_ops.rs @@ -31,10 +31,14 @@ pub async fn mongo_find_documents_core( collection: &str, skip: u64, limit: i64, + filter: Option<&str>, + sort: Option<&str>, ) -> Result { let connections = state.connections.read().await; match connections.get(connection_id).ok_or("Not found")? { - PoolKind::MongoDb(client) => mongo_driver::find_documents(client, database, collection, skip, limit).await, + PoolKind::MongoDb(client) => { + mongo_driver::find_documents(client, database, collection, skip, limit, filter, sort).await + } PoolKind::Elasticsearch(client) => { let client = client.clone(); drop(connections); diff --git a/src-tauri/src/commands/mongo_cmd.rs b/src-tauri/src/commands/mongo_cmd.rs index 5aabc413b..a79b144b9 100644 --- a/src-tauri/src/commands/mongo_cmd.rs +++ b/src-tauri/src/commands/mongo_cmd.rs @@ -29,8 +29,20 @@ pub async fn mongo_find_documents( collection: String, skip: u64, limit: i64, + filter: Option, + sort: Option, ) -> Result { - dbx_core::mongo_ops::mongo_find_documents_core(&state, &connection_id, &database, &collection, skip, limit).await + dbx_core::mongo_ops::mongo_find_documents_core( + &state, + &connection_id, + &database, + &collection, + skip, + limit, + filter.as_deref(), + sort.as_deref(), + ) + .await } #[tauri::command] diff --git a/src-web/src/routes/mongo.rs b/src-web/src/routes/mongo.rs index 4b1f66719..1c169a070 100644 --- a/src-web/src/routes/mongo.rs +++ b/src-web/src/routes/mongo.rs @@ -28,6 +28,8 @@ pub struct MongoFindRequest { pub collection: String, pub skip: Option, pub limit: Option, + pub filter: Option, + pub sort: Option, } #[derive(Deserialize)] @@ -88,6 +90,8 @@ pub async fn find_documents( &req.collection, req.skip.unwrap_or(0), req.limit.unwrap_or(50), + req.filter.as_deref(), + req.sort.as_deref(), ) .await .map_err(AppError)?; diff --git a/src/components/grid/DataGrid.vue b/src/components/grid/DataGrid.vue index 949397636..1693e443d 100644 --- a/src/components/grid/DataGrid.vue +++ b/src/components/grid/DataGrid.vue @@ -829,8 +829,10 @@ const tableUsesSyntheticRowId = computed(() => usesSyntheticRowIdKey(props.databaseType, props.tableMeta?.primaryKeys ?? []), ); const hiveTableTransactional = ref(undefined); -const canEditExistingRows = computed(() => - canEditExistingTableRows(props.databaseType, hiveTableTransactional.value, props.tableMeta?.primaryKeys ?? []), +const canEditExistingRows = computed( + () => + !!props.customSave || + canEditExistingTableRows(props.databaseType, hiveTableTransactional.value, props.tableMeta?.primaryKeys ?? []), ); watch( () => [props.databaseType, props.connectionId, props.database, props.tableMeta?.schema, props.tableMeta?.tableName], @@ -2081,7 +2083,9 @@ defineExpose({ -
+ + +
- {{ t("mongo.documents", { count: total }) }} - + {{ t("mongo.documents", { count: total }) }}