如何在聚合中将字段值用作键?

huangapple go评论49阅读模式
英文:

how can I use field value as a key in aggregation?

问题

我有类似以下结构的nmap结果:

_id: 64940937ab90b8acfa5386fb
ip: "1.2.3.4"
top_ports: Object
--> 12.168.16.253: Object
--> state: Object
----> state: "up"

我想要进行聚合操作,以查看有多少台机器处于 'up' 状态。

所以我尝试了以下操作:

$unwind
{
  path: "$top_ports",
}

但我不确定如何进行匹配,其中ip字段值被用作匹配的键:

$match
{
  "$top_ports.ip.state.state": "up"
}

如果我在Python中执行这个操作,替换字符串会很容易,但我需要在MongoDB Compass中进行此聚合操作,以便稍后在MongoDB图表中使用它。

我尝试过以下方式:

$match{"$top_ports.$ip.state.state": "up"}
$match{"$top_ports[ip].state.state": "up"}

以及许多其他尝试,但都没有成功。

我认为我需要使用 $set:

{ 
  allKeys: {$objectToArray: "$top_ports"}
}

但我卡住了 :-/

英文:

I have nmap results in a structure like this:

_id: 64940937ab90b8acfa5386fb
ip : "1.2.3.4"
top_ports: Object
--> 12.168.16.253: Object
--> state: Object
----> state : "up"

I would like to do an aggregation where I can see how many machines are in 'up' state.

So I did

$unwind
{
  path: "$top_ports",
}

but I am not sure how to do the match where the ip field value is used as a key in the match

$match
{
  "$top_ports.$ip.state.state" : "up"
}

If I do it in python it would be easy to replace the string, but I need this aggregation in mongodb compass so I can use it later on in mongodb charts.

I tried

$match{"$top_ports.$ip.state.state" : "up"}
$match{"$top_ports[ip].state.state" : "up"}

and many other desperate combinations

I think I need to use $set

{ 
  allKeys: {$objectToArray: "$top_ports"}
}

but I get stuck :-/

答案1

得分: 0

通常将值用作键不是一个好的做法,如果您可以固定模式,那么在您的情况下更方便的做法是将其设置如下:

{
  "_id": 1,
  "ip": "1.2.3.4",
  "top_ports": [
    {
      "addr": "12.168.16.253",
      "state": {
        "state": "up"
      }
    }
  ]
}

您可以简单地使用以下方式进行匹配:

{ $match:{ "top_ports.addr":"12.168.16.253"}}

并且可以轻松地按如下方式仅筛选匹配状态 "up":

db.collection.aggregate([
{
  "$addFields": {
    "top_ports": {
      "$filter": {
        "input": "$top_ports",
        "as": "tp",
        "cond": {
          $and: [
            {
              "$eq": [
                "$$tp.state.state",
                "up"
              ]
            },
            {
              "$eq": [
                "$$tp.addr",
                "12.168.16.253"
              ]
            }
          ]
        }
      }
    }
   }
 }
])

另外,您还可以使用以下方式进行一些不太适合较大文档和集合的额外转换:

db.collection.aggregate([
{
  "$addFields": {
    "top_ports": {
      "$objectToArray": "$top_ports"
    }
  }
},
{
  $match: {
    "top_ports.k": "12.168.16.253"
  }
},
{
  "$addFields": {
    "top_ports": {
      "$arrayToObject": "$top_ports"
    }
  }
}
])
英文:

Generally having value as key is not a good practice , if you can fix the schema , more convenient in your case would be to have it as follow:

{
 "_id": 1,
 "ip": "1.2.3.4",
 "top_ports": [
   {
      "addr": "12.168.16.253",
      "state": {
        "state": "up"
      }
   }
 ]
}

Where you can match simply by:

{ $match:{ "top_ports.addr":"12.168.16.253"}}

and filter easily only the matching state up like this:

db.collection.aggregate([
{
"$addFields": {
  "top_ports": {
    "$filter": {
      "input": "$top_ports",
      "as": "tp",
      "cond": {
        $and: [
          {
            "$eq": [
              "$$tp.state.state",
              "up"
            ]
          },
          {
            "$eq": [
              "$$tp.addr",
              "12.168.16.253"
            ]
          }
        ]
      }
    }
  }
 }
 }
])

Playgorund2

Otherways you will need to do some additional transformations like the below that are not very optimal for larger documents and collections:

db.collection.aggregate([
{
"$addFields": {
  "top_ports": {
    "$objectToArray": "$top_ports"
  }
 }
 },
 {
  $match: {
   "top_ports.k": "12.168.16.253"
  }
 },
 {
 "$addFields": {
  "top_ports": {
    "$arrayToObject": "$top_ports"
    }
  }
 }
])

Playgorund

huangapple
  • 本文由 发表于 2023年6月22日 19:54:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76531605.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定