我有一个“聊天”猫鼬Schema
,它具有以下属性:
const schema = mongoose.Schema({
...
recipient: {
type: mongoose.Types.ObjectId,
required: true,
ref: 'User',
},
sender: {
type: mongoose.Types.ObjectId,
required: true,
ref: 'User',
},
content: {
type: String,
},
...
}, {
timestamps: true,
});
通常,我想获取用户每次掩护的最后一条消息。这意味着我需要提供一个用户ID(可以存储在sender
或recipient
字段中)并获取用户与每个用户共享的最后一条消息(由createdAt
表示)其他用户。
示例:
假设我有以下document
:
[
{
recipient: "One",
sender: "Two",
createdAt: ISODate("2014-01-01T08:00:00Z"),
},
{
recipient: "One",
sender: "Three",
createdAt: ISODate("2014-02-15T08:00:00Z")
},
{
recipient: "Two",
sender: "One",
createdAt: ISODate("2014-02-16T12:05:10Z")
}
]
以“ One”作为输入-来自Model.find(...)
的期望结果是:
[
{
recipient: "One",
sender: "Three",
createdAt: ISODate("2014-02-15T08:00:00Z")
},
{
recipient: "Two",
sender: "One",
createdAt: ISODate("2014-02-16T12:05:10Z")
}
]
答案 0 :(得分:2)
您可以通过汇总来执行此操作,如下面的查询所示
工作示例-https://mongoplayground.net/p/wEi4Y6IZJ2v
db.collection.aggregate([
{
$sort: {
recipient: 1,
createdAt: 1
}
},
{
$group: {
_id: "$recipient",
createdAt: {
$last: "$createdAt"
}
}
},
{
$project: {
_id: 0,
recipient: "$_id",
createdAt: "$createdAt"
}
}
])
如果要匹配两个字段,则可以使用以下查询
工作示例-https://mongoplayground.net/p/Rk5MxuphLOT
db.collection.aggregate([
{
$match: {
$or: [
{
sender: "One"
},
{
recipient: "One"
}
]
}
},
{
$addFields: {
other: {
$cond: {
if: {
$eq: [
"$recipient",
"One"
]
},
then: "$sender",
else: "$recipient"
}
}
}
},
{
$sort: {
createdAt: 1
}
},
{
$group: {
_id: "$other",
createdAt: {
$last: "$createdAt"
},
recipient: {
$last: "$recipient"
},
sender: {
$last: "$sender"
}
}
},
{
$project: {
_id: 0,
recipient: "$recipient",
sender: "$sender",
createdAt: "$createdAt"
}
}
])
答案 1 :(得分:2)
使用示例数据:
[
{
recipient: "One",
sender: "Two",
createdAt: ISODate("2014-01-01T08:00:00Z"),
content: "Hi Mr. One! - Two"
},
{
recipient: "One",
sender: "Three",
createdAt: ISODate("2014-02-15T08:00:00Z"),
content: "Hello One! - Three"
},
{
recipient: "Two",
sender: "One",
createdAt: ISODate("2014-02-16T12:05:10Z"),
content: "Whats up, Two? - One"
}
]
看看以下汇总:https://mongoplayground.net/p/DTSDWX3aLWe
它...
One
)匹配的用户conversationWith
字段,该字段包含recipient
(如果是向用户One发出的消息 或{{1} },如果它是用户One发送的消息 sender
字段中使用 $ group 将所有消息分组,并以conversationWith
的形式返回最新消息完整的聚合管道:
firstMessage
使用mongoplayground,您可以一个一个地删除聚合步骤,以查看每个步骤的作用。
尝试:
以获得最佳理解。
答案 2 :(得分:0)
如果您想依靠mongodb过滤出重复项,最好不要创建unique index,甚至永远不要重复。
因为似乎您的收件人嵌套在父方案中,所以我将在nodejs中过滤重复项,因为它很难在mongodb查询中解开此问题。 如果您需要使用mongodb,请使用distinct函数或aggregate pipeline,并受this article
的启发