Добавить свойство в объект, возвращаемое Sequelize FindOne
Я пытаюсь добавить свойство к экземпляру sequelize, прежде чем передать его клиенту.
router.get('/cats/1', function (req, res) {
Cat.findOne({where: {id: 1}})
.then(function (cat) {
// cat exists and looks like {id: 1}
cat.name = "Lincoln";
// console.log of cat is {id: 1, name: Lincoln}
res.json(cat);
});
});
Клиент видит только {id: 1}
, а не только добавленный ключ.
- Что здесь происходит?
- Какой тип объекта возвращается Sequelize?
- Как добавить новые свойства кошкам и отправить их обратно?
Ответы
Ответ 1
Класс Sequelize Model
(из которых ваши кошки являются экземплярами) имеет метод toJSON()
, который res.json предположительно будет использовать для сериализации ваших кошек. Метод возвращает результат Model#get()
(https://github.com/sequelize/sequelize/blob/95adb78a03c16ebdc1e62e80983d1d6a204eed80/lib/model.js#L3610-L3613), который использует только атрибуты, определенные в модели. Если вы хотите установить имя кота, но не хранить имена в БД, вы можете использовать виртуальный столбец при определении своей модели cat:
sequelize.define('Cat', {
// [other columns here...]
name: Sequelize.VIRTUAL
});
В качестве альтернативы, если вы не хотите добавлять свойства к определению модели:
cat = cat.toJSON(); // actually returns a plain object, not a JSON string
cat.name = 'Macavity';
res.json(cat);
Ответ 2
Следующие работы для sequelize v4.
...
const order = Order.findOne(criteria);
order.setDataValue('additionalProperty', 'some value');
...
Надеюсь это поможет. Было немного поздно, но люди все еще ищут ответы.
Ответ 3
Это не позволит мне прокомментировать правильный ответ выше (fooobar.com/questions/1007988/...), просто хотел добавить вариант использования, где это помогло мне.
У меня есть база данных mysql, которую мы не можем изменить в схеме (должна работать со старой системой и новой системой, пока мы не сможем отказаться от старой системы), но мы добавили в MonogoDB и дополнительные функции, пока не сможем создать систему рефакторинг.
Вышеприведенный ответ о свойстве Virtual помог, потому что я в основном сделал бы заполнитель для информации mongo db (в данном случае - журнал активности объекта) и добавил ее при вызове службы findMyObject.
Например:
const model = sequelize.define('myobj', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
field: 'eventId',
},
name: { type: Sequelize.STRING, allowNull: false },
history: Sequelize.VIRTUAL,
...
}
Затем в MyObjectService вызов findMyObject:
...
const result = yield MyObject.findOne(query);
result.history = yield getMyObjectHistoryArray(id);
return result;
И результирующий JSON выглядит так:
{
"id": 1,
"name": "My Name",
"history": [
{...},
{...},
]
}
Таким образом, мы смогли расширить объект без изменения базы данных, но в бэкэнде все еще есть объект, куда вы можете перейти:
let obj = yield findMyObject(id);
obj.name = "New Name";
return yield obj.save();
Что вы не сможете сделать, если в функции findMyObject вы сделали {raw: true}
или result.get({plain: true})
Ответ 4
Вы можете использовать toJSON(), чтобы преобразовать объект Sequelize в тип JSON, а затем добавить свойства, как мы делаем в js
Пример:
UserModel.findById(req.params.id)
.then(function (userIns) {
// here userIns is Sequelize Object
// and data is Json Object
let data = userIns.toJSON();
data['displayName'] = 'John';
})