我正在使用passport-bnet
来验证使用battlenet的用户(他们可以拥有多项服务)。我有一个用户对象格式如下:
{
"id": 1,
"name": "Meow",
"battlenet": {
"id": 5,
"tag": "obviously-not-a-real-battletag#1234"
}
}
当我对用户进行身份验证时,我会在响应中获得warnet用户的id。我试图做的是从这个json字段中选择id,如果它不存在则创建它。
passport.use(new Battlenet({/**...*/}, function (accessToken, refreshToken, profile, done) {
database
.select('*')
.where('battlenet->id', '=', profile.id)
.then(user => done(null, user))
.catch(done);
});
然而,我遇到了一些麻烦。如何插入此用户文档以包含一些默认值?基本上,我想在mongo中使用类似于这种修饰符的东西
{
$setOnInsert: { name: profile.tag.replace(/\W/, '') },
$set: { battlenet: profile }
}
如何通过knex和postgres完成?
答案 0 :(得分:0)
我很难理解您的架构以及您希望在以下情况下发生什么相同的查询运行两次。随意更新问题,我可能会给出更完整的答案。
一般来说,对于knex,有关于upsert的讨论已经讨论过
https://github.com/tgriesser/knex/issues/54和https://github.com/tgriesser/knex/issues/1121
讨论得出的结论是,仍然应该使用原始SQL(knex.raw
)fr upsert。
对于问题的SQL部分,我认为关键是您需要为UNIQUE
属性创建battlenet->id
约束。之后,可以执行INSERT
s与JSONB属性中的重复ID冲突。
这样的事情:
CREATE UNIQUE INDEX t_id ON t((json->>'id'));
之后,应该很容易编写upsert,它实际上只是在jsonb_set
函数的帮助下更新了一些JSONB属性。