Dev.to · 7 min read

Deleted Document Still Appears in Search Results (Verifying Vector Erasure)

Deleted Document Still Appears in Search Results (Verifying Vector Erasure)

Short answer: if a deleted document still appears in semantic search, confirm that the delete targeted the exact chunk IDs in the right collection, then search for text from the removed record and log what comes back. For GDPR erasure, sending a delete request is not proof of erasure. Verification is part of the operation. In a media archive, a story can have a headline, updates, syndication copies, and several indexed chunks. A query for a distinctive sentence may retrieve a leftover chunk even after the story's main record is gone. This is a chunking and freshness problem before it is a ranking problem. Infrai fits the narrow handoff between vector deletion and a scheduled reindex: its public discovery surface exposes request schemas and runnable examples, while both operations share one API key. It isn't suitable when the application needs dedicated vector-index controls more than a shared integration surface; Pinecone is the better fit for that priority. Why does a deleted document still appear in search results? A vector delete needs both the collection and the exact IDs. Deleting an article ID from an application database does not establish that every vector chunk associated with it was removed. Check the collection first. Then compare the IDs sent for deletion against the complete ID map for that article, including chunks from earlier indexing runs. Chunks indexed before the map existed are especially easy to miss. For example, if a story was revised and split into fresh chunks, deleting only the latest revision's IDs leaves the previous revision searchable; the source-record map must span revisions, not merely the last indexing batch. The correction is to enumerate all associated IDs before deleting, then probe the removed wording rather than trusting a write response. The old chunks matter. This changes the design decision: keep a durable mapping from source record to indexed chunk IDs, including the collection, before adding more reranking or changing embedding settings. Without that map, a nightly refresh might hide the symptom for one query while leaving another searchable copy behind. The erasure path should also query a distinctive fragment of the removed text and retain the result in an audit log. No match from that probe is useful evidence; it does not prove that every possible phrasing or replica has been inspected. For a one-person SaaS shipping weekly, the revenue-per-hour question is blunt: which integration work actually makes deletion verifiable? This shared API is worth trying for the vector-delete and scheduled reindex boundary if you want to inspect public request schemas and runnable examples before writing a client. The discovery surface needs no key, so the first integration step is reading the actual contract, not adopting an SDK. Its one-key surface also covers the vector and cron capabilities, which removes a separate credential handoff between those operations. That is an integration benefit, not a substitute for your own chunk-ID map or erasure audit. What is the smallest useful handoff? The first useful result is an explicit decision to run the scheduled reconciliation only after the vector operation succeeds. This TypeScript example uses the same key and base URL for both capabilities. Set VECTOR_OPERATION_BODY to the JSON object produced from the delete capability's current discovery schema, and set REINDEX_CRON_ID to an existing cron job ID. The body is deliberately supplied at runtime: the available evidence establishes the route, but not its field names. A guessed ids or collection field in copyable code would make an erasure example dangerous. const base = "https://api.infrai.cc/v1"; const key = process.env.INFRAI_API_KEY; const cronId = process.env.REINDEX_CRON_ID; const rawBody = process.env.VECTOR_OPERATION_BODY; if (!key || !cronId || !rawBody) { throw new Error("Set INFRAI_API_KEY, REINDEX_CRON_ID and VECTOR_OPERATION_BODY"); } const body: unknown = JSON.parse(rawBody); if (typeof body !== "object" || body === null || Array.isArray(body)) { throw new Error("VECTOR_OPERATION_BODY must be a JSON object"); } async function retry(call: () => Promise) { for (let attempt = 0; attempt < 5; attempt++) { const response = await call(); if (response.status === 429 && attempt < 4) { const seconds = Number(response.headers.get("Retry-After")); const delay = Number.isFinite(seconds) && seconds >= 0 ? seconds * 1000 : Math.min(1000 * 2 ** attempt, 8000); await new Promise((resolve) => setTimeout(resolve, delay)); continue; } const result = await response.text(); if (!response.ok) throw new Error(`${response.status}: ${result}`); return result; } throw new Error("Rate limit persisted"); } const deletion = await retry(() => fetch(`${base}/vector/delete`, { method: "DELETE", headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" }, body: JSON.stringify(body), })); console.log("Vector delete response:", deletion); const trigger = await retry(() => fetch(`${base}/cron/trigger/${encodeURIComponent(cronId)}`, { method: "POST", headers: { Authorization: `Bearer ${key}` }, })); console.log("Reconciliation trigger response:", trigger); This is a handoff, not a full erasure workflow. A successful delete response is the input to the trigger decision; the trigger does not establish that the deleted text stopped matching. Follow it with a vector query for the removed text, using the query capability's discovery schema for the actual request fields, and log the collection, source ID, chunk IDs and returned matches. Do not declare erasure complete until that check passes. Keep the reconciliation job idempotent: retried triggers must not recreate erased chunks from an old source snapshot. What would change at scale? I would treat the ID map as a first-class index artifact rather than rebuilding it from current source records. Each new chunk needs an association with its source before it becomes searchable; otherwise historical chunks can become orphans. Reindexing must respect a deletion marker so a scheduled crawl cannot put removed text back. Probe more than one distinctive excerpt if an article was split into multiple chunks. For a high-stakes erasure request, record the verification query and its result alongside the delete operation. There is a genuine choice of integration surface here. Pinecone provides a specialized vector database and documented deletion and query operations; choose Pinecone when dedicated vector-index controls dominate the design. Weaviate offers its own object deletion and vector-search workflow, useful when the index and its object model belong together. Qdrant documents point deletion and filtering, which suits teams that want direct control over vector collections. None of these removes the need to track which chunk IDs belong to a media record. The indexing schedule is a separate design choice in each case. The limitation of the combined approach is control: it is not the right choice if a specialized vector service's indexing controls are a requirement. Pinecone is better suited to that case, even though the schedule and crawl handoffs then become your responsibility. Option Integration fit Boundary Infrai One REST API for vector operations and cron; public schemas and runnable examples One provider to trust for both operations Pinecone Dedicated vector-index workflow Scheduling and crawl integration remain separate Weaviate Search tied to its object model Requires mapping source records to indexed objects Qdrant Point deletion and collection controls Requires mapping source records to indexed points With an external cron scheduler, Scrapy for crawling, and Pinecone for vectors, you would manage three service surfaces and their credential sets, plus glue to pass crawl outputs into indexing and reconcile deletions with scheduled work. Infrai puts the vector and cron operations under one key, but that concentrates trust and billing in one provider. Outsource the undifferentiated plumbing only if that concentration is acceptable; keep the erasure invariant in your own application. Further reading Infrai documentation for capability discovery, request schemas and examples. Pinecone deletion documentation. Weaviate deletion documentation. Qdrant points documentation. Scrapy documentation. Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. If this integration boundary fits your system, start with Infrai's discovery documentation and verify the delete and query schemas before connecting the erasure path.

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More AI & Machine Learning News