我已经被困在这个问题上了一段时间,我觉得我已经接近了,但却无法找到解决方案。
我有一个如下所示的精简架构:
{
"_id": {
"$oid": "5a423f48d3983274668097f3"
},
"id": "59817",
"key": "DW-15450",
"changelog": {
"histories": [
{
"id": "449018",
"created": "2017-12-13T11:11:26.406+0000",
"items": [
{
"field": "status",
"toString": "Released"
}
]
},
{
"id": "448697",
"created": "2017-12-08T09:54:41.822+0000",
"items": [
{
"field": "resolution",
"toString": "Fixed"
},
{
"field": "status",
"toString": "Completed"
}
]
}
]
},
"fields": {
"issuetype": {
"id": "1",
"name": "Bug"
}
}
}
我想抓住changelog.histories
changelog.histories.items.toString
值为Completed
的所有"pipeline" => [
[
'$match' => [
'changelog.histories.items.toString' => 'Completed'
]
],
[
'$unwind' => '$changelog.histories'
],
[
'$project' => [
'changelog.histories' => [
'$filter' => [
'input' => '$changelog.histories.items',
'as' => 'item',
'cond' => [
'$eq' => [
'$$item.toString', 'Completed'
]
]
]
]
]
]
]
。
以下是我的管道
{
"id": "448697",
"created": "2017-12-08T09:54:41.822+0000",
"items": [
{
"field": "resolution",
"toString": "Fixed"
},
{
"field": "status",
"toString": "Completed"
}
]
理想情况下,我希望以下内容返回
{{1}}
}
答案 0 :(得分:1)
你可以尝试这样的事情。
db.changeLogs.aggregate([
{ $unwind: '$changelog.histories' },
{ $match: {'changelog.histories.items.toString': 'Completed'} },
{ $replaceRoot: { newRoot: "$changelog.histories" } }
]);
此解决方案执行COLLSCAN,因此在大量收集时会很昂贵。如果您有严格的性能要求,可以按如下方式创建索引。
db.changeLogs.createIndex({'changelog.histories.items.toString': 1})
然后,为了利用索引,您必须按如下方式更改查询。
db.changeLogs.aggregate([
{ $match: {'changelog.histories.items.toString': 'Completed'} },
{ $unwind: '$changelog.histories' },
{ $match: {'changelog.histories.items.toString': 'Completed'} },
{ $replaceRoot: { newRoot: "$changelog.histories" } }
]);
第一阶段过滤在Completed
状态下具有至少一个历史记录项的changeLog文档。此阶段使用索引。第二阶段解开向量。第三阶段再次过滤具有Completed
状态中的至少一个历史项的展开文档。最后,第四阶段将根返回项替换为文档。
根据您的评论,这是一个替代解决方案,在保留的文档中保留id
和key
字段(同时保持使用索引)。
db.changeLogs.aggregate([
{ $match: {'changelog.histories.items.toString': 'Completed'} },
{ $unwind: '$changelog.histories' },
{ $match: {'changelog.histories.items.toString': 'Completed'} },
{ $project: { _id: 0, id: 1, key: 1, changelog: 1 }}
]);