Переглянути джерело

feat: add delete_where_id_prefix migration operation

Bulk-delete every document in a collection whose id begins with a
literal prefix. First hit: purging legacy `doc:`-prefixed rows in the
`memories` collection left over from when the ShadowMan
DocumentManager wrote document-chunk embeddings there under
"doc:{document_id}:{chunk_index}" keys. Migration 027 on the
ShadowMan side uses this to clean up after routing those writes to
the dedicated `document_chunks` collection.
Fszontagh 3 місяців тому
батько
коміт
b346cfa8fa

+ 41 - 0
service/src/migrations/migration_runner.cpp

@@ -337,6 +337,47 @@ bool MigrationRunner::applyOperation(const nlohmann::json& operation) {
         return true;
     }
 
+    if (type == "delete_where_id_prefix") {
+        std::string collection = operation.value("collection", "");
+        std::string id_prefix = operation.value("id_prefix", "");
+
+        if (collection.empty() || id_prefix.empty()) {
+            spdlog::error("delete_where_id_prefix: missing collection or id_prefix");
+            return false;
+        }
+
+        // Collect matching ids first so we don't mutate the collection
+        // mid-iteration. Use a generous limit — migrations should never
+        // silently truncate.
+        Query query;
+        query.limit = 1'000'000;
+        auto result = store_.find(collection, query);
+
+        std::vector<std::string> to_delete;
+        to_delete.reserve(result.documents.size());
+        for (const auto& doc : result.documents) {
+            if (doc.id.rfind(id_prefix, 0) == 0) {
+                to_delete.push_back(doc.id);
+            }
+        }
+
+        int removed = 0;
+        for (const auto& id : to_delete) {
+            try {
+                if (store_.remove(collection, id)) {
+                    ++removed;
+                }
+            } catch (const std::exception& e) {
+                spdlog::warn("delete_where_id_prefix: failed to remove '{}' from '{}': {}",
+                             id, collection, e.what());
+            }
+        }
+
+        spdlog::info("delete_where_id_prefix: removed {} docs from '{}' with prefix '{}'",
+                     removed, collection, id_prefix);
+        return true;
+    }
+
     if (type == "alter_collection") {
         std::string collection = operation.value("collection", "");
         if (collection.empty()) {

+ 3 - 0
service/src/migrations/migration_runner.hpp

@@ -30,6 +30,9 @@ namespace smartbotic::database {
  * - upsert: Insert or update document
  * - update: Update existing document
  * - delete: Delete document
+ * - delete_where_id_prefix: Delete every document in a collection whose id
+ *   begins with a literal prefix. Useful for cleaning up legacy
+ *   namespaced keys (e.g. memories with "doc:" prefix).
  */
 class MigrationRunner {
 public: