feat(mongo): preserve BSON types when cloning and saving documents

This commit is contained in:
二丫讲梵 authored and GitHub committed 2026-08-10 23:02:37 +08:00
1 parent cc7112b240
commit a5ce8510e7
12 files changed
+239 -36

No files matched your search

+30
View File
@@ -1651,6 +1651,21 @@ pub async fn insert_document(
Ok(format!("{}", result.inserted_id))
}
/// Inserts a document from canonical Extended JSON without interpreting
/// Mongo shell-like strings such as `ISODate(...)`.
pub async fn insert_document_extended_json(
client: &Client,
database: &str,
collection: &str,
doc_json: &str,
) -> Result<String, String> {
let value: serde_json::Value = serde_json::from_str(doc_json).map_err(|e| format!("Invalid JSON: {e}"))?;
let doc = json_object_to_document_extended_json(&value).map_err(|e| format!("Invalid document: {e}"))?;
let col = client.database(database).collection::<Document>(collection);
let result = col.insert_one(doc).await.map_err(|e| e.to_string())?;
Ok(format!("{}", result.inserted_id))
}
pub async fn insert_documents(
client: &Client,
database: &str,
@@ -3492,6 +3507,21 @@ mod tests {
assert!(matches!(doc.get("count"), Some(Bson::Int64(42))));
}
#[test]
fn json_object_to_document_extended_json_keeps_shell_date_strings_literal() {
let value = serde_json::json!({
"date_text": "ISODate(\"2026-08-10T00:00:00.000Z\")",
"actual_date": { "$date": "2026-08-10T00:00:00.000Z" },
});
let doc = json_object_to_document_extended_json(&value).unwrap();
assert!(matches!(
doc.get("date_text"),
Some(Bson::String(value)) if value == "ISODate(\"2026-08-10T00:00:00.000Z\")"
));
assert!(matches!(doc.get("actual_date"), Some(Bson::DateTime(_))));
}
#[test]
fn parse_gridfs_file_id_accepts_extended_json_object_id() {
let id = parse_gridfs_file_id(r#"{"$oid":"507f1f77bcf86cd799439011"}"#).unwrap();
+21
View File
@@ -524,6 +524,27 @@ pub async fn insert_document_core(
}
}
pub async fn insert_document_preserving_bson_types_core(
state: &AppState,
connection_id: &str,
database: &str,
collection: &str,
doc_json: &str,
routing: Option<&str>,
) -> Result<String, String> {
ensure_document_pool(state, connection_id).await?;
let connections = state.connections.read().await;
match connections.get(connection_id).ok_or("Not found")? {
PoolKind::MongoDb(client) => {
mongo_driver::insert_document_extended_json(client, database, collection, doc_json).await
}
_ => {
drop(connections);
insert_document_core(state, connection_id, database, collection, doc_json, routing).await
}
}
}
pub async fn update_document_core(
state: &AppState,
connection_id: &str,