Запрос Cosmos sql, который не возвращает массив - PullRequest
1 голос
/ 16 июня 2020

Я пытаюсь запросить базу данных Cosmos, чтобы узнать идентификаторы всех ее контейнеров.

Используя приведенный ниже код, он дает мне ответ json, который является одним элементом (а не массивом).

Есть ли способ написать запрос, чтобы я получал только массив полей id из DocumentCollection. например, что-то вроде

 [ { "id": "Summary-v00019"}, {"id": "Details-V00019"} ]
using Microsoft.Azure.Cosmos;
using System;
using System.IO;

namespace QueryDatabase
{
    class Program
    {
        const string CosmosConnectionString = "AccountEndpoint=https://some-cosmos-ccount.documents.azure.com:443/;AccountKey=blahblah==;";

        const string Database = "database-name";

        static async System.Threading.Tasks.Task Main()
        {

            var cosmosClient = new CosmosClient(CosmosConnectionString);

            var database = cosmosClient.GetDatabase(Database);

            string queryText = "SELECT * FROM c";
            QueryDefinition queryDefinition = new QueryDefinition(queryText);
            FeedIterator feedIterator = database.GetContainerQueryStreamIterator(queryDefinition);
            while (feedIterator.HasMoreResults)
            {
                using (ResponseMessage response = await feedIterator.ReadNextAsync())
                {
                    using (var sr = new StreamReader(response.Content))
                    {
                        var text = sr.ReadToEnd();
                        Console.WriteLine(text);
                    }
                }
            }
        }
    }
}

JSON Ответ из приведенного выше кода:

{
    "_rid": "blah==",
    "DocumentCollections": [
        {
            "id": "Summary-v00019",
            "indexingPolicy": {
                "indexingMode": "consistent",
                "automatic": true,
                "includedPaths": [
                    {
                        "path": "/*"
                    }
                ],
                "excludedPaths": [
                    {
                        "path": "/\"_etag\"/?"
                    }
                ]
            },
            "partitionKey": {
                "paths": [
                    "/foo"
                ],
                "kind": "Hash"
            },
            "conflictResolutionPolicy": {
                "mode": "LastWriterWins",
                "conflictResolutionPath": "/_ts",
                "conflictResolutionProcedure": ""
            },
            "geospatialConfig": {
                "type": "Geography"
            },
            "_rid": "blah=",
            "_ts": 1591935021,
            "_self": "dbs/blah==/colls/blah=/",
            "_etag": "\"blah-blah-blah-0000-blah\"",
            "_docs": "docs/",
            "_sprocs": "sprocs/",
            "_triggers": "triggers/",
            "_udfs": "udfs/",
            "_conflicts": "conflicts/"
        },
        {
            "id": "Details-v00019",
            "indexingPolicy": {
                "indexingMode": "none",
                "automatic": false,
                "includedPaths": [],
                "excludedPaths": []
            },
            "partitionKey": {
                "paths": [
                    "/bar"
                ],
                "kind": "Hash"
            },
            "conflictResolutionPolicy": {
                "mode": "LastWriterWins",
                "conflictResolutionPath": "/_ts",
                "conflictResolutionProcedure": ""
            },
            "geospatialConfig": {
                "type": "Geography"
            },
            "_rid": "blah=",
            "_ts": 1591935021,
            "_self": "dbs/blah==/colls/blah=/",
            "_etag": "\"blah-0000-blah-0000-blah\"",
            "_docs": "docs/",
            "_sprocs": "sprocs/",
            "_triggers": "triggers/",
            "_udfs": "udfs/",
            "_conflicts": "conflicts/"
        }
    ],
    "_count": 2
}

Ответы [ 3 ]

1 голос
/ 17 июня 2020

Прежде всего, есть что-то подозрительное в инструкции select, НЕ выбирающей то, что вы ему указываете. Скорее всего, это ошибка cosmosDB .

Кажется, что ваши выбранные результаты всегда возвращаются в фиксированной оболочке:

{
    "_rid": "...",
    "DocumentCollections": [  ], // .. your select applies here .. 
    "_count": N
}

Кажется чтобы не было возможности избавиться от этой обертки. Но вы можете ограничить содержимое DocumentCollections. Например, используйте запрос:

SELECT c.id FROM c

, который должен дать результат:

{
    "_rid":"blah==",
    "DocumentCollections":[ 
        {"id": "Summary-v00019"}, 
        {"id": "Details-V00019"} 
    ],
    "_count":2
}

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

1 голос
/ 18 июня 2020

Cosmos DB возвращает все операции запроса, чтения и изменения веб-канала в оболочке.

Вот несколько примеров того, как это сделать с помощью версии 3.10.0, где FeedIterator теперь реализует IDisposable для исправления утечка памяти.

  using (FeedIterator feedIterator = this.cosmosDatabase.GetContainerQueryStreamIterator(
                "select value c.id From c "))
{
   // The current logic is not handling if there is a loop.
    while (feedIterator.HasMoreResults)
    {
        using (ResponseMessage response = await feedIterator.ReadNextAsync())
        {
            response.EnsureSuccessStatusCode();
            using (StreamReader streamReader = new StreamReader(response.Content))
            {
                string content = await streamReader.ReadToEndAsync();
                // Output will be:
                // {"_rid":"7p8wAA==","DocumentCollections":["4d310b0d-1716-4bc8-adfa-861a66e4034b","e3eb4ac7-f8a4-47ce-bd71-f65ab43dcb53"],"_count":2}
                int arrayStart = content.IndexOf('[');
                int arrayEnd = content.IndexOf(']');
                string json = content.Substring(arrayStart, arrayEnd - arrayStart + 1);
            }
        }
    }
}

Это пример использования типизированного API. Вы не должны часто запрашивать список контейнеров, поэтому использование типизированного API может стоить снижения производительности.

List<string> ids = new List<string>();
using (FeedIterator<string> feedIterator = this.cosmosDatabase.GetContainerQueryIterator<string>(
        "select value c.id From c "))
{
    while (feedIterator.HasMoreResults)
    {
        FeedResponse<string> iterator = await feedIterator.ReadNextAsync();
        ids.AddRange(iterator);
    }
}

string json = JsonConvert.SerializeObject(ids);
0 голосов
/ 16 июня 2020

Попробуйте следующее:

static async System.Threading.Tasks.Task Main()
    {

        var cosmosClient = new CosmosClient(EndpointUri, PrimaryKey);

        var database = cosmosClient.GetDatabase(databaseId);
        string queryText = "SELECT c.id FROM c";
        QueryDefinition queryDefinition = new QueryDefinition(queryText);
        FeedIterator feedIterator = database.GetContainerQueryStreamIterator(queryDefinition);
        while (feedIterator.HasMoreResults)
        {
            using (ResponseMessage response = await feedIterator.ReadNextAsync())
            {
                using (var sr = new StreamReader(response.Content))
                {
                    string text = sr.ReadToEnd();
                    Console.WriteLine(text);
                    JObject json = (JObject)JsonConvert.DeserializeObject(text);
                    Console.WriteLine(json["DocumentCollections"]);
                }
            }
        }
    }

Результат:

{"_rid":"R-5RAA==","DocumentCollections":[{"id":"orders"},{"id":"user"},{"id":"employee"}],"_count":3}
[
  {
    "id": "orders"
  },
  {
    "id": "user"
  },
  {
    "id": "employee"
  }
]

Надеюсь, это вам поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...