mongodb - mongodb group by where 字段不等于 max
问题描述
我想获取所有(按 2 个字段分组)不等于其最大值的文档。
每个文档都有多个版本,因此查看所有最新版本的查询是:
db.getCollection('datatype').aggregate(
[
{
$group:
{
_id: {
"name": "$name",
"applicationId": "$applicationId"
},
latest: { $max: "$version" }
}
}
]
)
现在我需要这个查询的补充(所有以前的版本,不是最新的)。
我尝试了一些查询,如下所示,但没有一个有效。
db.getCollection('datatype').aggregate(
[
{
$group:
{
_id: {
"name": "$name",
"applicationId": "$applicationId"
},
previousVersions:
{ $ne: {$max: "$version"} }
}
}
]
)
编辑:输入/输出示例:输入:
db.getCollection('datatype').insertMany([
{ applicationId: "AAAA", name: "foo", version: NumberInt(1) },
{ applicationId: "AAAA", name: "foo", version: NumberInt(2) },
{ applicationId: "AAAA", name: "foo", version: NumberInt(3) },
{ applicationId: "BBBB", name: "foo", version: NumberInt(1) },
{ applicationId: "CCCC", name: "bar", version: NumberInt(1) },
{ applicationId: "CCCC", name: "bar", version: NumberInt(2) }
])
因此,从 applicationId+name 获取最新版本的第一个查询的预期结果是:
{ applicationId: "AAAA", name: "foo", version: NumberInt(3) },
{ applicationId: "BBBB", name: "foo", version: NumberInt(1) },
{ applicationId: "CCCC", name: "bar", version: NumberInt(2) }
我想要的输出基本上是这个查询的补充,除了最新版本之外的所有结果(所有这些文档都有一个更新版本,它们对应的 applicationId+name)
{ applicationId: "AAAA", name: "foo", version: NumberInt(1) },
{ applicationId: "AAAA", name: "foo", version: NumberInt(2) },
{ applicationId: "CCCC", name: "bar", version: NumberInt(1) }
解决方案
没有单个命令可以执行此操作,如果文档中的自然顺序与顺序db
匹配,version
并且您没有在其他字段上使用任何可能混淆顺序的特定索引,您可以使用$slice删除不需要的版本,像这样:
db.collection.aggregate([
{
$group: {
_id: {
"name": "$name",
"applicationId": "$applicationId"
},
not_latest: {
"$push": "$version"
}
}
},
{
$project: {
_id: 1,
not_latest: {
$slice: [
"$not_latest",
0,
{
$subtract: [
{
$size: "$not_latest"
},
1
]
}
]
}
}
}
])
如果由于某种原因您不能依赖订单,只需在阶段之前添加一个$sort
阶段version: 1
并$group
使用相同的代码。
如果由于某种原因您不想这样做,$sort
您可以暂时保存latest
并使用它来过滤出最终结果,如下所示:
db.collection.aggregate([
{
$group: {
_id: {
"name": "$name",
"applicationId": "$applicationId"
},
not_latest: {
"$push": "$version"
},
latest: {
$max: "$version"
}
}
},
{
$project: {
_id: 1,
not_latest: {
$filter: {
input: "$not_latest",
as: "elem",
cond: {
$ne: [
"$$elem",
"$latest"
]
}
}
}
}
}
])