如何对 MongoDB 聚合管道使用多个运算符?
How to use multiple operators to a MongoDB aggregation pipeline?
我有一个包含此架构中的文档的集合(是的,我知道这是 无架构的世界 ):
{
name: "Real Colicos",
fee: 123,
creator: {},
participants: [{},{}]
}
所以,我需要一个 查询,我可以在其中获得按参与者计数 排序的第一个组。当然,我可以有一个 participantsCount 属性并在更新时使用 $inc
增加它,但我觉得这是一种幼稚的方法。这是聚合还是 map reduce 领域?
编辑。解决方案是使用 aggregate
:
来自 docs 我可以接受这个:
db.groups.aggregate(
[
{
$project: {
name: 1,
participantsCount: {$size: "$participants"}
}
}
])
这有效。现在我想知道,如何对搜索进行分页,按 participantsCount 排序并仅包含一些文档属性?
我试过:
db.groups.aggregate(
[
{
$project: {
name: 1,
participantsCount: {$size: "$participants"}
},
$skip: 10,
$limit: 5,
$sort: {participantsCount: -1},
$match: {isPrivate: false}
}
],
function (err, results) {
console.log(results);
}
);
但抛出 undefined
作为结果。
还有:
db.groups.aggregate(
[
{
$project: {
name: 1,
participantsCount: {$size: "$participants"}
},
{$skip: 10},
{$limit: 5},
{$sort: {participantsCount: -1}},
{$match: {isPrivate: false}}
}
],
function (err, results) {
console.log(results);
}
);
抛出一个空数组。
甚至:
db.groups.aggregate(
[
{$project: {name: 1, isPrivate: 1, participantsCount: {$size: "$participants"}}},
{$match: {isPrivate: false}},
{$skip: 10},
{$limit: 5},
{$sort: {participantsCount: -1}}
],
function (err, results) {
console.log(results);
}
);
这也会抛出一个空数组。
我可以看到两个紧迫的问题:
- 阶段未正确流水线化。它们目前都是一个对象的一部分,但应该作为单独的文档出现在数组中:
db.groups.aggregate(
[
{$project: {name: 1, participantsCount: {$size: "$participants"}}},
{$skip: 10},
{$limit: 5},
{$sort: {participantsCount: -1}},
{$match: {isPrivate: false}}
],
function (err, results) {
console.log(results);
}
);
- 没有任何内容会通过最后一个 $match,因为 isPrivate 在第一个 $project 中被剥离。您可能需要在 $project.
中包含该字段
答案:聚合可以是管道。
来自文档:
The aggregation pipeline is a framework for data aggregation modeled on the concept of data processing pipelines. Documents enter a multi-stage pipeline that transforms the documents into an aggregated results.
If your aggregation operation requires only a subset of the data in a collection, use the $match, $limit, and $skip stages to restrict the documents that enter at the beginning of the pipeline.
所以这意味着处理管道以获得想要的结果。正如第二段所暗示的,管道处理顺序很重要。
它应该是这样的:
collection.aggregate(
[
{$match: {isPrivate: false}},
{$skip: 0},
{$limit: 2},
{$project: {name: 1, participantsCount: {$size: "$participants"}}},
{$sort: {participantsCount: -1}}
]
);
我有一个包含此架构中的文档的集合(是的,我知道这是 无架构的世界 ):
{
name: "Real Colicos",
fee: 123,
creator: {},
participants: [{},{}]
}
所以,我需要一个 查询,我可以在其中获得按参与者计数 排序的第一个组。当然,我可以有一个 participantsCount 属性并在更新时使用 $inc
增加它,但我觉得这是一种幼稚的方法。这是聚合还是 map reduce 领域?
编辑。解决方案是使用 aggregate
:
来自 docs 我可以接受这个:
db.groups.aggregate(
[
{
$project: {
name: 1,
participantsCount: {$size: "$participants"}
}
}
])
这有效。现在我想知道,如何对搜索进行分页,按 participantsCount 排序并仅包含一些文档属性?
我试过:
db.groups.aggregate(
[
{
$project: {
name: 1,
participantsCount: {$size: "$participants"}
},
$skip: 10,
$limit: 5,
$sort: {participantsCount: -1},
$match: {isPrivate: false}
}
],
function (err, results) {
console.log(results);
}
);
但抛出 undefined
作为结果。
还有:
db.groups.aggregate(
[
{
$project: {
name: 1,
participantsCount: {$size: "$participants"}
},
{$skip: 10},
{$limit: 5},
{$sort: {participantsCount: -1}},
{$match: {isPrivate: false}}
}
],
function (err, results) {
console.log(results);
}
);
抛出一个空数组。
甚至:
db.groups.aggregate(
[
{$project: {name: 1, isPrivate: 1, participantsCount: {$size: "$participants"}}},
{$match: {isPrivate: false}},
{$skip: 10},
{$limit: 5},
{$sort: {participantsCount: -1}}
],
function (err, results) {
console.log(results);
}
);
这也会抛出一个空数组。
我可以看到两个紧迫的问题:
- 阶段未正确流水线化。它们目前都是一个对象的一部分,但应该作为单独的文档出现在数组中:
db.groups.aggregate(
[
{$project: {name: 1, participantsCount: {$size: "$participants"}}},
{$skip: 10},
{$limit: 5},
{$sort: {participantsCount: -1}},
{$match: {isPrivate: false}}
],
function (err, results) {
console.log(results);
}
);
- 没有任何内容会通过最后一个 $match,因为 isPrivate 在第一个 $project 中被剥离。您可能需要在 $project. 中包含该字段
答案:聚合可以是管道。
来自文档:
The aggregation pipeline is a framework for data aggregation modeled on the concept of data processing pipelines. Documents enter a multi-stage pipeline that transforms the documents into an aggregated results.
If your aggregation operation requires only a subset of the data in a collection, use the $match, $limit, and $skip stages to restrict the documents that enter at the beginning of the pipeline.
所以这意味着处理管道以获得想要的结果。正如第二段所暗示的,管道处理顺序很重要。
它应该是这样的:
collection.aggregate(
[
{$match: {isPrivate: false}},
{$skip: 0},
{$limit: 2},
{$project: {name: 1, participantsCount: {$size: "$participants"}}},
{$sort: {participantsCount: -1}}
]
);