Массовый запрос API 2.0 возвращает усеченные результаты, когда предложение LIMIT не используется - PullRequest
0 голосов
/ 18 марта 2020

версия 47.0

Bulk API 2.0 NOT SOQL

Создание сценария python с использованием модулей request и arguments_oathlib для test.salesforce .com / services / oauth2 / token для генерации токенов доступа и функции, которая объединяет фрагменты результатов до тех пор, пока не будет обнаружен последний фрагмент, а затем создает строку json из результатов.

мы знаем у нас в контакте 1479552 строки.

Проблема:

    SELECT id,Name,Email,Phone FROM Contact LIMIT 1850000

производит

    ccntr: 0
    size of this  chunk: 113666341 bytes
    size of total chunk: 113666341 bytes
    Sforce-NumberOfRecords for this chunk: 1479553
    Sforce-Locator for this chunk: null
    =======================
    length of bigStr   : 113643182 chars

возвращает все 1479552 строки (плюс одна строка заголовка), но

    SELECT id,Name,Email,Phone FROM Contact

производит

    ccntr: 0
    size of this  chunk: 18952552 bytes
    size of total chunk: 18952552 bytes
    Sforce-NumberOfRecords for this chunk: 246370
    Sforce-Locator for this chunk: 246370
    -----------------------
    ccntr: 1
    size of this  chunk: 18943704 bytes
    size of total chunk: 37896256 bytes
    Sforce-NumberOfRecords for this chunk: 245824
    Sforce-Locator for this chunk: 492194
    -----------------------
    ccntr: 2
    size of this  chunk: 118 bytes
    size of total chunk: 37896374 bytes
    Sforce-NumberOfRecords not found
    Sforce-Locator not found
    =======================
    length of bigStr   : 37892718 chars
    total rows for decoded_content_list: 49219

возвращает только 492196 !!! Что случилось с этим ?? !! ??

И я заметил, что при использовании предложения LIMIT возвращаются только два блока, первый содержит все или почти все данные, а второй только 110 байтов или около того, в то время как без LIMIT возвращаются 3 чанка примерно одинакового размера.

Есть и еще - с предложением LIMIT на месте один чанк возвращается с заголовком «Sforce-Locator» со значением «null» допустимая строка. Обратите внимание, что в последнем фрагменте результата без предложения LIMIT отсутствует заголовок Sforce-Locater на всех . Таким образом, поведение отличается по крайней мере на двух фронтах.

Может ли кто-нибудь проверить и / или объяснить это поведение? А еще лучше, скажите мне, как обойти это?

Дополнительный вопрос: SOQL возвращает столбцы в том же порядке, как указано в операторе SELECT, как и ожидалось. Но когда тот же оператор выполняется с помощью Bulk API 2.0, результаты возвращаются со столбцами, отсортированными в алфавитном порядке, например, Email, id, Name, Phone. Это не артефакт того, что python не поддерживает порядок в словах, я проверил необработанные данные CSV, возвращаемые запросом, прежде чем он преобразуется в JSON.

Некоторые фрагменты кода

    def getBulkQueryResults( url_to_use, access_token, operation_id, isDebug=False):
      finished = False
      bio = io.BytesIO()
      url_full = "{0}/jobs/query/{1}/results".format( url_to_use, operation_id)
      while not finished:
        r = requests.get(url_full, headers=headers ) # an object of type Response 
        header_dict = r.headers
        bio.write( r.content)
        if( 'Sforce-Locator' not in header_dict): # this may be the problem
          finished = True
        else:
          url_full = url_full + '/?locator=' + header_dict['Sforce-Locator']
      totbio = bio.getvalue()
      bigStr = totbio.decode('utf-8')
      decoded_content_list = bigStr.split('\n')
      print( "=======================")
      print( "length of bigStr   : {0} chars".format( str( len(bigStr))))
      print( "total rows for decoded_content_list: {0}".format ( str( len( decoded_content_list))))
      json_str = convertCsvListToJsonStr( decoded_content_list, isDebug)
      return json_str

    def executeBulkQuery( url_to_use, access_token, query_to_use, isDebug=False):
      if isDebug: print( "executeBulkQuery - entered")
    # to to retrieve some data
      headers = { 'Authorization' : "Bearer {0}".format( access_token)
                , 'Content-Type'  : "application/json; charset=utf-8"
                , 'Accept'        : "application/json"
                }
      boddy_dict   = { 'operation' : "query" , 'query' : query_to_use }
      boddy_json   = json.dumps( boddy_dict)
      url_full = "{0}/jobs/query".format( url_to_use)
      r = requests.post( url_full, headers=headers, data=boddy_json )
      r_dict = r.json()
      query_id = r_dict['id']
      finished = False
      while not finished:
        if( checkBulkQueryStatus( url_to_use, access_token, query_id) == "JobComplete"):
          finished = True
      json_str = getBulkQueryResults( url_to_use, access_token, query_id, isDebug)
      return json_str

TIA,

code_warrior

1 Ответ

0 голосов
/ 01 апреля 2020

Тонкий: этот оператор:

    url_full = url_full + '/?locator=' + header_dict['Sforce-Locator']

продолжает добавлять? Локатор с каждой итерацией. Решение состоит в том, чтобы переписать его на

    url_full = "{0}/jobs/query/{1}/results?locator={2}".format( url_to_use, operation_id, header_dict['Sforce-Locator'])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...