CloudKit JS последовательный запрос с ссылочным фильтром в Knockoutjs

Работа над сайтом дополняет приложение для iOS, и мое отсутствие знаний javascript показывает, и я мог бы использовать некоторые рекомендации.

Моя база данных CloudKit имеет как минимум два типа recordTypes: Events и Organization, каждое из которых имеет несколько полей. Организация recordType содержит ссылку на конкретные события recordNames. Я пытаюсь закодировать последовательный запрос так, чтобы после вызова каждого события его recordName затем использовалось для фильтрации запроса организации, чтобы я мог получить связанные поля имени, логотипа и т. Д. Организаций, которые ссылаются на событие.

Этот подход работает в коде iOS (XCode 7, Swift 2). Я могу успешно вызывать каждый recordType в коде knockoutjs, поэтому я знаю, что доступ к БД в порядке.

Приведенный ниже код в настоящее время настроен на то, чтобы первая функция (fetchRecords) вызывала вторую (fetchRecords2) и затем объединяла два набора записей. Я уверен, что это ужасная структура, но я пробовал разные подходы и сейчас немного растерялся.

     self.fetchRecords = function() {
        var query = { recordType: 'Events' };

        return publicDB.performQuery(query).then(function (response) {
            if(response.hasErrors) {
                console.error(response.errors[0]);
                return;
            }

            var records = response.records;
            var numberOfRecords = records.length;
            if (numberOfRecords === 0) {
                console.error('No matching items');
                return;
            }

            self.events(records);

            self.fetchRecords2();

        if (self.organization() != "") {
            self.events.push(self.organization);
            self.organization("");
            }

        });         
    };

    self.fetchRecords2 = function() {       
        var query2 = { recordType: 'Organization', filterBy: [{
                fieldName: 'events',
                comparator: 'EQUALS',
                fieldValue: {value: self.events.recordName}
            }] };

         return publicDB.performQuery(query2).then(function (response2) {
            if(response2.hasErrors) {
                console.error(response2.errors[0]);
                return;
            }

            var records2 = response2.records;
            var numberOfRecords2 = records2.length;
            if (numberOfRecords2 === 0) {
                console.error('No matching items');
                return;
            }

            self.organization(records2);


            });

        };

HTML-вызов выглядит следующим образом:

<div data-bind="foreach: events">
  <div class="display">
    <h3><span data-bind="text: recordName"></span></h3> 
    <h3><span data-bind="text: fields.event_title.value"></span></h3>
    <h3><span data-bind="text: fields.date_of_event.value"></span></h3>
    <h3><span data-bind="text: fields.event_ratings.value"></span></h3> 
    <h3><span data-bind="text: fields.organization_name.value"></span></h3>                         
  </div>
</div>

Я вижу все поля "Событие" (первые четыре), но имя_организации (полученное из типа записи организации) приводит к появлению ошибок.

Любая помощь или предложения будут с благодарностью.

1 ответ

Из вашего описания, похоже, у вас есть следующая схема:

  1. Тип записи "Организация" (с одним или несколькими полями CKReference для событий)
  2. Тип записи "Событие"

Мое предложение состоит в том, чтобы инвертировать эти отношения, а именно:

  1. Тип записи "Организация"
  2. Тип записи "Событие" (с полем CKReference для организации)

Это дает вам следующие преимущества:

  • Вы можете запросить события, а затем выбрать организацию для каждого события.
  • Вы можете использовать справочные действия:
    • "VALIDATE": CloudKit гарантирует, что организация, на которую ссылается событие, существует
    • "DELETE_SELF": CloudKit удаляет все связанные события при удалении организации
  • Добавление нового события не меняет recordChangeTag организации

Пример - запрос событий, затем выборка организаций:

var organizations = {};
function getOrCreateOrganizationObject(orgRecordName) {
   if(!organizations[orgRecordName]) {
       //You'll want to create the new object the Knockout way
       organizations[orgRecordName] = {};
   }
   return organizations[orgRecordName];
}

//Query for events
publicDB.performQuery({recordType: 'Event'})
    .then(function(response) {
        var orgNamesToLookup = [];
        var events = response.records.map(function(record) {
            var orgRecordName = record.fields.organization.value.recordName;

            var organization = getOrCreateOrganizationObject(orgRecordName);

            var event = {
                recordName: record.recordName,
                title: record.fields.event_title.value,
                date: record.fields.date_of_event.value,
                rating: record.fields.event_ratings.value,
                //Note: You probably need some additional plumbing
                //      for this to work with Knockout
                organization: organization
            };
            return event;
        });

        //You can already show the list of events at this point, e.g.
        //something like: self.events(events)

        var orgRecordNames = Object.keys(organizations);
        return publicDB.fetchRecords(orgRecordNames)
            .then(function(response) {
                response.records.forEach(function(orgRecord) {
                    var organization = getOrCreateOrganizationObject[orgRecord.recordName];
                    organization.name = orgRecord.fields.name.value;
                });
            });
    })

Тогда в вашем HTML у вас будет что-то вроде этого:

<div data-bind="foreach: events">
  <div class="display">
    <h3><span data-bind="text: recordName"></span></h3> 
    <h3><span data-bind="text: event_title"></span></h3>
    <h3><span data-bind="text: date_of_event"></span></h3>
    <h3><span data-bind="text: event_ratings"></span></h3> 
    <h3><span data-bind="text: organization.name"></span></h3>                         
  </div>
</div>

НТН

PS: в реальном приложении вы бы также хотели обрабатывать ошибки и случай, когда в исходном запросе больше событий, чем было возвращено.

Другие вопросы по тегам