问题
I am writing a python script that performs these tasks:
- Query a MongoDB Collection with embeded documents
- Aggregate and Project to change the field names that are returned in the query to match a "u_" convention
- Import the values to ServiceNow via REST API
ISSUE:
The embedded documents are not in a consistent structure. The HOSTNAME field is stored in varying structures.
I need to return the hostname as u_hostname. I need the value of $hostnames.name if it exists OR the value of $hostname if it exists.
How can I determine if either one exists, and return it as u_hostname?
Structure 1 Hostname stored as $hostnames.name
{
"_id" : "192.168.1.1",
"addresses" : {
"ipv4" : "192.168.1.1"
},
"hostnames" : [
{
"type" : "PTR",
"name" : "example.hostname.com"
}
]
}
Structure 2 Hostname stored as $hostname
{
"_id" : "192.168.2.1",
"addresses" : {
"ipv4" : "192.168.2.1"
},
"hostname" : "helloworld.com",
}
Script:
The query will only return the value of $hostname, not $hostname.name.
cmp = db['computers'].aggregate([
{"$project" : {
"_id":0,
"u_hostname": "$hostnames.name",
"u_hostname": "$hostname",
"u_ipv4": "$addresses.ipv4"
}}
])
回答1:
You can use the $ifNull operator to $project the "hostname" field.
cmp = db['computers'].aggregate([
{"$project": {
"u_hostname": {
"$ifNull": [
"$hostnames.name",
{ "$map": {
"input": {"$literal": ["A"]},
"as": "el",
"in": "$hostname"
}}
]
},
"_id": 0,
"u_ipv4": "$addresses.ipv4"
}},
{"$unwind": "$u_hostname"}
])
回答2:
You want the $unwind, $group and $setUnion operators included in the aggregate function. It will allow you to flatten you list of hostnames.name and then union them with the other hostnames.
来源:https://stackoverflow.com/questions/38234053/project-different-embedded-structures-to-same-name