【问题标题】:Is there a way to apply an arbitrary condition to a MongoDB aggregation?有没有办法将任意条件应用于 MongoDB 聚合?
【发布时间】: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


【解决方案1】:

不清楚您在寻找什么。你是这个意思吗?

{"$addFields": {
    "condition": {$cond: [
        {$eq: ["$details.vulns": "cve-2019-19781"]},
        1,
        0,
    ]}
}},

还是简单的$match

你可以跑

var field = "ip";
db.hosts.aggregate([
  {$unwind: field }
])

var condObj = JSON.parse('{"$and": [{"details.vulns": "cve-2019-19781"}]}');
db.hosts.aggregate([
    {"$addFields": {
        "condition": {$cond: [
            condObj,
            1,
            0,
        ]}
    }}
]);

顺便说一句,你可以简单地写:

{"$project": {
    "ip": 1,
    "timestamp": 1,
    "condition": 1
}}

【讨论】:

  • 我已在问题中添加了更多详细信息,希望能帮助演示该问题,当我尝试运行时,您的第一个查询片段也会给我一个语法错误。
  • 更正了语法错误。对我来说,仍然不清楚你在寻找什么。为什么以及何时期望 10 用于字段 condition
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-04
  • 1970-01-01
  • 1970-01-01
  • 2018-09-16
  • 2020-09-03
  • 1970-01-01
相关资源
最近更新 更多