Поиск Azure, возвращающий результаты для удаленных ресурсов BLOB-объектов

У меня есть служба поиска Azure, которая используется для поиска по BLOBS (изображениям) на основе метаданных BLOB.

Индекс, на котором основан поиск, обновляется ежечасно.

Однако я все еще получаю результаты для BLOB-объектов, которые больше не существуют, которые возвращаются в результатах поиска.

Использование API Get Indexer Status (вывод ниже) показывает, что индекс был успешно обновлен после удаления 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.

Проблема, которую это вызывает, состоит в том, что эти изображения выводятся на веб-страницу и в настоящее время отображаются как отсутствующие изображения, а также делают индекс больше, чем нужно.

2 ответа

Решение

После прочтения я обнаружил, что единственной политикой удаления, поддерживаемой в настоящее время поиском Azure, является Soft Delete.

Чтобы включить это для хранилища больших двоичных объектов, необходимо создать значение метаданных для каждого большого двоичного объекта (например, 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"
    }
} 

Полная информация здесь

Мне нужно будет провести некоторое тестирование, чтобы убедиться в безопасности обновления метаданных и немедленного удаления BLOB-объекта.

Хотя Soft Delete является опцией, индекс, на который нацеливается индексатор, также может быть напрямую изменен, если вы того пожелаете.

Вы можете использовать POST для индексации API, подробно описанного на этой странице, чтобы напрямую удалять документы, используя их поле "ключ". Пример ниже:

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-объектов, из документации на этой странице ключевым полем будет закодированное в base64 значение свойства metadata_storage_path (опять же, для получения дополнительной информации обратитесь к предыдущей ссылке), Таким образом, после удаления большого двоичного объекта вы можете написать триггер для отправки соответствующей полезной нагрузки в поисковый индекс, из которого вы хотите удалить документы.

Вот решение, которое я реализовал для удаления больших двоичных объектов в источнике данных поиска Azure.

  • Шаг 1. Удалите документ из хранилища BLOB-объектов
  • Шаг 2: удалите документ из лазурного поиска

В словаре ключ - это имя контейнера, значения - это список файлов.

Вот пример кода

 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;
        }
    }