fix(mongodb): preserve BSON dates in copied inserts
This commit is contained in:
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(
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
Reference in new issue
Block a user