我在尝试使用MongooseJs在Mongodb中按嵌套数组排序时遇到了一个小问题。
a)一个产品包含任务,每个任务都有子任务。
b)任务有顺序
这是一个示例产品文档:
db.products.find({_id: ObjectId("554a13d4b692088a38f01f3b")})
结果:
{
"_id" : ObjectId("554a13d4b692088a38f01f3b"),
"title" : "product title",
"order" : 3,
"description" : "Description here ",
"status" : "live",
"tasks" : [
{
"title" : "task 1",
"description" : "task 1 desc",
"order" : 10,
"_id" : ObjectId("554a13d4b692088a38f01f3a"),
"status" : "live",
"subTasks" : [
{
"title" : "task 1 sub 1",
"content" : "aaa",
"order" : -2,
"_id" : ObjectId("554a13d4b692088a38f01f5a"),
"status" : "live"
},
{
"title" : "task 1 sub 2",
"content" : "aaa",
"order" : 1,
"_id" : ObjectId("554a13d4b692088a38f01f3a"),
"status" : "live"
},
{
"title" : "task 1 sub 4",
"content" : "aaa",
"order" : 8,
"_id" : ObjectId("554a13d4b692088a38f01f4a"),
"status" : "live"
},
{
"title" : "task 1 sub 3 ",
"content" : "aaa",
"order" : 2,
"_id" : ObjectId("5550d0a61662211332d9a973"),
"status" : "live"
}
]
},
{
"title" : "task 2",
"description" : "task desc 2",
"order" : 1,
"_id" : ObjectId("5550855f9ee2db4e3958d299"),
"status" : "live",
"subTasks" : [
{
"title" : "task 2 sub 1",
"content" : "bbb",
"order" : 1,
"_id" : ObjectId("55508f459ee2db4e3958d29a"),
"status" : "live"
}
]
},
{
"title" : "task 3",
"description" : "task 3 desc",
"order" : 2,
"_id" : ObjectId("5551b844bb343a620f85f323"),
"status" : "live",
"subTasks" : [
{
"title" : "task 3 sub 2",
"content" : "cccc",
"order" : 0,
"_id" : ObjectId("5551b88abb343a620f85f324"),
"status" : "live"
},
{
"title" : "task 3 sub 4",
"content" : "cccc",
"order" : 1,
"_id" : ObjectId("5551b8f1bb343a620f85f325"),
"status" : "hidden"
},
{
"title" : "task 3 sub 3",
"content" : "ccc",
"order" : 2,
"_id" : ObjectId("5551ba40bb343a620f85f327"),
"status" : "hidden"
},
{
"title" : "task 3 sub 1",
"content" : "cccc",
"order" : -1,
"_id" : ObjectId("5551bcb8c31283c051d30b7c"),
"status" : "hidden"
}
]
}
]
}
我正在使用MongoDB聚合管道来订购任务
db.products.aggregate([
{
$project: {
"tasks" : 1
}
},
{
$match: {
_id: ObjectId("554a13d4b692088a38f01f3b")
}
},
{
$unwind: "$tasks"
},
{
$project: {
"tasks": 1,
"subTasks": 1
}
},
{
$unwind: "$tasks.subTasks"
},
{
$sort: {
"tasks.subTasks.order": 1
}
},
{
$sort: {
"tasks.order": 1
}
}
])
结果:
{
"result": [
{
"_id": ObjectId("554a13d4b692088a38f01f3b"),
"tasks": {
"title": "task 2",
"description": "task desc 2",
"order": 1,
"_id": ObjectId("5550855f9ee2db4e3958d299"),
"status": "live",
"subTasks": {
"title": "task 2 sub 1",
"content": "bbb",
"order": 1,
"_id": ObjectId("55508f459ee2db4e3958d29a"),
"status": "live"
}
}
},
{
"_id": ObjectId("554a13d4b692088a38f01f3b"),
"tasks": {
"title": "task 3",
"description": "task 3 desc",
"order": 2,
"_id": ObjectId("5551b844bb343a620f85f323"),
"status": "live",
"subTasks": {
"title": "task 3 sub 1",
"content": "cccc",
"order": -1,
"_id": ObjectId("5551bcb8c31283c051d30b7c"),
"status": "hidden"
}
}
},
{
"_id": ObjectId("554a13d4b692088a38f01f3b"),
"tasks": {
"title": "task 3",
"description": "task 3 desc",
"order": 2,
"_id": ObjectId("5551b844bb343a620f85f323"),
"status": "live",
"subTasks": {
"title": "task 3 sub 2",
"content": "cccc",
"order": 0,
"_id": ObjectId("5551b88abb343a620f85f324"),
"status": "live"
}
}
},
{
"_id": ObjectId("554a13d4b692088a38f01f3b"),
"tasks": {
"title": "task 3",
"description": "task 3 desc",
"order": 2,
"_id": ObjectId("5551b844bb343a620f85f323"),
"status": "live",
"subTasks": {
"title": "task 3 sub 4",
"content": "cccc",
"order": 1,
"_id": ObjectId("5551b8f1bb343a620f85f325"),
"status": "hidden"
}
}
},
{
"_id": ObjectId("554a13d4b692088a38f01f3b"),
"tasks": {
"title": "task 3",
"description": "task 3 desc",
"order": 2,
"_id": ObjectId("5551b844bb343a620f85f323"),
"status": "live",
"subTasks": {
"title": "task 3 sub 3",
"content": "ccc",
"order": 2,
"_id": ObjectId("5551ba40bb343a620f85f327"),
"status": "hidden"
}
}
},
{
"_id": ObjectId("554a13d4b692088a38f01f3b"),
"tasks": {
"title": "task 1",
"description": "task 1 desc",
"order": 10,
"_id": ObjectId("554a13d4b692088a38f01f3a"),
"status": "live",
"subTasks": {
"title": "task 1 sub 1",
"content": "aaa",
"order": -2,
"_id": ObjectId("554a13d4b692088a38f01f5a"),
"status": "live"
}
}
},
{
"_id": ObjectId("554a13d4b692088a38f01f3b"),
"tasks": {
"title": "task 1",
"description": "task 1 desc",
"order": 10,
"_id": ObjectId("554a13d4b692088a38f01f3a"),
"status": "live",
"subTasks": {
"title": "task 1 sub 2",
"content": "aaa",
"order": 1,
"_id": ObjectId("554a13d4b692088a38f01f3a"),
"status": "live"
}
}
},
{
"_id": ObjectId("554a13d4b692088a38f01f3b"),
"tasks": {
"title": "task 1",
"description": "task 1 desc",
"order": 10,
"_id": ObjectId("554a13d4b692088a38f01f3a"),
"status": "live",
"subTasks": {
"title": "task 1 sub 3 ",
"content": "aaa",
"order": 2,
"_id": ObjectId("5550d0a61662211332d9a973"),
"status": "live"
}
}
},
{
"_id": ObjectId("554a13d4b692088a38f01f3b"),
"tasks": {
"title": "task 1",
"description": "task 1 desc",
"order": 10,
"_id": ObjectId("554a13d4b692088a38f01f3a"),
"status": "live",
"subTasks": {
"title": "task 1 sub 4",
"content": "aaa",
"order": 8,
"_id": ObjectId("554a13d4b692088a38f01f4a"),
"status": "live"
}
}
}
],
"ok": 1
}
预期结果:
{
"_id": ObjectId("554a13d4b692088a38f01f3b"),
"title": "product title",
"order": 3,
"description": "Description here ",
"status": "live",
"tasks": [
{
"title": "task 2",
"description": "task desc 2",
"order": 1,
"_id": ObjectId("5550855f9ee2db4e3958d299"),
"status": "live",
"subTasks": [
{
"title": "task 2 sub 1",
"content": "bbb",
"order": 1,
"_id": ObjectId("55508f459ee2db4e3958d29a"),
"status": "live"
}
]
},
{
"title": "task 3",
"description": "task 3 desc",
"order": 2,
"_id": ObjectId("5551b844bb343a620f85f323"),
"status": "live",
"subTasks": [
{
"title": "task 3 sub 1",
"content": "cccc",
"order": -1,
"_id": ObjectId("5551bcb8c31283c051d30b7c"),
"status": "hidden"
},
{
"title": "task 3 sub 2",
"content": "cccc",
"order": 0,
"_id": ObjectId("5551b88abb343a620f85f324"),
"status": "live"
},
{
"title": "task 3 sub 3",
"content": "ccc",
"order": 2,
"_id": ObjectId("5551ba40bb343a620f85f327"),
"status": "hidden"
}{
"title": "task 3 sub 4",
"content": "cccc",
"order": 1,
"_id": ObjectId("5551b8f1bb343a620f85f325"),
"status": "hidden"
}
]
}{
"title": "task 1",
"description": "task 1 desc",
"order": 10,
"_id": ObjectId("554a13d4b692088a38f01f3a"),
"status": "live",
"subTasks": [
{
"title": "task 1 sub 1",
"content": "aaa",
"order": -2,
"_id": ObjectId("554a13d4b692088a38f01f5a"),
"status": "live"
},
{
"title": "task 1 sub 2",
"content": "aaa",
"order": 1,
"_id": ObjectId("554a13d4b692088a38f01f3a"),
"status": "live"
},
{
"title": "task 1 sub 3 ",
"content": "aaa",
"order": 2,
"_id": ObjectId("5550d0a61662211332d9a973"),
"status": "live"
},
{
"title": "task 1 sub 4",
"content": "aaa",
"order": 8,
"_id": ObjectId("554a13d4b692088a38f01f4a"),
"status": "live"
}
]
}
]
我真的很接近了,所有的排序似乎都在工作。我只需要一些帮助来将子任务放回父母体内。非常感谢任何帮助。
谢谢
从聚合管道的一开始,您就犯了一个错误
$project: {
"tasks" : 1
}
从而丢失所有数据。因此,首先您需要进行以下操作:
$project: {
tasks: 1,
doc: {
title: "$title",
order: "$order",
description: "$description",
status: "$status"
}
}
然后像您在问题中所做的那样执行您的$unWind
s:
{$unwind: "$tasks"}, {$unwind: "$tasks.subTasks"}
然后进行排序。您需要使用复合键进行排序,否则tasks.subTasks.order
的排序将不会在您按tasks.order
排序时保持不变。所以:
{$sort: {"tasks.order": -1, "tasks.subTasks.order": 1}}
然后是最难的部分。您需要返回结果,第一步是返回子任务,但首先需要保留任务属性:
$project: {
doc: 1,
task_id: "$tasks._id",
tasks_doc: {
title: "$tasks.title",
description: "$tasks.description",
order: "$tasks.order",
status: "$tasks.status"
},
subTasks: "$tasks.subTasks"
}
...收集子任务:
$group: {
_id: {
_id: "$_id",
task_id: "$task_id",
doc: "$doc",
task_doc: "$tasks_doc"
},
subTasks: {
$push: "$subTasks"
}
}
任务
也是如此。请注意,在$group
ing期间,您还需要投影回task_doc
属性:
$group: {
_id: {
_id: "$_id._id",
doc: "$_id.doc"
},
tasks: {
$push: {
_id: "$_id.task_id",
title: "$_id.task_doc.title",
description: "$_id.task_doc.description",
order: "$_id.task_doc.order",
status: "$_id.task_doc.status"
subTasks: "$subTasks"
}
}
}
然后投射回根doc
属性:
$project: {
_id: "$_id._id",
title: "$_id.doc.title",
description: "$_id.doc.description",
order: "$_id.doc.order",
status: "$_id.doc.status",
tasks: 1
}
基本上就是这样。这是完整的原始聚合管道,因此您可以测试并查看是否获得所需的结果:
[
{$match: {_id: ObjectId("554a13d4b692088a38f01f3b")}},
{$project: {tasks: 1, doc: {title: "$title", order: "$order", description: "$description", status: "$status"}}},
{$unwind: "$tasks"},
{$unwind: "$tasks.subTasks"},
{$sort: {"tasks.order": -1, "tasks.subTasks.order": 1}},
{$project: {doc: 1, task_id: "$tasks._id", tasks_doc: {title: "$tasks.title", description: "$tasks.description", order: "$tasks.order", status: "$tasks.status"}, subTasks: "$tasks.subTasks"}},
{$group: {_id: {_id: "$_id", task_id: "$task_id", doc: "$doc", task_doc: "$tasks_doc"}, subTasks: {$push: "$subTasks"}}},
{$group: {_id: {_id: "$_id._id", doc: "$_id.doc"}, tasks: {$push: {_id: "$_id.task_id", title: "$_id.task_doc.title", description: "$_id.task_doc.description", order: "$_id.task_doc.order", status: "$_id.task_doc.status", subTasks: "$subTasks"}}}},
{$project: {_id: "$_id._id", title: "$_id.doc.title", description: "$_id.doc.description", order: "$_id.doc.order", status: "$_id.doc.status", tasks: 1}}
]
更新
如果数组字段为空或不存在(null
),则对该字段的$unroll
操作将返回空结果。这种情况的解决方案最初是将null
/空字段设置为某个零
值,例如"
看看这个关于如何使用ifNull操作符的答案。请在此处查看“$size”操作符。
处理完此部分后,您需要对结果进行分组,这可以通过使用cond运算符检查
我试图使用MongoDb列出展开嵌套数组。 一个产品包含任务,每个任务可以有零个、一个或多个子任务。 以下是产品文档示例: 结果: 聚合管道在对任务进行排序方面起到了很大的作用 有时任务没有子任务,例如: 当他们没有孩子的时候,还有什么可以帮助他们完成任务吗? 当前聚合: 期望的结果:
本文向大家介绍在MongoDB中执行聚合排序?,包括了在MongoDB中执行聚合排序?的使用技巧和注意事项,需要的朋友参考一下 您可以将method和$sort()运算符一起使用。为了理解这个概念,让我们用文档创建一个集合。使用文档创建集合的查询如下- 在method的帮助下显示集合中的所有文档。查询如下- 以下是输出- 这是对MongoDB聚合排序的查询。 情况1-每当您希望结果按降序排列时。查
给定具有以下文档结构的MongoDB集合: 其中每个文档包含一个子文档数组,我希望将集合转换为以下结构的文档: 其中每个子文档现在是主文档中以子文档中的一个值命名的新字段的值(在该示例中,< code>animal字段的值用于创建新字段的名称,即< code>cat和< code>dog)。 我知道如何使用爪哇脚本片段进行。它很慢。我的问题是:如何使用聚合管道完成此操作?
我有一个具有以下模式的待售项目集合: 我继承了一个聚合查询,它返回匹配类别的项目,按商家分组,组按组中的最大评级排序: 在此之后,代码继续按评级对每组中的项目进行排序,并删除除每组中排名前2位之外的所有项目。 作为聚合函数的一部分,是否可以在组内执行此排序和限制,以便聚合只返回每组中评级最高的两个项目?
设想一个集合,该集合在聚合的$match操作符上返回具有此结构的文档数组 所以基本上每个返回的文档都共享一个片段(这就是我将如何对它们进行分组),但是每个文档都有一个子文档数组,每个子文档都有不同的_id。 因此,当我使用{slug:“a”}执行$match聚合时,它返回一个数组
在elasticsearch中,是否有方法使用自定义分数对聚合桶进行排序/排序? 我正在按客户姓名进行扣球。每个客户都有多个订单,其中有一个交货日期字段(DeliveDate)。我想根据与当前日期的距离(接近程度)对桶进行排序。 例如,对交货日期更接近今天日期的客户名进行排序。 非常感谢。