Невозможно развернуть функцию события дивана

У меня есть документ "студент" в ведре студенческих записей, где id - это задокументированный.

{
  "id":"101",
  "fname": "abc",
  "lname": "xyz",
  "rank": "1",
  "scholarShip": "",
  "grade": ""
}

Моя работа - найти всех студентов с рангом 1, а затем обновить «стипендию» и «оценку» в соответствующих документах.

Я создал функцию события в Couchbase, как показано ниже.

function OnUpdate(doc, meta) {
    log('docId', meta.id);
       try {
        var rankValue = SELECT rank FROM `student-records` USE KEYS ["id"];
        for (var rv of rankValue) {
            if (rv==1) {  
               UPDATE `student-records` USE KEYS ["id"] set scholarShip="100%", grade="A";
        }
     }
    } catch(e) { log(e); } 
}

при развертывании я получаю сообщение об ошибке:

Ошибка развертывания: синтаксическая ошибка (7, 16) - не удается выполнить запрос DML в сегменте «студенческие записи».

при создании функции я заявил:

исходный сегмент => студенческие записи

ведро метаданных => метаданные-записи-студента


person Bifrost    schedule 12.12.2019    source источник


Ответы (1)


Давайте рассмотрим ваш вопрос - интуитивно я знаю ответ (запись в исходную корзину (проблема-A) и неправильное использование ключей (проблема-B)), но мы можем немного улучшить ваш код, пройдя по ним, чтобы выделить оба лучших практики и объяснят вам, что вам нужно. Сначала предположим, что у вас будет другой документ рядом с записью студента, поэтому добавьте поле «Тип». Ниже я показываю один образец записи, который я мог бы поместить в ваши «студенческие записи» (type = student, это мое добавленное поле).

{  "id":"101", "fname": "abc", "lname": "xyz", 
"rank": "1", "scholarShip": "", "grade": "", 
"type": "student" }

Далее, поскольку couchbase работает лучше, ограничивая количество ведер примерно 10 ведрами (и 30 ведрами для версии 6.5, которая находится в бета-версии). На самом деле нам не нужна целая куча разных сегментов «метаданных» для отдельных функций обработки событий, поэтому я обычно делаю общую корзину, называемую «мета», для всех моих функций обработки событий. В том же духе, если вы думаете об этом, добавив поле типа, вы можете хранить много разных типов данных в корзине, так почему бы нам также не переименовать student-records в корзину общего назначения school. Таким образом, корзина school может содержать несколько типов: тип = ученики, тип = учителя, тип = класс, тип = расписание и т. Д. И т. Д.

Итак, я создаю две корзины 1) school и 2 meta, а затем вставляю тестовую запись через редактор QUERY пользовательского интерфейса.

INSERT INTO `school` ( KEY, VALUE ) VALUES
(
   "student101",
   {  "id":"101", "fname": "abc", "lname": "xyz", 
      "rank": "1", "scholarShip": "", "grade": "", "type": "student" }
)

Чтобы помочь / разрешить наши запросы по определенным типам, давайте создадим индекс N1QL в редакторе QUERY пользовательского интерфейса.

CREATE INDEX adv_type ON `school`(`type`);

Теперь посмотрим на наши тестовые данные в редакторе QUERY пользовательского интерфейса.

SELECT * FROM `school` WHERE type = "student";

Возвращаются ожидаемые данные JSON.

[
  {
    "school": {
      "fname": "abc",
      "grade": "",
      "id": "101",
      "lname": "xyz",
      "rank": "1",
      "scholarShip": "",
      "type": "student"
    }
  }
]

Всегда полезно протестировать N1QL перед тем, как поместить его в Eventing, поэтому давайте сделаем пробный запуск в редакторе QUERY пользовательского интерфейса. Пожалуйста, посмотрите на КЛЮЧ и на то, как он построен как конкатенация как «типа», так и «идентификатора», чтобы у нас был существующий КЛЮЧ - это относится к проблеме-B, где вы использовали строку «id» в своей исходной функции Eventing. .

UPDATE `school` USE KEYS ["student101"] 
set scholarShip="100%", grade="A" WHERE type="student";

Давайте еще раз посмотрим на результат

SELECT * FROM `school` WHERE type = "student";

Возвращаются ожидаемые данные JSON.

[
  {
    "school": {
      "fname": "abc",
      "grade": "A",
      "id": "101",
      "lname": "xyz",
      "rank": "1",
      "scholarShip": "100%",
      "type": "student"
    }
  }
]

Теперь давайте вернем данные в исходное состояние (я не показываю результаты)

UPDATE `school` USE KEYS ["student101"] 
set scholarShip="", grade="" WHERE type="student";

Обратите внимание, поскольку мы используем KEYS, мне не нужно было использовать предложение WHERE type = "student" в предыдущих операторах UPDATE, но оно подчеркивает, как различать, когда у вас есть несколько типов в одном сегменте.

Хорошо, теперь пора сделать функцию троеборья, но на этом этапе мы должны понять некоторые аспекты троеборья.

  • Для версий Couchbase, начиная с 6.0.X, вы не можете выполнять обратную запись в исходную корзину через Eventing.
  • Для версии 6.5 (которая является бета-версией) вы можете писать обратно в исходную корзину через карту KV с псевдонимом (но не через N1QL).

Причина этого ограничения заключается в том, что вы можете создавать циклические зависимости, запускающие бесконечные рекурсивные операции по событию, и очень сложно обнаружить такие вхождения в N1QL, в отличие от понимания прямой операции из функции обработки событий на карте KV с псевдонимом.

Итак, продвигаясь вперед, реализуя вашу фактическую функцию Eventing, у вас есть два варианта, чтобы заставить вашу фактическую функцию Eventing использовать запрос 6.5 с N1QL, но вернуть биты через KV или создать целевую корзину. Я предполагаю, что вы используете 6.5-бета в этом случае, когда мы определяем нашу функцию, которую хотим: а) сегмент исходного кода "школа", б) сегмент метаданных "мета" и в) псевдоним сегмента "школа" для bucket 'school' установлен на 'чтение и запись' следующим образом:

экран настройки

Обратите внимание, что при создании псевдонимов не используйте символ '-', так как это недопустимое имя переменной javascript и вы будете жаловаться при попытке развернуть функцию Eventing.

И в коде событий здесь нам даже не нужно использовать N1QL, мы используем открытую карту KV Javascript (я использовал псевдоним «школа» для сегмента «школа», этот псевдоним - карта Javascript, которая раскрывает корзину с помощью своих КЛЮЧЕЙ.

function OnUpdate(doc, meta) {
    log('docId', meta.id);
    if (doc.type != "student") return;
    if (doc.rank == 1) {
        try {
            doc.grade = "A";
            doc.scholarShip = "100%";
            school[meta.id] = doc;
        } catch(e) { 
            log(e); 
        } 
    }
}

Теперь, если вы развернете функцию (для всего), вы увидите, что единственная имеющаяся у вас запись автоматически обновляется Eventing, поскольку эта запись имела ранг 1.

Запустите запрос выбора и убедитесь, например,

SELECT * FROM `school` WHERE type = "student";

Если Eventing работает, вы можете вернуть данные обратно с помощью нашего предыдущего ОБНОВЛЕНИЯ, но, поскольку это генерирует мутацию, Eventing немедленно вернет его обратно в обработанное состояние (будьте уверены, что обновление действительно работает, но с ранга = 1 оно повторно обрабатывается, потому что Eventing работает и развернут, и он уловил мутацию, созданную вами в пользовательском интерфейсе QUERY):

UPDATE `school` USE KEYS ["student101"] 
set scholarShip="", grade="" WHERE type="student";

Конечно, каждый раз, когда запускается событие, он будет записывать в журнал (доступный через вкладку Eventing пользовательского интерфейса для вашей функции) такую ​​информацию, как следующая:

2019-12-12T15:30:18.153-07:00 [INFO] "docId" "student101"

Если вам нужна помощь с N1QL или реализация решения до 6.5-beta, не стесняйтесь обращаться ко мне напрямую.

person Jon Strabala    schedule 12.12.2019
comment
Большое спасибо за подробное объяснение. Я использую Couchbase 6.0.3. Как мне добиться того же в этой версии? - person Bifrost; 13.12.2019
comment
Как я уже сказал, для версий Couchbase, хотя и 6.0.X, вы не можете записывать обратно в исходную корзину через Eventing. Создайте еще один сегмент для чтения-записи и псевдонима, называемый update, и просто измените school[meta.id] = doc; на. updates[meta.id] = doc;. - person Jon Strabala; 14.12.2019