【发布时间】:2020-10-17 16:49:19
【问题描述】:
我有一个 MongoDB 数据库,人们可以在其中输入相对任意的搜索条件(在这种情况下,它们经过审查,但在概念上不受限制)。用户可以指定的条件示例可能如下所示:
{"$and": [
{"details.vulns": "cve-2019-19781"},
]}
这对于搜索很有效,但是,我还希望能够根据旧数据生成统计信息,为此我使用如下聚合:
db.hosts.aggregate([
{"$sort": {"timestamp": 1}},
{"$addFields": {
"condition": {$cond: [
{"$and": [
{"details.vulns": "cve-2019-19781"},
]},
1,
0,
]}
}},
{"$project": {
"ip": "$ip",
"timestamp": "$timestamp",
"condition": "$condition",
}},
]);
这种查询的问题是 MongoDB 似乎不允许使用 $cond 和 $details.vulns 之类的东西。我知道标准方法是展开,但是,由于在我的代码执行之前不知道条件,除非我在自己的代码中重新实现 MongoDB 解析引擎,否则我无法知道要展开哪些字段。
为了更清楚地说明问题,这里有一些示例数据。请记住,这是简化的——真实数据包含我可能希望查询的许多不同字段,因此上述关于 unwind 的陈述不是一个令人满意的解决方案:
// Objects
{ "_id" : ObjectId("5cfc73657e2438b115888d1b"), "ip" : NumberLong("12345"), "timestamp" : ISODate("2019-06-09T02:45:45Z"), "vulns" : [ "cve-2019-19781" ] },
{ "_id" : ObjectId("5d04c5497e2438b115b06659"), "ip" : NumberLong("12345"), "timestamp" : ISODate("2019-06-15T10:13:33Z"), "vulns" : [ "" ] },
{ "_id" : ObjectId("5d108c52211d917c6ff48bfd"), "ip" : NumberLong("12345"), "timestamp" : ISODate("2019-06-24T08:37:31Z"), "vulns" : [ "cve-2019-19781", "other-vuln" ] },
// Desired output from aggregate
{"ip" : NumberLong("12345"), "timestamp" : ISODate("2019-06-09T02:45:45Z"), "condition": 1 },
{"ip" : NumberLong("12345"), "timestamp" : ISODate("2019-06-15T10:13:33Z"), "condition": 0 },
{"ip" : NumberLong("12345"), "timestamp" : ISODate("2019-06-24T08:37:31Z"), "condition": 1 },
这里是否有我遗漏的替代方法,或者 MongoDB 只是缺乏在聚合期间应用搜索子句的能力? 如果有一种缓慢的方法,我会接受的。
【问题讨论】:
-
如果您添加一些示例文档和预期结果会有所帮助。
标签: mongodb aggregation-framework