Mongoose,在子文档数组上应用`.aggregate()`,并以最少的查询次数获得文档其他字段的结果
Posted
技术标签:
【中文标题】Mongoose,在子文档数组上应用`.aggregate()`,并以最少的查询次数获得文档其他字段的结果【英文标题】:Mongoose, apply `.aggregate()` on array of subdocuments and get the result with other fields of document in least number of queries 【发布时间】:2020-11-08 08:27:46 【问题描述】:这是我的猫鼬模型:
const postSchema = new Schema(
user:
type: Schema.Types.ObjectId,
ref: 'User',
required: true
,
caption:
type: String
,
action:
type: [
actionName:
type: String,
required: true
,
user:
type: Schema.Types.ObjectId,
ref: 'User'
],
default: []
,
shares: [
type: Schema.Types.ObjectId,
ref: 'User'
];
);
我想要的只是使用或不使用 .aggregate()
的 mongodb 查询来获取 user
和 caption
字段,而不是 action
和 shares
我想要他们对特定的计数文件。
示例文档
_id: "fgsergehegoieofgesfglesfg",
user: "dfjksjdnfkjsdfkjsdklfjglkbj",
caption: "This is the post caption",
action: [
actionName: 'e1', user: "sdfasdsdfasdfdsdfac951e5c"
,
actionName: 'e1', user: "asdfmadfadfee103c9c951e5d"
,
actionName: 'e2', user: "op34937cdbae0cd4160bbec"
,
actionName: 'e2', user: "2543ebbasdfd1750690b5b01c"
,
actionName: 'e3', user: "asdfcfebdb5dd1750690b5b01d"
,
],
shares: ["ewrebdb5ddadsf5069sadf1d", "asdfsdfbb85dd1750690b5b01c", "fasec92dsfasde103c9c95df5d"]
;
查询后的期望输出:
_id: "fgsergehegoieofgesfglesfg",
user: 'dfjksjdnfkjsdfkjsdklfjglkbj',
caption: 'This is the post caption',
actionCount: [ count: 1, actionName: 'e3' ,
count: 2, actionName: 'e2' ,
count: 2, actionName: 'e1' ],
shareCount: 3
我可以使用.aggregate()
得到以下结果:
查询:
let data = await Test.aggregate([
$match: _id: mongoose.Types.ObjectId("fgsergehegoieofgesfglesfg") ,
$unwind: "$action" ,
$group:
_id: "$action.actionName",
count: $sum: 1
,
$project:
_id: 0,
actionName: "$_id",
count: 1
]);
结果:
[
count: 1, actionName: 'e3' ,
count: 2, actionName: 'e2' ,
count: 2, actionName: 'e1'
]
我只是想把这个放在原始文档中并得到结果。此外,对 share
字段执行相同操作。如果这可以在单个查询中完成会更好。我曾尝试使用$replaceRoot
和$mergeObjects
,但不知道如何正确使用它们。我对 mongodb 和 mongoose 很陌生。
请帮忙。谢谢。
【问题讨论】:
【参考方案1】:由于您正在聚合一个嵌套数组,您需要运行 $group
twice 和 $first
可用于保留原始文档的字段值:
await Test.aggregate([
$match: _id: mongoose.Types.ObjectId("fgsergehegoieofgesfglesfg") ,
$unwind: "$action" ,
$group:
_id: _id: "$_id", actionName: "$action.actionName" ,
user: $first: "$user" ,
caption: $first: "$caption" ,
count: $sum: 1 ,
shareCount: $first: $size: "$shares"
,
$group:
_id: "$_id._id",
user: $first: "$user" ,
caption: $first: "$caption" ,
shareCount: $first: "$shareCount" ,
actionCount:
$push:
actionName: "$_id.actionName",
count: "$count"
])
Mongo Playground
【讨论】:
非常感谢。这正是我所需要的。但我希望在有 1000 次操作的情况下使用多个$group
不会过多地增加查询延迟。你能推荐学习 mongodb 的最佳方法吗?
@NeetigyaChahar 文档绝对是学习 MongoDB 的最佳途径以上是关于Mongoose,在子文档数组上应用`.aggregate()`,并以最少的查询次数获得文档其他字段的结果的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB/Mongoose 一对多,在子节点中引用父节点 - 分组并加入