如何使用knex和ON CONFLICT子句将promise链接起来



我有两个表"temp_users"one_answers"ratings">

TABLE 1 (temp_users)
temp_user_id(pkey) | ip_address | total_ratings
-----------------------------------------
|            |              
|            |              
|            |              

TABLE 2 (ratings)
rating_id | rating | product_id | temp_user_id(fkey)
----------------------------------------------------
|        |            |              
|        |            |              
|        |            |                      

我正在努力做到,一旦用户试图对产品进行评分,就会用他们的ip地址创建一个临时用户。

一旦将ip_address插入表中,就会生成user_temp_id,除非表中已经存在ip地址(我使用postgres ON CONFLICT来实现这一点,如下面的代码所示(。

一旦临时用户对产品进行评分,他们就不能再对其进行评分。换句话说,一个temp_user只能对同一个产品进行一次评分。

当我使用"ON CONFLICT"或"WHERE NOT EXIST"子句时,我的代码无法实现这一点,当我允许插入相同ip地址的副本时,代码可以正常工作。我的代码如下:

app.post("/rating", (req, res) => {
const ip =                              // <==== this is just to get the ip address. works fine.
(req.headers["x-forwarded-for"] || "").split(",").pop().trim() ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress; 
const { rating, product_id } = req.body;
knex
.raw(                   // <=== inserts ip and temp_user_id. returns temp_user_id
`INSERT INTO temp_users(ip_address)    
VALUES ('${ip}')
ON CONFLICT (ip_address)
DO UPDATE SET total_ratings = EXCLUDED.total_ratings
RETURNING temp_user_id`
)
.then((results) => {        // <=== counts the ratings to check later if user rated before
return knex("ratings")
.count("*")
.as("total")
.where({
product_id: product_id,
temp_user_id: results[0].temp_user_id,
})
.then((data) => {         // <=== check if user rated before, if not insert new user
if (data[0].count > 0) {
return res.status(400).json("user already rated");
} else {
return knex("ratings")
.returning("*")
.insert({
rating: rating,
product_id: product_id,
temp_user_id: results[0].temp_user_id,
})
.then((response) => res.json(response))
.catch((err) => err);
}
});
})
.then((response) => res.json(response))
.catch((err) => err);
});

如果我使用下面的代码,代码会非常完美,但它插入了多个具有不同temp_user_id的ip地址,这不是我想要的。

所以通过切换这部分代码。。。

knex
.raw(
`INSERT INTO temp_users(ip_address)
VALUES ('::5')
ON CONFLICT (ip_address)
DO UPDATE SET total_ratings = EXCLUDED.total_ratings
RETURNING temp_user_id`
)

对此。。。

knex("temp_users")
.insert({
ip_address: ip,
})
.returning("*")

我把承诺串起来是不是做错了什么?我怎样才能让它工作?如有任何帮助,我们将不胜感激。

我已经找到了答案。第一个promise(我使用"ON CONFLICT"子句的那个(不仅像我期望的那样返回一个带有temp_user_id的对象数组,而且它返回了一个包含许多属性的对象,其中包括一个名为"rows"的属性,其中包含返回的temp_user_id值。

所以我只需要将代码更改为results.rows[0].temp_user_id,而不是results[0].ttemp_user_id.

最新更新