Я уверен, что у меня что-то не хватает, но я считаю, что API Bookshelf неумолимо запутывает меня. Вот что я пытаюсь сделать:
- У меня есть модель под названием
Radio
с первичным ключом строки с именем приложения с именемserial
и для этого примера два поля с именемexample1
иexample2
. Я указал пользовательский идентификатор сidAttribute: 'serial'
в определении модели. - Я пытаюсь выполнить upsert с Bookshelf (не с Knex напрямую, в моем фактическом приложении этот запрос становится довольно сложным).
- У меня есть дело ввода вставки, но я не могу заставить дело обновления работать.
- Для простоты я сейчас не забочусь о транзакциях или атомарности. Я доволен, чтобы получить простой select → вставить/обновить для работы.
И конкретно в этом примере:
- Вставить набор вставки
example1
иexample2
. - В наборе обновлений
example1
и оставьтеexample2
неизменным.
Итак, у меня есть что-то подобное в модели Bookshelf, так как метод класса (то есть "статический" ) ( "info" имеет поля "serial", "example1" и "example2" ):
insertOrUpdate: function (info) {
return new Radio({'serial':info.serial}).fetch().then(function (model) {
if (model) {
model.set('example1', info.example1);
return model.save({}, {
method: 'update',
patch: true
})
} else {
return new Radio({
serial: info.serial,
example1: info.example1,
example2: info.example2
}).save({}, {
method: 'insert'
})
}
}).then(function (model) {
console.log("SUCCESS");
}).catch(function (err) {
console.log("ERROR", err);
});
}
Пример вызова:
Radio.insertOrUpdate({
serial: ...,
example1: ...,
example2: ...
})
Проблема, с которой я столкнулся, заключается в том, что, хотя дело "вставка" работает, случай "обновления" завершается с:
ERROR { Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where `serial` = '123223'' at line 1
Что очевидно при включенной отладке Knex, где в сгенерированном запросе отсутствует предложение set
:
update `radios` set where `serial` = ?
Теперь я сосредоточен на документах Bookshelf для fetch
и save
, и мне интересно, пойду ли я в неправильном направлении.
Я знаю, что неправильно использую API, но не могу понять. Несколько странных вещей, которые я заметил/должен был сделать, чтобы получить его в полурабочее состояние:
-
Я не понимаю первый параметр
save
. Было бы разумно, если бы сохранить был статический методModel
, но это не так. Это метод экземпляра, и вы уже можете передавать атрибуты конструкторуModel
(например, что бы обозначитьnew X(a:1).save({a:2})
...?), И вы уже можете установить атрибуты сset
до сохранения. Поэтому я не могу понять это. Мне пришлось передать{}
в качестве заполнителя, чтобы указать параметры. -
Существует эта
forge
, но я не уверен, какова ее цель, поскольку вы уже можете передавать атрибуты конструкторуModel
если авторы не нашли преимущества дляX.forge({a:1})
vs.new X({a:1})
...?). -
Я обнаружил, что мне нужно явно указать способ сохранения из-за кажущегося quirk Bookshelf: Bookshelf основывает свой выбор метода на
isNew()
, ноisNew()
всегдаtrue
, когда вы передаете идентификатор к конструктору модели, который вы должны выполнить в случае с идентификатором приложения. Поэтому для присвоенных приложениями идентификаторов Bookshelf всегда будет делать "вставку", так как всегда думает, что модель "новая". Поэтому вам нужно заставить этот метод "обновить"... это просто добавляет к путанице в Книжной полке.
В любом случае, как мне это сделать правильно? Как сделать эту работу вставки и обновления?
Что еще важнее, где это документировано? Я добросовестно полагаю, что он где-то задокументирован, и я просто не могу увидеть лес для деревьев прямо сейчас, поэтому я действительно ценю какое-то направление, чтобы следовать в документах даже больше, чем прямой ответ, потому что мне нужно чтобы понять это. Я потратил много времени на Книжную полку вместо фактической разработки, настолько, что мне почти жаль, что я просто не застрял бы направить SQL-запросы с самого начала.