Получение более 100 записей с Airtable

Я создаю приложение, которое получает базу данных на Airtable с библиотекой запросов и преобразует ее в список.

Моя проблема в том, что я могу получить только 100 записей с запросом URL. Я пытался найти решение в API Airtable, но изменения в URL для вставки maxRecords не работали.

Я использую этот URL для получения данных. Но он возвращает только 100 записей.

    https://api.airtable.com/v0/appP6G7OJmLzUCoUt/Table%201?api_key=MY_KEY

Я читал о maxRecords и разбивке на страницы, но не смог найти способ изменить URL, чтобы использовать это.

Кто-нибудь может мне помочь?

1 ответ

TLDR:
Вы можете попробовать использовать рекурсивную функцию, которая выполняется, когда в ответе http (json) существует смещение.

Подтверждение:
Это решение заняло 7 часов исследований, поиска неисправностей и советов от великого и влиятельного Дуга. Проект использует Alamofire для выполнения http-запросов и SwiftyJson для доступа к JSON.

Причина:
В документации Airtable указывается, что их лимит скорости составляет 100 единиц на запрос. Если запрос содержит более 100 элементов, запрос будет включать смещение.

Они дают указание включить смещение в ваш следующий запрос, чтобы получить следующие 100 результатов. Но они не объясняют и не демонстрируют, как это сделать.

Решение:
Он был протестирован на получение 2565 элементов из 25 HTTP-запросов. Написанная на Swift, логика проста:

Напишите рекурсивную функцию с аргументом для необязательного смещения. Вызовите функцию без смещения. Проверьте HTTP-ответ (JSON) для смещения. Если смещение существует, сохраните http-запрос (json) в массиве вне функции. Затем вызовите эту же функцию изнутри себя - на этот раз со смещением.

Расширенный код здесь.

func requestAirtableRecords(forTable table: String, withTableView tableView: String, withOffset offset: String?, completion: @escaping ([JSON]) -> ()) {
    let parameters: [String: Any] = offset != nil ? ["view": tableView, "offset": offset!] : ["view": tableView]
    do {
        let url: URLRequest = try self.requestRecordsURL(table: table, method: HttpRequest.get, parameters: parameters)!
        Alamofire.request(url).responseJSON { (response) in
            switch response.result {
            case .success(_):
                let json = JSON(response.result.value!)
                self.jsonArray.append(json)
                let nextOffset = json["offset"]
                if nextOffset.exists() {
                    self.requestAirtableRecords(forTable: table, withTableView: tableView, withOffset: nextOffset.stringValue, completion: { _ in
                        completion(self.jsonArray)
                    })
                } else {
                    completion(self.jsonArray)
                }
            case .failure(let error):
                print(error)
            }
        }
    } catch {
        print("Error: Unable to request records from Airtable.")
    }
}

Как я видел в других постах, многие люди имели дело с той же проблемой. Я пытался найти решения, но я не смог исправить это с помощью URL.

Хотя, слава богу, все данные из Airtable в Python легче получить с помощью библиотеки API Airtable. ( http://airtable-python-wrapper.readthedocs.io/en/master/)

Есть функция get_all(), которая принимает аргумент maxRecords. Просто вызовите x.get_all() без аргументов внутри, и API вернет каждую запись в таблице.

Это код, который я использовал в Python для решения этой проблемы - в соответствии с ответом Кристиана я использовал рекурсивный вызов. Однако я публикую этот код, потому что OP запросил ответ на Python.

def get_airtable_data(email_dict=None, offset=None):
        """
        queries airtable and creates a dict of {name: email} from records that are 
        listed as subscribed
        """

    if email_dict is None:
        email_dict = {}
    r = requests.get(request_url, headers={"Authorization": bearer_token}, params={"pageSize": 100, "offset": offset})
    r_json = json.loads(r.text)
    for item in r_json["records"]:
        if item["fields"]["subscribed"] == 1:
            email_dict[item["fields"]["Name"]] = item["fields"]["Primary Email"]

    if r_json["offset"] is None:
        print("all data loaded")
    else:
        try:
            get_airtable_data(email_dict, r_json["offset"])
        except KeyError:
            print("all data loaded")
    return email_dict
Другие вопросы по тегам