如何使用 knex 和 ON CONFLICT 子句链接承诺?
how to chain promises using knex with the ON CONFLICT clause?
我有两个 tables 'temp_users' 和 '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)
----------------------------------------------------
| | |
| | |
| | |
我正在努力做到这一点,以便一旦用户尝试对产品进行评分,就会创建一个 temp_user 以及他们的 IP 地址。
一旦 ip_address 插入 table 就会生成 user_temp_id 除非 IP 地址已经存在于 table 中(我正在使用 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,
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' 子句的承诺不只是 return 具有 temp_user_id 的对象数组,就像我预期的那样,而是 return编辑了一个包含许多属性的对象,其中包括一个名为“行”的 属性,其中包含 returned temp_user_id 值。
所以我只需要将我的代码更改为 results.rows[0].temp_user_id 而不是 results[0].temp_user_id.
我有两个 tables 'temp_users' 和 '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)
----------------------------------------------------
| | |
| | |
| | |
我正在努力做到这一点,以便一旦用户尝试对产品进行评分,就会创建一个 temp_user 以及他们的 IP 地址。
一旦 ip_address 插入 table 就会生成 user_temp_id 除非 IP 地址已经存在于 table 中(我正在使用 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,
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' 子句的承诺不只是 return 具有 temp_user_id 的对象数组,就像我预期的那样,而是 return编辑了一个包含许多属性的对象,其中包括一个名为“行”的 属性,其中包含 returned temp_user_id 值。
所以我只需要将我的代码更改为 results.rows[0].temp_user_id 而不是 results[0].temp_user_id.