fix(mongodb): support shell delete commands
This commit is contained in:
parent
ff1a0f5eda
commit
0c4ae7caf6
|
|
@ -48,6 +48,7 @@ public final class AgentProtocol {
|
|||
public static final String MONGO_METHOD_UPDATE_DOCUMENT = "update_document";
|
||||
public static final String MONGO_METHOD_UPDATE_DOCUMENTS = "update_documents";
|
||||
public static final String MONGO_METHOD_DELETE_DOCUMENT = "delete_document";
|
||||
public static final String MONGO_METHOD_DELETE_DOCUMENTS = "delete_documents";
|
||||
|
||||
public static final String KV_METHOD_LIST_PREFIX = "kv_list_prefix";
|
||||
public static final String KV_METHOD_GET = "kv_get";
|
||||
|
|
@ -123,7 +124,9 @@ public final class AgentProtocol {
|
|||
MONGO_METHOD_SERVER_VERSION,
|
||||
MONGO_METHOD_INSERT_DOCUMENT,
|
||||
MONGO_METHOD_UPDATE_DOCUMENT,
|
||||
MONGO_METHOD_DELETE_DOCUMENT
|
||||
MONGO_METHOD_UPDATE_DOCUMENTS,
|
||||
MONGO_METHOD_DELETE_DOCUMENT,
|
||||
MONGO_METHOD_DELETE_DOCUMENTS
|
||||
));
|
||||
|
||||
public static final List<String> KV_METHODS = Collections.unmodifiableList(Arrays.asList(
|
||||
|
|
|
|||
|
|
@ -72,7 +72,9 @@
|
|||
"server_version",
|
||||
"insert_document",
|
||||
"update_document",
|
||||
"delete_document"
|
||||
"update_documents",
|
||||
"delete_document",
|
||||
"delete_documents"
|
||||
],
|
||||
"kvMethods": [
|
||||
"kv_list_prefix",
|
||||
|
|
|
|||
|
|
@ -536,6 +536,21 @@ public final class MongoAgent {
|
|||
return Collections.singletonMap("deleted_count", result.getDeletedCount());
|
||||
}
|
||||
|
||||
private static Object deleteDocuments(JsonObject params) {
|
||||
MongoClient c = requireClient();
|
||||
String database = params.get("database").getAsString();
|
||||
String collection = params.get("collection").getAsString();
|
||||
String filterJson = params.get("filter_json").getAsString();
|
||||
boolean many = params.get("many").getAsBoolean();
|
||||
|
||||
var col = c.getDatabase(database).getCollection(collection);
|
||||
Document filter = documentForWrite(filterJson);
|
||||
// Shell deleteOne/deleteMany use a filter document, unlike the row-view
|
||||
// delete path which always targets a single _id.
|
||||
var result = many ? col.deleteMany(filter) : col.deleteOne(filter);
|
||||
return Collections.singletonMap("deleted_count", result.getDeletedCount());
|
||||
}
|
||||
|
||||
private static Map<String, Object> bsonToJson(Document doc) {
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> entry : doc.entrySet()) {
|
||||
|
|
@ -662,6 +677,7 @@ public final class MongoAgent {
|
|||
case AgentProtocol.MONGO_METHOD_UPDATE_DOCUMENT -> updateDocument(params);
|
||||
case AgentProtocol.MONGO_METHOD_UPDATE_DOCUMENTS -> updateDocuments(params);
|
||||
case AgentProtocol.MONGO_METHOD_DELETE_DOCUMENT -> deleteDocument(params);
|
||||
case AgentProtocol.MONGO_METHOD_DELETE_DOCUMENTS -> deleteDocuments(params);
|
||||
case AgentProtocol.METHOD_DISCONNECT, AgentProtocol.METHOD_SHUTDOWN -> {
|
||||
if (client != null) {
|
||||
client.close();
|
||||
|
|
|
|||
|
|
@ -149,6 +149,20 @@ class MongoAgentTest {
|
|||
assertFalse(json.getAsJsonObject("error").get("message").getAsString().contains("Unknown method"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteDocumentsMethodIsRecognizedOverJsonRpc() {
|
||||
String response = MongoAgent.handleRequest(
|
||||
"{\"jsonrpc\":\"2.0\",\"id\":11,\"method\":\"delete_documents\","
|
||||
+ "\"params\":{\"database\":\"app\",\"collection\":\"orders\","
|
||||
+ "\"filter_json\":\"{\\\"status\\\":\\\"draft\\\"}\",\"many\":true}}");
|
||||
|
||||
JsonObject json = JsonParser.parseString(response).getAsJsonObject();
|
||||
assertEquals(11, json.get("id").getAsInt());
|
||||
assertEquals("Not connected", json.getAsJsonObject("error").get("message").getAsString());
|
||||
assertFalse(json.getAsJsonObject("error").get("message").getAsString().contains("Unknown method"));
|
||||
assertTrue(AgentProtocol.MONGO_LEGACY_METHODS.contains(AgentProtocol.MONGO_METHOD_DELETE_DOCUMENTS));
|
||||
}
|
||||
|
||||
@Test
|
||||
void extractsServerVersionFromBuildInfo() {
|
||||
assertEquals("4.4.29", MongoAgent.serverVersionFromBuildInfo(new Document("version", "4.4.29")));
|
||||
|
|
|
|||
|
|
@ -72,7 +72,9 @@
|
|||
"server_version",
|
||||
"insert_document",
|
||||
"update_document",
|
||||
"delete_document"
|
||||
"update_documents",
|
||||
"delete_document",
|
||||
"delete_documents"
|
||||
],
|
||||
"kvMethods": [
|
||||
"kv_list_prefix",
|
||||
|
|
|
|||
|
|
@ -249,10 +249,11 @@ pub enum MongoAgentMethod {
|
|||
UpdateDocument,
|
||||
UpdateDocuments,
|
||||
DeleteDocument,
|
||||
DeleteDocuments,
|
||||
}
|
||||
|
||||
impl MongoAgentMethod {
|
||||
pub const ALL: [Self; 8] = [
|
||||
pub const ALL: [Self; 10] = [
|
||||
Self::ListDatabases,
|
||||
Self::ListCollections,
|
||||
Self::FindDocuments,
|
||||
|
|
@ -260,7 +261,9 @@ impl MongoAgentMethod {
|
|||
Self::ServerVersion,
|
||||
Self::InsertDocument,
|
||||
Self::UpdateDocument,
|
||||
Self::UpdateDocuments,
|
||||
Self::DeleteDocument,
|
||||
Self::DeleteDocuments,
|
||||
];
|
||||
|
||||
pub fn as_str(self) -> &'static str {
|
||||
|
|
@ -274,6 +277,7 @@ impl MongoAgentMethod {
|
|||
Self::UpdateDocument => "update_document",
|
||||
Self::UpdateDocuments => "update_documents",
|
||||
Self::DeleteDocument => "delete_document",
|
||||
Self::DeleteDocuments => "delete_documents",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -972,6 +976,13 @@ impl AgentDriverClient {
|
|||
self.call_mongo_method(MongoAgentMethod::DeleteDocument, params).await
|
||||
}
|
||||
|
||||
pub async fn mongo_delete_documents<T: DeserializeOwned + Send + 'static>(
|
||||
&mut self,
|
||||
params: Value,
|
||||
) -> Result<T, String> {
|
||||
self.call_mongo_method(MongoAgentMethod::DeleteDocuments, params).await
|
||||
}
|
||||
|
||||
pub async fn try_optional_handshake(&mut self, app_version: &str) -> Option<AgentHandshake> {
|
||||
match self.call_method::<AgentHandshake>(AgentMethod::Handshake, agent_handshake_params(app_version)).await {
|
||||
Ok(handshake) => {
|
||||
|
|
@ -1495,7 +1506,9 @@ mod tests {
|
|||
assert_eq!(MongoAgentMethod::ServerVersion.as_str(), "server_version");
|
||||
assert_eq!(MongoAgentMethod::InsertDocument.as_str(), "insert_document");
|
||||
assert_eq!(MongoAgentMethod::UpdateDocument.as_str(), "update_document");
|
||||
assert_eq!(MongoAgentMethod::UpdateDocuments.as_str(), "update_documents");
|
||||
assert_eq!(MongoAgentMethod::DeleteDocument.as_str(), "delete_document");
|
||||
assert_eq!(MongoAgentMethod::DeleteDocuments.as_str(), "delete_documents");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1537,7 +1550,9 @@ mod tests {
|
|||
let _mongo_server_version = AgentDriverClient::mongo_server_version::<serde_json::Value>;
|
||||
let _mongo_insert_document = AgentDriverClient::mongo_insert_document::<serde_json::Value>;
|
||||
let _mongo_update_document = AgentDriverClient::mongo_update_document::<serde_json::Value>;
|
||||
let _mongo_update_documents = AgentDriverClient::mongo_update_documents::<serde_json::Value>;
|
||||
let _mongo_delete_document = AgentDriverClient::mongo_delete_document::<serde_json::Value>;
|
||||
let _mongo_delete_documents = AgentDriverClient::mongo_delete_documents::<serde_json::Value>;
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -318,7 +318,18 @@ pub async fn mongo_delete_documents_core(
|
|||
PoolKind::MongoDb(client) => {
|
||||
mongo_driver::delete_documents(client, database, collection, filter_json, many).await
|
||||
}
|
||||
PoolKind::Agent(_) => Err("MongoDB legacy agent does not support bulk deleteOne/deleteMany writes".to_string()),
|
||||
PoolKind::Agent(client) => {
|
||||
let mut client = client.lock().await;
|
||||
let result: serde_json::Value = client
|
||||
.mongo_delete_documents(serde_json::json!({
|
||||
"database": database,
|
||||
"collection": collection,
|
||||
"filter_json": filter_json,
|
||||
"many": many,
|
||||
}))
|
||||
.await?;
|
||||
Ok(result.get("deleted_count").and_then(|v| v.as_u64()).unwrap_or(0))
|
||||
}
|
||||
_ => Err("Not a MongoDB connection".to_string()),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue