node.js - 猫鼬聚合不返回最新文档
问题描述
我有一个返回文档的聚合,但我需要它返回一个文档,该文档是集合 messageTrackingId 中的最新文档。在该字段中具有最新值的那个creationDate
我有一种方法可以完成此操作,但我不断收到不是最新的返回文档,我不知道为什么。目的是向用户显示该用户与另一个用户之间发送的最后一条消息的时间戳,无论是谁发送的。感谢任何帮助。
app.get("/api/messages", (req, res, next) => {
query = {};
inbox = false;
messageId = false;
console.log(req.query.recipientId);
if (req.query.recipientId) {
query = { recipientId: req.query.recipientId };
inbox = true;
Messages.aggregate([
{
$match: {
$or: [
{ recipientId: req.query.recipientId },
{ creator: mongoose.Types.ObjectId(req.query.recipientId) }
]
}
},
{
$addFields: {
conversant: {
$cond: [
{ $ne: ["$recipientId", req.query.recipientId] },
"$recipientId",
"$creator"
]
}
}
},
{
$sort: { creationDate: 1 }
},
{
$group: {
_id: "$conversant",
message: { $last: "$message" },
recipientId: { $last: "$recipientId" },
creator: { $last: "$creator" },
messageTrackingId: { $last: "$messageTrackingId" },
recipient: { $last: "$recipient" },
creationDate: { $last: "$creationDate" }
}
},
{
$lookup: {
from: "users",
let: { creator: "$creator" },
pipeline: [
{ $match: { $expr: { $eq: ["$_id", "$$creator"] } } },
{ $project: { instagramName: 1 } }
],
as: "creatorName"
}
}
]).then(documents => {
if (inbox === true) {
res.status(200).json({
message: "User's Inbox Retrieved!",
posts: documents
});
}
});
我清理了消息表并来回发送了3条消息进行演示。当我重新加载页面时,我只收到 JSON 响应中的 2 个文档,而不是最新的一个。在收到的 2 个中,它们似乎都不是最新的。我不确定为什么它不返回一个。请参阅下面的页面加载输出。
留言:
/* 1 */
{
"_id" : "5e16463be5fcba1d2c56ebb7",
"creator" : "5e0a1d41f86e1e4234fc1a77",
"recipient" : "andy",
"recipientId" : "5df0014e25ee451beccf588a",
"message" : "First message",
"messageTrackingId" : "17c4fc99-d92f-46ef-9bae-1408f415287a",
"creatorName" : "buyer1",
"creationDate" : ISODate("2020-01-08T21:14:35.104Z"),
"__v" : 0.0
}
/* 2 */
{
"_id" : "5e16464de5fcba1d2c56ebb9",
"creator" : "5df0014e25ee451beccf588a",
"recipient" : "buyer1",
"recipientId" : "5e0a1d41f86e1e4234fc1a77",
"message" : "Second Message",
"messageTrackingId" : "17c4fc99-d92f-46ef-9bae-1408f415287a",
"creatorName" : "andy",
"creationDate" : ISODate("2020-01-08T21:14:53.618Z"),
"__v" : 0.0
}
/* 3 */
{
"_id" : "5e16465ce5fcba1d2c56ebbb",
"creator" : "5e0a1d41f86e1e4234fc1a77",
"recipient" : "andy",
"recipientId" : "5df0014e25ee451beccf588a",
"message" : "Third Message",
"messageTrackingId" : "17c4fc99-d92f-46ef-9bae-1408f415287a",
"creatorName" : "buyer1",
"creationDate" : ISODate("2020-01-08T21:15:08.500Z"),
"__v" : 0.0
}
用户:
/* 1 */
{
"_id" : "5df00d08c713f722909c99c1",
"email" : "joe@gmail.com",
"password" : "$2b$10$5eWhwL4RNT8TyQRCC191J.myYBwFcJ8hCARqGfofYWUmRaq6jJFQm",
"instagramName" : "joe",
"over21" : "Yes",
"role" : "Artist",
"fullName" : "testdsfdfsfs",
"address1" : "adfsdf",
"address2" : "dssdf",
"city" : "sdfsdfsdf",
"state" : "dsffsdsd",
"zip" : "dsdfsdf",
"passwordCreated" : ISODate("2020-01-07T23:46:57.861Z"),
"__v" : 0
}
/* 2 */
{
"_id" : "5df0014e25ee451beccf588a",
"email" : "andy@gmail.com",
"password" : "$2b$10$fNHmIoDb4mX6x.YeMLXHbu2yIaeW6HVQvNpZR8Nt/a4xVFkhxM1Ey",
"instagramName" : "andy",
"over21" : "Yes",
"role" : "Artist",
"fullName" : "dsfdsfdfdsf",
"address1" : "111",
"address2" : "111",
"city" : "atlanta",
"state" : "ga",
"zip" : "33222",
"passwordCreated" : ISODate("2019-12-19T15:29:46.528Z"),
"__v" : 0
}
所需输出(返回每个用户的最后一条消息):
/* 1 */
{
"_id" : {
"conversant" : "5df0014e25ee451beccf588a",
"recipient" : "andy"
},
"message" : "Third Message",
"recipientId" : "5df0014e25ee451beccf588a",
"creator" : "5e0a1d41f86e1e4234fc1a77",
"messageTrackingId" : "17c4fc99-d92f-46ef-9bae-1408f415287a",
"recipient" : "andy",
"creationDate" : ISODate("2020-01-08T21:15:08.500Z"),
"creatorName" : [
{
"_id" : "5df0014e25ee451beccf588a",
"instagramName" : "andy"
}
]
}
/* 2 */
{
"_id" : {
"conversant" : "5df0014e25ee451beccf588a",
"recipient" : "buyer1"
},
"message" : "Second Message",
"recipientId" : "5e0a1d41f86e1e4234fc1a77",
"creator" : "5df0014e25ee451beccf588a",
"messageTrackingId" : "17c4fc99-d92f-46ef-9bae-1408f415287a",
"recipient" : "buyer1",
"creationDate" : ISODate("2020-01-08T21:14:53.618Z"),
"creatorName" : [
{
"_id" : "5df0014e25ee451beccf588a",
"instagramName" : "andy"
}
]
}
解决方案
改变必须是
1)如果我在这个阶段理解正确,你想recipientId
对一个字段进行分组(因为你不能对单个值的两个字段进行分组)所以你正在创建一个名为的新字段conversant
,所以它必须是$eq
或者你需要交换recipientId
& creator
& 也必须是$toString
:
{
$addFields: {
conversant: {
$cond: [
{ $eq: ["$recipientId", req.query.recipientId] },
"$recipientId",
{$toString : "$creator"}
]
}
}
}
2)您不需要这个$sort
阶段,因为所有最新添加的集合都将在最后添加(期望creationDate
一旦创建但从未更新):
// Not useful
{
$sort: { creationDate: 1 }
}
此外,您还需要_id: { conversant: "$conversant", recipient: '$recipient' }
根据基于user
. 在$lookup
改变这个let: { conversant: "$_id.conversant" }
。
尝试这个 :
Messages.aggregate([
{
$match: {
$or: [
{ recipientId: req.query.recipientId },
{ creator: mongoose.Types.ObjectId(req.query.recipientId) }
]
}
},
{
$addFields: {
conversant: {
$cond: [
{ $eq: ["$recipientId", req.query.recipientId] },
"$recipientId",
{ $toString: "$creator" }
]
}
}
},
{
$group: {
_id: { conversant: "$conversant", recipient: '$recipient' },
message: { $last: "$message" },
recipientId: { $last: "$recipientId" },
creator: { $last: "$creator" },
messageTrackingId: { $last: "$messageTrackingId" },
recipient: { $last: "$recipient" },
creationDate: { $last: "$creationDate" }
}
},
{
$lookup: {
from: "users",
let: { conversant: "$_id.conversant" },
pipeline: [
{ $match: { $expr: { $eq: ["$_id", "$$conversant"] } } },
{ $project: { instagramName: 1 } }
],
as: "creatorName"
}
},
// this is optional only if you wanted to return latest document irrespective of user.
{ $sort: { creationDate: -1 } }
])
推荐阅读
- spring - Spring Boot MongoDB 云集群
- django - Nginx 在用于容器的 Azure Web App 的 Dockered Django 应用中找不到静态文件
- python - Python - 读取文本并写入 csv。将空列替换为默认的“N/A”值
- java - 等价于 java 中的 std::iota
- json - Flutter/Dart setState 不刷新文本小部件中的文本
- react-hooks - 如何在 apollo 客户端中获取值
- node.js - Node js Mysql Ininter加入多个数据库表
- javascript - 将等待值导出为 ESM 模块
- javascript - 持续监听智能合约事件
- javascript - UseState 在初始加载时重新渲染过多