0

データを取得しているAPIがあり、このAPIからすべてのタグを収集したいのですが、タグの数が事前にわからないため、APIは返された結果の最大数を介してアクセスを抑制します任意の1回の呼び出し(100)。ただし、ページ数に制限はありません。

したがって、呼び出しは次のようになります。Tag.update_tags(100, 5)ここ100で、は1回の呼び出しで返されるオブジェクトの最大数であり、5開始するページです(つまり、タグが順番に格納されていると仮定すると、IDが含まれるタグレコードが返されます。の範囲401 - 500

問題は、手動で入力する必要がないことです5(つまり、上限が何であるかわかりません)。タグの総数にpingを実行する方法はありません(タグがある場合は、単純に分割して、この呼び出しをその数までループに入れます)。

私が知っているのは、結果がないページに到達すると、空の配列が返されるということだけ[]です。

では、すべてのタグをループして、返される結果が空の配列(返される最終結果であるため評価されない)になったときに停止するにはどうすればよいですか?

そのループはどのように見えますか?

4

2 に答える 2

1

結果が空の配列を返す場合は、break ステートメントで無条件ループを使用します。

i = 1
loop do
  result = call_to_api(i)
  do_something_with(result)
  i += 1
  break if result.empty?
end

もちろん、プロダクション シナリオでは、ループが無限にならないようにするために、例外ハンドラー、進行状況ログのレポート、ある種の具体的な反復制限など、もう少し堅牢なものが必要です。

アップデート

クラスを使用してロジックをまとめる例を次に示します。

class Api
  DEFAULT_OPTIONS = {:start_position => 1, :max_iterations => 1000}

  def initialize(base_uri, config)
    @config = DEFAULT_OPTIONS.merge(config)
    @position = config[:start_position]
    @results_count = 0
  end

  def each(&block)
    advance(&block) while can_advance?
    log("Processed #{@results_count} results")
  end

  def advance(&block)
    yield result
    @results_count += result.count
    @position += 1
    @current_result = nil
  end

  def result
    @current_result ||= begin
      response = Net::HTTP.get_response(current_uri)
      JSON.decode(response.body)
    rescue
      # provide some exception handling/logging
    end
  end

  def can_advance?
    @position < (@config[:start_position] + @config[:max_iterations]) && result.any?
  end

  def current_uri
    Uri.parse("#{@base_uri}?page=#{@position}")
  end
end

api = Api.new('http://somesite.com/api/v1/resource')

api.each do |result|
  do_something_with(result)
end

これには、各スレッドの開始カウントと反復カウントを設定することで同時実行を可能にする角度もあります。これにより、同時 http 要求でこれが確実に高速化されます。

于 2013-02-22T23:45:08.800 に答える
0

うーん。一度に 100 個のアイテムを取得し、特定のページから開始できます。反復を実装する方法は、何をしたいかによって異なります。一意のタグをすべて収集するとします。マップ (HashMap など) を確立し、一度に 1 ページを取得して処理します。空のページにアクセスすると、完了です。

// Implements a map and methods to update it
MyHashMap uniqueTags;
// Stores a page of tags
Page page;
Do
    // get a page of tags
    page = readTags();
    if (page != null) {
        uniqueTags.getUniqueTags(page);
    } else {
        break;
    }
until (page == null);
于 2013-02-22T23:08:11.993 に答える