[英]Increment ($inc) update not working with upsert (MongoDB, NodeJS)
[英]How to increment property in MongoDB collection using $inc
我有一个具有属性views
的文章列表,每次用户单击文章标题时,我都想在数据库中增加该属性。 目前,当我这样做时没有任何反应。 为什么它不起作用,我如何在每次点击时增加该属性? 这是我的 React 部分:
const incrementViews = (id) => {
var item = posts.find(x => x._id === id);
item.views += 1;
}
<div className="post-title">
<Link to={`/post/${post._id}`}>
<h2><a href="#" onClick={() => incrementViews(post._id)}>{post.title}</a>
</h2>
</Link>
</div>
和我的 server.js:
// Requiring the dependencies
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
require('dotenv').config();
const mongoose = require('mongoose');
const PORT = process.env.PORT || 3001;
const BASE_URL = process.env.REACT_APP_BASE_URL;
console.log(BASE_URL)
const itemRoutes = express.Router();
let Comment = require('./comment.model');
app.use(cors());
app.use(bodyParser.json());
mongoose.connect(BASE_URL, { useNewUrlParser: true })
const connection = mongoose.connection;
connection.once('open', function () {
console.log('Connection to MongoDB established succesfully!');
});
let collection = connection.collection("posts_with_tags_test");
collection.createIndex(
{
postContent: 'text',
title: 'text'
}
);
// Serve static assets
if (process.env.NODE_ENV === 'production') {
app.use(express.static('build'));
}
itemRoutes.route('/').get(async (req, res) => {
let collection = connection.collection("posts_with_tags_test");
let response = await collection.find({})
.toArray();
res.send(response);
});
itemRoutes.route('/search').post(async (req, res) => {
let result = await connection.collection("posts_with_tags_test").find({
$text: {
$search: req.body.searchString
}
}).toArray();
res.send(result);
});
itemRoutes.route("increment/:id"").post(async (req, res) => {
const { id } = req.params;
collection.updateOne({ _id: id }, { $inc: { views: 1 } });
return res.status(200).json({ msg: "OK" });
});
itemRoutes.route('/comments').get(async (req, res) => {
let collection = connection.collection("comments");
let response = await collection.find({})
.toArray();
res.send(response);
});
itemRoutes.route('/comments')
.post((req, res) => {
res.setHeader('Content-Type', 'application/json');
let comment = new Comment(req.body);
comment.save()
.then(comment => {
res.status(200).json({ comment })
})
.catch(err => {
res.status(400).send('failed')
})
});
app.use('/', itemRoutes);
app.use('/comments', itemRoutes);
app.use('/search', itemRoutes);
app.use('/increment', itemRoutes);
app.listen(PORT, function () {
console.log('Server is running on' + ' ' + PORT);
})
我认为前端和后端分别有两个问题。
前端
您应该将post
变量用作 state 变量,以便在对post
进行更改时重新渲染 then 组件。
后端
在您的代码中增加view
没有问题。
在这里,您需要返回成功状态。
function incrementViews
仅增加前端的视图,从不向 API 发送任何数据。一种使其工作的方法如下:
server.js
itemRoutes.route("/increment/:id").post(async (req, res) => {
const { id } = req.params;
collection.updateOne({ _id: id }, { $inc: { views: 1 } });
return res.status(200).json({ msg: "OK" });
});
const incrementViews = (id) => {
// Assuming your API server is running on port 5000.
fetch(`http://localhost:5000/increment/${id}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
})
.then((res) => res.json())
.then(console.log)
.catch(console.error);
};
更新
你得到 404 的原因是路由参数中缺少冒号:
。
// Notice the :id, colon is important.
itemRoutes.route("/increment/:id").post(async (req, res) => {
const { id } = req.params;
// ...
});
这是在 Glitch 上复制的演示。 删除了数据库逻辑,只添加了一条响应消息。 我使用 Postman 测试了演示,它工作正常。
在对https://adaptive-sassy-legal.glitch.me/increment/123
的 POST 请求中,应返回如下所示的响应。
{
msg: "itemsRoute increment.",
id: "123"
}
更新 2
我在之前的更新中忘记提及的另一件事是更新中间件。
// Use only `/increment` instead of `increment/:id`.
app.use("/increment", itemRoutes);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.