fix(mongodb): preserve BSON dates in copied inserts

This commit is contained in:
zipg authored and GitHub committed 2026-07-15 21:01:40 +08:00
1 parent 711d0ec57b
commit 9234c33e24
12 files changed
+160 -26

No files matched your search

@@ -438,7 +438,12 @@ fn search_response_to_document_result(result: SearchResponse) -> Result<MongoDoc
.collect::<Result<Vec<_>, _>>()
.map_err(|e| format!("Elasticsearch document serialization failed: {e}"))?;
Ok(MongoDocumentResult { documents, raw_documents: Some(raw_documents), total: result.hits.total.value() })
Ok(MongoDocumentResult {
documents,
raw_documents: Some(raw_documents),
extended_documents: None,
total: result.hits.total.value(),
})
}
fn build_find_documents_body(
+34 -7
View File
@@ -17,6 +17,8 @@ pub struct MongoDocumentResult {
pub documents: Vec<serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub raw_documents: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extended_documents: Option<Vec<serde_json::Value>>,
pub total: u64,
}
@@ -586,12 +588,14 @@ pub async fn find_documents(
let mut cursor = find.await.map_err(|e| e.to_string())?;
let mut documents = Vec::new();
let mut extended_documents = Vec::new();
while cursor.advance().await.map_err(|e| e.to_string())? {
let doc = cursor.deserialize_current().map_err(|e| e.to_string())?;
documents.push(bson_to_json(&Bson::Document(doc)));
documents.push(bson_to_json(&Bson::Document(doc.clone())));
extended_documents.push(Bson::Document(doc).into_relaxed_extjson());
}
Ok(MongoDocumentResult { documents, raw_documents: None, total })
Ok(MongoDocumentResult { documents, raw_documents: None, extended_documents: Some(extended_documents), total })
}
#[derive(Debug, Default, Deserialize)]
@@ -727,7 +731,7 @@ pub async fn find_documents_extended_json(
documents.push(Bson::Document(doc).into_relaxed_extjson());
}
Ok(MongoDocumentResult { documents, raw_documents: None, total })
Ok(MongoDocumentResult { extended_documents: Some(documents.clone()), documents, raw_documents: None, total })
}
pub async fn aggregate_documents(
@@ -749,15 +753,18 @@ pub async fn aggregate_documents(
let max_rows = max_rows.unwrap_or(100);
let fetch_limit = max_rows.saturating_add(1);
let mut documents = Vec::new();
let mut extended_documents = Vec::new();
while documents.len() < fetch_limit && cursor.advance().await.map_err(|e| e.to_string())? {
let doc = cursor.deserialize_current().map_err(|e| e.to_string())?;
documents.push(bson_to_json(&Bson::Document(doc)));
documents.push(bson_to_json(&Bson::Document(doc.clone())));
extended_documents.push(Bson::Document(doc).into_relaxed_extjson());
}
let total = documents.len() as u64;
if documents.len() > max_rows {
documents.truncate(max_rows);
extended_documents.truncate(max_rows);
}
Ok(MongoDocumentResult { documents, raw_documents: None, total })
Ok(MongoDocumentResult { documents, raw_documents: None, extended_documents: Some(extended_documents), total })
}
pub async fn create_index(
@@ -1119,11 +1126,17 @@ fn find_and_modify_array_filters(
fn single_document_result(document: Option<Document>) -> MongoDocumentResult {
match document {
Some(document) => MongoDocumentResult {
documents: vec![bson_to_json(&Bson::Document(document))],
documents: vec![bson_to_json(&Bson::Document(document.clone()))],
raw_documents: None,
extended_documents: Some(vec![Bson::Document(document).into_relaxed_extjson()]),
total: 1,
},
None => MongoDocumentResult { documents: Vec::new(), raw_documents: None, total: 0 },
None => MongoDocumentResult {
documents: Vec::new(),
raw_documents: None,
extended_documents: Some(Vec::new()),
total: 0,
},
}
}
@@ -1825,6 +1838,20 @@ mod tests {
assert_eq!(value, serde_json::json!("ISODate(\"2026-06-10T13:59:31.287Z\")"));
}
#[test]
fn mongo_document_result_keeps_extended_json_types_for_copying() {
let date = DateTime::parse_rfc3339_str("2025-05-06T08:35:32Z").unwrap();
let result = single_document_result(Some(doc! {
"lastUpdatedDate": date,
"dateText": "ISODate(\"2025-05-06T08:35:32Z\")",
}));
assert_eq!(result.documents[0]["lastUpdatedDate"], serde_json::json!("ISODate(\"2025-05-06T08:35:32Z\")"));
let extended = result.extended_documents.expect("extended documents");
assert_eq!(extended[0]["lastUpdatedDate"], serde_json::json!({ "$date": "2025-05-06T08:35:32Z" }));
assert_eq!(extended[0]["dateText"], serde_json::json!("ISODate(\"2025-05-06T08:35:32Z\")"));
}
#[test]
fn bson_to_json_preserves_unsafe_int64_for_js() {
let value = bson_to_json(&Bson::Int64(2_326_645_729_978_441_729));
+7 -1
View File
@@ -523,6 +523,7 @@ pub async fn find_documents(
return Ok(crate::db::mongo_driver::MongoDocumentResult {
documents,
raw_documents: None,
extended_documents: None,
total: result.affected_rows,
});
}
@@ -566,7 +567,12 @@ pub async fn find_documents(
Value::Object(map)
})
.collect();
Ok(crate::db::mongo_driver::MongoDocumentResult { documents, raw_documents: None, total: result.affected_rows })
Ok(crate::db::mongo_driver::MongoDocumentResult {
documents,
raw_documents: None,
extended_documents: None,
total: result.affected_rows,
})
}
pub async fn execute_rest_query(client: &VectorClient, input: &str) -> Result<QueryResult, String> {
@@ -1,6 +1,7 @@
use std::time::Duration;
use dbx_core::db::mongo_driver;
use mongodb::bson::{doc, Bson, DateTime};
#[tokio::test]
#[ignore = "requires DBX_LIVE_MONGODB_URL pointing at a writable MongoDB database"]
@@ -34,3 +35,34 @@ async fn find_one_returns_only_the_sorted_document() {
assert_eq!(result.documents, vec![serde_json::json!({ "name": "new" })]);
mongo_driver::drop_collection(&client, database, &collection).await.unwrap();
}
#[tokio::test]
#[ignore = "requires DBX_LIVE_MONGODB_URL pointing at a writable MongoDB database"]
async fn find_documents_returns_type_preserving_copy_documents() {
let url = std::env::var("DBX_LIVE_MONGODB_URL").expect("DBX_LIVE_MONGODB_URL");
let client = mongo_driver::connect(&url, Duration::from_secs(10), Duration::from_secs(60)).await.unwrap();
let database = "dbx_live_find_one";
let collection = format!("copy_types_{}", std::process::id());
client
.database(database)
.collection(&collection)
.insert_one(doc! {
"lastUpdatedDate": DateTime::parse_rfc3339_str("2025-05-06T08:35:32Z").unwrap(),
"dateText": Bson::String("ISODate(\"2025-05-06T08:35:32Z\")".to_string()),
})
.await
.unwrap();
let result =
mongo_driver::find_documents(&client, database, &collection, 0, 10, Some("{}"), Some(r#"{"_id":0}"#), None)
.await
.unwrap();
assert_eq!(result.documents[0]["lastUpdatedDate"], serde_json::json!("ISODate(\"2025-05-06T08:35:32Z\")"));
let extended = result.extended_documents.expect("extended documents");
assert_eq!(extended[0]["lastUpdatedDate"], serde_json::json!({ "$date": "2025-05-06T08:35:32Z" }));
assert_eq!(extended[0]["dateText"], serde_json::json!("ISODate(\"2025-05-06T08:35:32Z\")"));
mongo_driver::drop_collection(&client, database, &collection).await.unwrap();
}