如何通过许多$projects来改善此聚合
How to improve this aggregate with many $projects
我创建了一个聚合函数,我觉得它很长而且不干。我想知道有什么方法可以改进它。
我的Thread
模型有一个名为 revisions
的子文档。该函数尝试获取具有status
的最新版本 APPROVED
.
这是完整模型。
{
"_id": ObjectId("56dc750769faa2393a8eb656"),
"slug": "my-thread",
"title": "my-thread",
"created": 1457249482555.0,
"user": ObjectId("56d70a491128bb612c6c9220"),
"revisions": [
{
"body": "This is the body!",
"status": "APPROVED",
"_id": ObjectId("56dc750769faa2393a8eb657"),
"comments": [
],
"title": "my-thread"
}
]
}
这是我想要改进的聚合函数。
Thread.aggregate([
{ $match: {
slug: thread
} },
{ $project: {
user: '$user',
created: '$created',
slug: '$slug',
revisions: {
$filter: {
input: '$revisions',
as: 'revision',
cond: { $eq: [ '$$revision.status', 'APPROVED' ] }
}
}
} },
{ $sort: { 'revisions.created': -1 } },
{ $project: {
user: '$user',
created: '$created',
slug: '$slug',
revisions: { $slice: ["$revisions", 0, 1] }
} },
{ $unwind: '$revisions'},
{ $project: {
body: '$revisions.body',
title: '$revisions.title',
user: '$user',
slug: '$slug',
created: '$created'
}}
])
好吧,
你真的不能,因为中间有$sort
和$unwind
阶段是故意的。这基本上也是"错误的",因为$sort
不能对数组重新排序,直到您先$unwind
它。
然后最好改用$group
和$first
,只从每个文档中的排序中获取第一个元素:
Thread.aggregate([
{ "$match": {
"slug": thread
} },
{ "$project": {
"user": 1,
"created": 1,
"slug": 1,
"revisions": {
"$filter": {
"input": "$revisions",
"as": "revision",
"cond": { "$eq": [ "$$revision.status", "APPROVED" ] }
}
}
} },
// Cannot sort until you $unwind
{ "$unwind": "$revisions" },
// Now that will sort the elements
{ "$sort": { "_id": 1, "revisions.created": -1 } },
// And just grab the $first boundary for everything
{ "$group": {
"_id": "$_id",
"body": { "$first": "$revisions.body" },
"title": { "$first": "$revisions.title" },
"user": { "$first": "$user" },
"slug": { "$first": "$slug" },
"created": { "$first": "$created" }
}}
])
您总是可以使用$push
来改革数组,然后应用$arrayElemAt
而不是$slice
来仅生成单个元素,但是考虑到首先在$group
之后还需要另一个$project
,这有点浮夸。
因此,即使有"一些"操作您可以在不使用$unwind
的情况下执行,不幸的是,"排序"从$filter
等函数生成的数组目前无法完成,直到您先$unwind
数组。
如果您不需要""revisions.created"
上的$sort
(示例文档中明显缺少),那么您可以改用普通投影:
Thread.find(
{ "slug": slug, "revisions.status": "APPROVED" },
{ "revisions.$": 1 },
)
只有在对数组元素进行排序时,您才需要其他任何东西,因为$
位置运算符无论如何都会返回第一个匹配的元素。
相关文章:
- 创建一个类似链接的按钮,并通过Javascript函数打开一个新的弹出窗口
- 无法在通过jQuery的ajax加载的页面中执行javascript
- 如何通过ajax刷新JSF填充的javascript变量
- 通过javascript重定向html传递php变量
- 通过Magento的网络服务检索运费
- 无法通过数组映射绑定
- 通过单击表单中的按钮,在代码生成中使用javascript生成字母数字代码
- 通过js在新选项卡中有条件地打开url
- 如何使用jquery处理php循环通过元素
- 通过Ajax将JavaScript函数传递给PHP文件
- jquery动画可以通过编程链接吗
- 通过在Dojo mobile ViewController.openExternalView中动态更改打开同一外部视图的
- 如何通过数组更新角度子范围
- 如何通过php页面将数据库值检索到jquery自动完成框中
- 通过找到一种删除许多 if 语句的方法来简化代码
- 通过jQuery一键隐藏/显示许多元素
- 如何通过许多$projects来改善此聚合
- 如何通过jquery单独管理许多setInterval函数
- 通过冒泡处理许多元素的点击事件
- 当通过websocket发送时,JSON将Float32Array缓冲区的大小增加了许多倍