Почему NextPageToken в Google StorageClient всегда равен нулю? - PullRequest
0 голосов
/ 24 апреля 2020

Я пытаюсь перечислить все элементы по пути для определенного сегмента с помощью API Google Cloud Storage. По этому пути есть более 1000 элементов - это максимальное количество элементов, которое ListObjects / ListObjectsAsync возвращает.

Чтобы иметь возможность повторить вызов и получить следующие 1000 элементов, мне нужен NextPageToken из предыдущего ответа, вот как результат нумерации страниц! Это просто и разумно.

Однако Я никогда не получаю NextPageToken в ответах . Я что-то пропустил? Это мой код до сих пор. Некоторые ключевые моменты:

  1. Хотя существует более +1000 элементов с одинаковым префиксом, я получаю только один ответ при циклическом просмотре их в перечислителе.
  2. NextPageToken в * Оператор 1013 * всегда равен нулю.
  3. Повторение одного и того же вызова возвращает одни и те же первые 1000 объектов снова и снова.
async IAsyncEnumerable<string> ListObjectsAsync(
    string prefix, [EnumeratorCancellation] CancellationToken cancelToken)
{
    var listObjectsOptions = new ListObjectsOptions
    {
        Fields = "items(name)"
    };

    var rawResponses = mGoogleClient.ListObjectsAsync(
        mBucketName,
        prefix,
        listObjectsOptions).AsRawResponses();

    using (var enumerator = rawResponses.GetEnumerator())
    {
        while (await enumerator.MoveNext(cancelToken))
        {
            foreach (var googleObject in enumerator.Current.Items)
                yield return googleObject.Name;
        }

        Console.WriteLine(enumerator.Current.NextPageToken);
    }
}

Спасибо.

1 Ответ

1 голос
/ 24 апреля 2020

Видимо, я пропускаю поле nextPageToken в ListObjectsOptions, используемом для запроса. Без указания этого поля служба не вернет его - потому что кто знает почему!

Этот код должен работать:

async IAsyncEnumerable<string> ListObjectsAsync(
    string prefix, [EnumeratorCancellation] CancellationToken cancelToken)
{
    var listObjectsOptions = new ListObjectsOptions
    {
        Fields = "items(name),nextPageToken"
    };

    var rawResponses = mGoogleClient.ListObjectsAsync(
        mBucketName,
        prefix,
        listObjectsOptions).AsRawResponses();

    using (var enumerator = rawResponses.GetEnumerator())
    {
        while (await enumerator.MoveNext(cancelToken))
        {
            foreach (var googleObject in enumerator.Current.Items)
                yield return googleObject.Name;
        }

        Console.WriteLine(enumerator.Current.NextPageToken);
    }
}

Приятно то, что у вас даже нет использовать NextPageToken явно. Это значит, что не нужно делать что-то вроде этого:

string token = null;
do
{
    var options = new ListObjectsOptions
    {
        Fields = "items(name),nextPageToken",
        PageToen = token
    };

    var rawResponses = mGoogleClient.ListObjectsAsync(
        mBucketName,
        prefix,
        listObjectsOptions).AsRawResponses();

    using (var enumerator = rawResponses.GetEnumerator())
    {
        while (await enumerator.MoveNext(cancelToken))
        {
            foreach (var googleObject in enumerator.Current.Items)
                yield return googleObject.Name;
        }

        token = enumerator.Current.NextPageToken;
    }
}
while (!string.IsNullOrEmpty(token));

... потому что перечисленный вами счетчик rawResponses.GetEnumerator() позаботится об использовании токена ответ для автоматической выборки следующего (при необходимости) при их итерации.

Таким образом, первый фрагмент кода действителен для итерации более +1000 объектов за один вызов.

...