Azure 搜索返回已删除 blob 资源的结果

Azure Search returning results for deleted blob resources

我有一个 Azure 搜索服务,用于根据 BLOB 元数据搜索 BLOBS(图像)。

搜索所依据的索引设置为每小时刷新一次。

但是,我仍然在搜索结果中返回不再存在的 BLOB 的结果。

使用Get Indexer Status API(下面的输出)显示删除 BLOBS 后索引已成功刷新。

"status": "running",
"lastResult": {
    "status": "success",
    "errorMessage": null,
    "startTime": "2018-02-05T16:00:03.29Z",
    "endTime": "2018-02-05T16:00:03.416Z",
    "errors": [],
    "warnings": [],
    "itemsProcessed": 0,
    "itemsFailed": 0,
    "initialTrackingState": "{\r\n  \"lastFullEnumerationStartTime\": \"2018-02-05T14:59:31.966Z\",\r\n  \"lastAttemptedEnumerationStartTime\": \"2018-02-05T14:59:31.966Z\",\r\n  \"nameHighWaterMark\": null\r\n}",
    "finalTrackingState": "{\"LastFullEnumerationStartTime\":\"2018-02-05T15:59:33.2900956+00:00\",\"LastAttemptedEnumerationStartTime\":\"2018-02-05T15:59:33.2900956+00:00\",\"NameHighWaterMark\":null}"
},
"

如果相关,则使用 Azure Storage Explorer

删除了 BLOB

这导致的问题是这些图像正在输出到网页并且当前显示为丢失的图像以及使索引比需要的更大。

经过一番阅读,我发现 Azure 搜索目前支持的唯一删除策略是 软删除

要为 BLOB 存储启用此功能,您必须在每个 BLOB 上创建一个元数据值(例如 IsDeleted)并更新此值以使其能够被删除策略捕获。

PUT https://[service name].search.windows.net/datasources/blob-datasource?api-version=2016-09-01
Content-Type: application/json
api-key: [admin key]

{
"name" : "blob-datasource",
"type" : "azureblob",
"credentials" : { "connectionString" : "<your storage connection string>" },
"container" : { "name" : "my-container", "query" : "my-folder" },
"dataDeletionDetectionPolicy" : {
    "@odata.type" :"#Microsoft.Azure.Search.SoftDeleteColumnDeletionDetectionPolicy",     
    "softDeleteColumnName" : "IsDeleted",
    "softDeleteMarkerValue" : "true"
    }
} 

Full details here

我需要进行一些测试以确保更新元数据是安全的,然后立即删除 BLOB。

虽然软删除是一个选项,但如果您愿意,也可以直接修改索引器所针对的索引。

您可以使用 POST 索引 API 详细 on this page 直接删除文档,使用它们的 "key" 字段。下面是一个例子:

POST https://[service name].search.windows.net/indexes/[index name]/docs/index?api-version=[api-version]   
Content-Type: application/json   
api-key: [admin key]  
{  
  "value": [  
    {  
      "@search.action": "delete",  
      "key_field_name": "value"
    }
  ]  
} 

假设您没有使用字段映射来修改 blob 索引器的默认 "key" 行为,根据文档 on this page,关键字段将是 base64 编码 metadata_storage_path 属性 的值(同样,详见前面的link)。因此,在删除 blob 后,您可以将触发器写入 POST 适当的负载到您要从中删除文档的搜索索引。

这是我为删除 azure 搜索数据源中的 blob 而实施的解决方案。

  • 第 1 步:从 blob 存储中删除文档
  • 第 2 步:从 Azure 搜索中删除文档

在字典中键是容器名称,值是文件列表。

Here is code sample

 public async Task<bool> RemoveFilesAsync(Dictionary<string, List<string>> listOfFiles)
    {
        try
        {
            CloudBlobClient cloudBlobClient = searchConfig.CloudBlobClient;
            foreach (var container in listOfFiles)
            {
                List<string> fileIds = new List<string>();
                CloudBlobContainer staggingBlobContainer = cloudBlobClient.GetContainerReference(container.Key);

                foreach (var file in container.Value)
                {
                    CloudBlockBlob staggingBlob = staggingBlobContainer.GetBlockBlobReference(file);

                    var parameters = new SearchParameters()
                    {
                        Select = new[] { "id", "fileName" }
                    };

                    var results = searchConfig.IndexClient.Documents.Search<Document>(file, parameters);

                    var filedetails = results.Results.FirstOrDefault(p => p?.Document["fileName"]?.ToString()?.ToLower() == file.ToLower());
                    if (filedetails != null)
                        fileIds.Add(filedetails.Document["id"]?.ToString());

                     await staggingBlob.DeleteAsync();
                }

                // delete from search index
                var batch = IndexBatch.Delete("id", fileIds);
                await searchConfig.IndexClient.Documents.IndexWithHttpMessagesAsync(batch);
            }

            return true;
        }
        catch (Exception ex)
        {
            throw;
        }
    }