问题描述
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地址创建一个temp_user。
将ip_address插入表中后,将生成一个user_temp_id,除非该IP地址已存在于表中(我正在使用postgres ON CONFLICT完成此操作,如下面的代码所示)。
一旦temp_user对产品进行评分,他们将无法再次对其进行评分。换句话说,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,})
.then((response) => res.json(response))
.catch((err) => err);
}
});
})
.then((response) => res.json(response))
.catch((err) => err);
});
如果我在下面使用此代码,代码可以完美地工作,但是它将插入具有不同temp_user_ids的多个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("*")
我在兑现承诺方面做错了什么吗?我该如何运作? 任何帮助将不胜感激。
解决方法
我已经找到答案了。第一个承诺(我在其中使用了“ ON CONFLICT”子句的那个)不只是像我期望的那样返回带有temp_user_id的对象数组,而是返回了一个包含许多属性的对象,其中包括名为“ rows”的属性“,其中包含返回的temp_user_id值。
所以我只需要将代码更改为results.rows [0] .temp_user_id,而不是results [0] .temp_user_id。