英文:
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"
]
}
]
}
}
}
}
}
])
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"
}
}
}
])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论