Поиск Azure с использованием REST c #

Я пытаюсь запустить следующий код:

public class Item
{
    [JsonProperty(PropertyName = "api-key")]
    public string apikey { get; set; }

}

[[some method]]{
            var url = "https://[search service name].search.windows.net/indexes/temp?api-version=2016-09-01"; 

            using (var httpClient = new HttpClient())
            {
                using (var request = new HttpRequestMessage(HttpMethod.Put,url))
                {
                    request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));                        
                    var sItem = new Item { apikey = [AzureSearchAdminKey] };
                    var tststring = JsonConvert.SerializeObject(sItem);
                    var body=new  StringContent(tststring, Encoding.UTF8,"application/json" );



                    request.Content =  body;

                    request.Method = HttpMethod.Put;

                    using (HttpResponseMessage response = httpClient.SendAsync(request).Result)
                    {                                                       
                        var stringr = response.Content.ReadAsStringAsync().Result;
                        Console.WriteLine(stringr);
                        Console.ReadLine();
                    }

                }  
            }

}

Я получаю следующую ошибку: «Ошибка чтения JObject из JsonReader. Путь», строка 0, позиция 0. »

Может ли кто-нибудь из поисковой команды сказать мне, что я сделал не так?


person Nok Dev    schedule 10.11.2017    source источник
comment
на самом деле полученная мной ошибка была: {StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: {Pragma: no-cache request-id: ----- -------- прошедшее время: 49 Строгая безопасность транспорта: max-age = 15724800; includeSubDomains Cache-Control: no-cache Дата: ------ Content-Length: 0 Срок действия: -1}}   -  person Nok Dev    schedule 10.11.2017


Ответы (2)


Ключ api должен быть в заголовке HTTP, а определение индекса должно быть в теле HTTP.

Вот пример кода для создания источника данных, index и indexer, который читает из базы данных SQL Azure и индексирует ее строки.

class Program
{
    static void Main(string[] args)
    {
        var searchServiceName = "[search service name]";
        var apiKey = "[api key]";

        var dataSourceName = "[data source name]";
        var indexName = "[index name]";
        var indexerName = "[indexer name]";

        var azureSqlConnectionString = "[Azure SQL connection string]";
        var azureSqlTableName = "[table name]";

        using (var httpClient = new HttpClient())
        {
            var dataSourceDefinition = AzureSqlDatasourceDefinition(azureSqlConnectionString, azureSqlTableName);
            var putDataSourceRequest = PutDataSourceRequest(searchServiceName, apiKey, dataSourceName, dataSourceDefinition);
            Console.WriteLine($"Put data source {putDataSourceRequest.RequestUri}");
            Console.WriteLine();
            var putDataSourceResponse = httpClient.SendAsync(putDataSourceRequest).Result;
            var putDataSourceResponseContent = putDataSourceResponse.Content.ReadAsStringAsync().Result;
            Console.WriteLine(putDataSourceResponseContent);
            Console.WriteLine();

            var indexDefinition = IndexDefinition();
            var putIndexRequest = PutIndexRequest(searchServiceName, apiKey, indexName, indexDefinition);
            Console.WriteLine($"Put index {putIndexRequest.RequestUri}");
            Console.WriteLine();
            var putIndexResponse = httpClient.SendAsync(putIndexRequest).Result;
            var putIndexResponseContent = putIndexResponse.Content.ReadAsStringAsync().Result;
            Console.WriteLine(putIndexResponseContent);
            Console.WriteLine();

            var indexerDefinition = IndexerDefinition(dataSourceName, indexName);
            var putIndexerRequest = PutIndexerRequest(searchServiceName, apiKey, indexerName, indexerDefinition);
            Console.WriteLine($"Put indexer {putIndexerRequest.RequestUri}");
            Console.WriteLine();
            var putIndexerResponse = httpClient.SendAsync(putIndexerRequest).Result;
            var putIndexerResponseContent = putIndexerResponse.Content.ReadAsStringAsync().Result;
            Console.WriteLine(putIndexerResponseContent);
            Console.WriteLine();

            var runIndexerRequest = RunIndexerRequest(searchServiceName, apiKey, indexerName);
            Console.WriteLine($"Run indexer {runIndexerRequest.RequestUri}");
            Console.WriteLine();
            var runIndexerResponse = httpClient.SendAsync(runIndexerRequest).Result;
            Console.WriteLine($"Success: {runIndexerResponse.IsSuccessStatusCode}");
            Console.ReadLine();
        }
    }

    static HttpRequestMessage PutDataSourceRequest(string searchServiceName, string apiKey, string dataSourceName,
        string datasourceDefinition)
    {
        var request = new HttpRequestMessage(HttpMethod.Put,
            $"https://{searchServiceName}.search.windows.net/datasources/{dataSourceName}?api-version=2016-09-01");
        request.Headers.Add("api-key", apiKey);
        var body = new StringContent(datasourceDefinition, Encoding.UTF8, "application/json");
        request.Content = body;
        return request;
    }

    static HttpRequestMessage PutIndexRequest(string searchServiceName, string apiKey, string indexName,
        string indexDefinition)
    {
        var request = new HttpRequestMessage(HttpMethod.Put,
            $"https://{searchServiceName}.search.windows.net/indexes/{indexName}?api-version=2016-09-01");
        request.Headers.Add("api-key", apiKey);
        var body = new StringContent(indexDefinition, Encoding.UTF8, "application/json");
        request.Content = body;
        return request;
    }

    static HttpRequestMessage PutIndexerRequest(string searchServiceName, string apiKey, string indexerName,
        string indexerDefinition)
    {
        var request = new HttpRequestMessage(HttpMethod.Put,
            $"https://{searchServiceName}.search.windows.net/indexers/{indexerName}?api-version=2016-09-01");
        request.Headers.Add("api-key", apiKey);
        var body = new StringContent(indexerDefinition, Encoding.UTF8, "application/json");
        request.Content = body;
        return request;
    }

    static HttpRequestMessage RunIndexerRequest(string searchServiceName, string apiKey, string indexerName)
    {
        var request = new HttpRequestMessage(HttpMethod.Post,
            $"https://{searchServiceName}.search.windows.net/indexers/{indexerName}/run?api-version=2016-09-01");
        request.Headers.Add("api-key", apiKey);
        return request;
    }

    static string AzureSqlDatasourceDefinition(string connectionString, string tableName)
    {
        return @"
{
  ""description"": ""azure sql datasource"",
  ""type"": ""azuresql"",
  ""credentials"": { ""connectionString"": """ + connectionString + @""" },
  ""container"": { ""name"": """ + tableName + @""" },
  ""dataChangeDetectionPolicy"": {
    ""@odata.type"": ""#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy"",
    ""highWaterMarkColumnName"": ""highwatermark""
  },
  ""dataDeletionDetectionPolicy"": {
    ""@odata.type"": ""#Microsoft.Azure.Search.SoftDeleteColumnDeletionDetectionPolicy"",
  ""softDeleteColumnName"": ""deleted"",
  ""softDeleteMarkerValue"": ""true""
  }
}
";
    }

    static string IndexDefinition()
    {
        return @"
{
  ""fields"": [
    {
      ""name"": ""id"",
      ""type"": ""Edm.String"",
      ""key"": true,
      ""searchable"": true,
      ""sortable"": true,
      ""retrievable"": true
    },
    {
      ""name"": ""field1"",
      ""type"": ""Edm.String"",
      ""searchable"": true,
      ""retrievable"": true
    },
    {
      ""name"": ""field3"",
      ""type"": ""Edm.Int32"",
      ""retrievable"": true
    }
  ]
}
";
    }

    static string IndexerDefinition(string dataSourceName, string indexName)
    {
        return @"
{
  ""description"": ""indexer for azure sql datasource"",
  ""dataSourceName"": """ + dataSourceName + @""",
  ""targetIndexName"": """ + indexName + @""",
  ""schedule"": { ""interval"": ""P1D"" }
}
";
    }
}

Индексатор планируется запускать один раз в день. Вы можете настроить его на более частое выполнение, если данные часто меняются, но это может повлиять на пропускную способность поиска.

Это определение таблицы, если вам интересно

CREATE TABLE [dbo].[testtable](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [field1] [nchar](10) NULL,
    [field2] [nchar](10) NULL,
    [field3] [int] NULL,
    [highwatermark] [timestamp] NOT NULL,
    [deleted] [bit] NOT NULL
) ON [PRIMARY]

INSERT INTO [dbo].[testtable] (field1, field2, field3, deleted) VALUES ('abc', 'def', 123, 0)
person 8163264128    schedule 15.11.2017
comment
Спасибо. Это то, что я искал. Документы Microsoft иногда выглядят непонятно. Он показывает, как будто application / json должен войти в заголовок, но на самом деле не говорит ничего, кроме требуемой фразы. Я думаю, по крайней мере, он должен явно указывать, какая часть идет в заголовок, а какая - в тело. - person Nok Dev; 16.11.2017

Похоже, вы пытаетесь изменить определение индекса, но тело запроса содержит ключ API вместо JSON для определения индекса. API-ключ должен быть в заголовках запроса, а не в теле.

Возможно, вам будет проще использовать Azure Search .NET SDK вместо прямого вызова REST API.

person Bruce Johnston    schedule 10.11.2017
comment
Причина использования REST в том, что .net SDK не покрывает все. Несколько инженеров Microsoft сказали мне, что сначала будет обновлен REST, а затем .NET SDK. Итак, я добавил информацию из заголовка, но по-прежнему получаю ту же ошибку. Я был бы признателен, если бы вы могли изменить опубликованный мной код и показать мне, что я должен писать. - person Nok Dev; 11.11.2017
comment
.NET SDK находится на том же уровне функций, что и REST API. Версия 3.0.4 SDK соответствует версии 2016-09-01 REST API, а версия 4.0.1-preview SDK соответствует версии 2016-09-01-Preview REST API. Не должно быть никаких функций REST API, которые не поддерживаются одним из этих двух SDK. Мы очень стараемся обновить SDK в течение месяца после REST API, когда это возможно. Если вам по-прежнему нужно напрямую использовать REST API, но вы по-прежнему получаете ошибку 403, дважды проверьте, что вы используете правильный ключ api. - person Bruce Johnston; 11.11.2017
comment
Я не могу найти документ SDK о создании индексатора, который легко найти в REST. Не только поиск, но и все другие службы Azure отдают приоритет REST над .NET SDK. Они не всегда на высоте. Я проверял несколько раз, чтобы убедиться, что я предоставляю правильный ключ администратора. Все, что я пытаюсь сделать, это обновить индекс, а затем я попытаюсь создать индексатор. Я был бы признателен, если бы вы могли взглянуть на код REST или создать его для себя и посмотреть, правильно ли обновляется индекс. Я был бы признателен за любой рабочий исходный код, который успешно подключается к службе поиска с использованием REST в C #. - person Nok Dev; 12.11.2017
comment
К сожалению, вы не нашли в документации то, что вам нужно об индексаторах. Команда работает над новым контентом для индексаторов, поэтому со временем он должен улучшиться. На GitHub только что был опубликован новый пример C # с использованием .NET SDK. Это должно вам помочь: github.com/Azure-Samples / search-dotnet-getting-started / tree / Если вам нужна ссылка на .NET SDK, она находится здесь: docs.microsoft.com/dotnet/api/ - person Bruce Johnston; 13.11.2017
comment
Спасибо. Однако, как вы можете видеть, есть много случаев, когда Microsoft не может вовремя обновить документы, и скромным разработчикам, таким как я, приходится страдать или ждать ответа от stackexchange или искать какие-то сообщения в блогах. Вот почему я хочу использовать REST. Эта проблема существует не только с поиском, но и почти со всеми службами Azure. Итак, пожалуйста, помогите мне сделать успешный запрос REST для обновления индексов. Потребовались дни, чтобы выяснить, почему вызов продолжает возвращать отказ в соединении, тогда как он работает с использованием SDK. Был использован тот же ключ администратора. - person Nok Dev; 14.11.2017