عرض التقارير باستخدام GoogleAdsService

لاسترداد كيانات Google Ads API وبيانات التقارير، استخدِم إحدى الطرق التالية:

في ما يلي الاختلافات الرئيسية بين الطريقتَين:

GoogleAdsService.SearchStream GoogleAdsService.Search
مناسب لرمز الإنتاج نعم نعم
الخدمة GoogleAdsService GoogleAdsService
السيناريو جارٍ جلب العناصر والتقارير جارٍ جلب العناصر والتقارير
الردّ مجموعة من عناصر GoogleAdsRow صفحات من عناصر GoogleAdsRow
حقول الردّ المستخدمون المحدّدون في طلب البحث فقط المستخدمون المحدّدون في طلب البحث فقط
الحدود اليومية الحدود اليومية استنادًا إلى مستويات الوصول الحدود اليومية استنادًا إلى مستويات الوصول

بينما تُرسِل Search طلبات متعددة مقسّمة على صفحات لتنزيل تقرير كامل، تُرسِل SearchStream طلبًا واحدًا وتبدأ اتصال gRPC دائمًا مع Google Ads API بغض النظر عن حجم التقرير.

بالنسبة إلى SearchStream، يبدأ تنزيل حِزم البيانات على الفور في دفعات من عناصر SearchGoogleAdsStreamResponse. يمكن للرمز البرمجي تكرار الدفعات الواردة عند وصولها بدون انتظار انتهاء البث بالكامل.

من خلال إلغاء الوقت الذي تستغرقه الشبكة في إرسال البيانات واستقبالها لطلب كل صفحة فردية من استجابة Search، يقدّم SearchStream أداءً أفضل من التنقّل بين الصفحات، خاصةً للتقارير الكبيرة.

مثال

يتناول هذا المثال تقريرًا يتألف من 100,000 صف. يوضّح الجدول التالي الاختلافات بين الطلبات والردود في الطريقتَين:

SearchStream بحث
حجم الصفحة غير سارٍ ‫10,000 صف في كل صفحة
عدد طلبات البيانات من واجهة برمجة التطبيقات طلب واحد ‫10 طلبات
عدد الردود من واجهة برمجة التطبيقات بث مباشر واحد متواصل ‫10 ردود

عوامل الأداء

في معظم حالات الاستخدام، ننصح باستخدام SearchStream بدلاً من Search للأسباب التالية:

  • التقارير المكوّنة من صفحة واحدة (أقل من 10,000 صف): لا توجد اختلافات كبيرة في الأداء بين الطريقتين.
  • التقارير المتعدّدة الصفحات: يكون SearchStream عادةً أسرع لأنّه يتجنّب رحلات الذهاب والعودة المتعدّدة على الشبكة، كما أنّ القراءة أو الكتابة من ذاكرة التخزين المؤقت للقرص تكون أقل تأثيرًا.
  • كفاءة الذاكرة: عند معالجة تقارير كبيرة باستخدام SearchStream، يجب تكرار العملية على أجزاء من مصدر البيانات ومعالجة الصفوف فور وصولها بدلاً من تخزين جميع الصفوف مؤقتًا في الذاكرة في الوقت نفسه لتجنُّب أخطاء نفاد الذاكرة (OOM).
  • مرونة الاتصال: نظرًا لأنّ SearchStream يعتمد على اتصال مستمر، يمكن أن تتم مقاطعة عمليات البث الطويلة بسبب انقطاع الشبكة أو انتهاء المهلة المحددة. اضبط مهلات RPC المناسبة ونفِّذ منطق إعادة المحاولة لأخطاء البث المؤقتة.

الحدود القصوى لمعدّل الاستخدام

تلتزم حدود العمليات اليومية لكلتا الطريقتَين بالحدود العادية ومستويات الوصول لمشروعك على Google Cloud. يتم احتساب طلب البحث المنطقي الواحد للتقرير كعملية واحدة ضمن حصة العمليات اليومية بغض النظر عما إذا كانت النتيجة يتم بثها باستخدام SearchStream أو استردادها عبر صفحات مخزنة مؤقتًا متعددة باستخدام Search مع page_token. ومع ذلك، لا يزال كل طلب Search مقسّم إلى صفحات يُحتسب كمكالمة RPC فردية ضمن حدود المعدّل على المدى القصير.

مثال على الرمز البرمجي

يوضّح نموذج الرمز البرمجي التالي كيفية تنفيذ طلب بحث لتقرير بث مباشر باستخدام مكتبات العملاء:

جافا

private void runExample(GoogleAdsClient googleAdsClient, long customerId) {
  try (GoogleAdsServiceClient googleAdsServiceClient =
      googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
    String query = "SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id";
    // Constructs the SearchGoogleAdsStreamRequest.
    SearchGoogleAdsStreamRequest request =
        SearchGoogleAdsStreamRequest.newBuilder()
            .setCustomerId(Long.toString(customerId))
            .setQuery(query)
            .build();

    // Creates and issues a search Google Ads stream request that will retrieve all campaigns.
    ServerStream<SearchGoogleAdsStreamResponse> stream =
        googleAdsServiceClient.searchStreamCallable().call(request);

    // Iterates through and prints all of the results in the stream response.
    for (SearchGoogleAdsStreamResponse response : stream) {
      for (GoogleAdsRow googleAdsRow : response.getResultsList()) {
        System.out.printf(
            "Campaign with ID %d and name '%s' was found.%n",
            googleAdsRow.getCampaign().getId(), googleAdsRow.getCampaign().getName());
      }
    }
  }
}
      

#C

public void Run(GoogleAdsClient client, long customerId)
{
    // Get the GoogleAdsService.
    GoogleAdsServiceClient googleAdsService = client.GetService(
        Services.V26.GoogleAdsService);

    // Create a query that will retrieve all campaigns.
    string query = @"SELECT
                    campaign.id,
                    campaign.name,
                    campaign.network_settings.target_content_network
                FROM campaign
                ORDER BY campaign.id";

    try
    {
        // Issue a search request.
        googleAdsService.SearchStream(customerId.ToString(), query,
            delegate (SearchGoogleAdsStreamResponse resp)
            {
                foreach (GoogleAdsRow googleAdsRow in resp.Results)
                {
                    Console.WriteLine("Campaign with ID {0} and name '{1}' was found.",
                        googleAdsRow.Campaign.Id, googleAdsRow.Campaign.Name);
                }
            }
        );
    }
    catch (GoogleAdsException e)
    {
        Console.WriteLine("Failure:");
        Console.WriteLine($"Message: {e.Message}");
        Console.WriteLine($"Failure: {e.Failure}");
        Console.WriteLine($"Request ID: {e.RequestId}");
        throw;
    }
}
      

PHP

public static function runExample(GoogleAdsClient $googleAdsClient, int $customerId)
{
    $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
    // Creates a query that retrieves all campaigns.
    $query = 'SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id';
    // Issues a search stream request.
    /** @var GoogleAdsServerStreamDecorator $stream */
    $stream = $googleAdsServiceClient->searchStream(
        SearchGoogleAdsStreamRequest::build($customerId, $query)
    );

    // Iterates over all rows in all messages and prints the requested field values for
    // the campaign in each row.
    foreach ($stream->iterateAllElements() as $googleAdsRow) {
        /** @var GoogleAdsRow $googleAdsRow */
        printf(
            "Campaign with ID %d and name '%s' was found.%s",
            $googleAdsRow->getCampaign()->getId(),
            $googleAdsRow->getCampaign()->getName(),
            PHP_EOL
        );
    }
}
      

Python

def main(client: GoogleAdsClient, customer_id: str) -> None:
    ga_service: GoogleAdsServiceClient = client.get_service("GoogleAdsService")

    query: str = """
        SELECT
          campaign.id,
          campaign.name
        FROM campaign
        ORDER BY campaign.id"""

    # Issues a search request using streaming.
    stream: Iterator[SearchGoogleAdsStreamResponse] = ga_service.search_stream(
        customer_id=customer_id, query=query
    )

    for batch in stream:
        rows: List[GoogleAdsRow] = batch.results
        for row in rows:
            print(
                f"Campaign with ID {row.campaign.id} and name "
                f'"{row.campaign.name}" was found.'
            )
      

Ruby

def get_campaigns(customer_id)
  # GoogleAdsClient will read a config file from
  # ENV['HOME']/google_ads_config.rb when called without parameters
  client = Google::Ads::GoogleAds::GoogleAdsClient.new

  responses = client.service.google_ads.search_stream(
    customer_id: customer_id,
    query: 'SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id',
  )

  responses.each do |response|
    response.results.each do |row|
      puts "Campaign with ID #{row.campaign.id} and name '#{row.campaign.name}' was found."
    end
  end
end
      

Perl

sub get_campaigns {
  my ($api_client, $customer_id) = @_;

  # Create a search Google Ads stream request that will retrieve all campaigns.
  my $search_stream_request =
    Google::Ads::GoogleAds::V26::Services::GoogleAdsService::SearchGoogleAdsStreamRequest
    ->new({
      customerId => $customer_id,
      query      =>
        "SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id"
    });

  # Get the GoogleAdsService.
  my $google_ads_service = $api_client->GoogleAdsService();

  my $search_stream_handler =
    Google::Ads::GoogleAds::Utils::SearchStreamHandler->new({
      service => $google_ads_service,
      request => $search_stream_request
    });

  # Issue a search request and process the stream response to print the requested
  # field values for the campaign in each row.
  $search_stream_handler->process_contents(
    sub {
      my $google_ads_row = shift;
      printf "Campaign with ID %d and name '%s' was found.\n",
        $google_ads_row->{campaign}{id}, $google_ads_row->{campaign}{name};
    });

  return 1;
}
      

curl