Hi @amenlust2 and welcome in the MongoDB Community! 
I have to say that this one made me sweat a little! 
First of all, you have a typo in your document above, it’s missing a ' after the field ftp.
Then, I’m guessing that you need to provide some extra information to identify which element of the checks array needs to be updated in the ports array so I took the supposition / decision that number was unique in your array of ports and I assumed that this is how you identify which element to update as you probably don’t want to update all the checks arrays.
So I simplified a bit the document model for the sake of the example:
db.c.drop()
db.c.insertOne({
"ip": "192.168.1.1",
"ports": [
{
"number": 21,
"checks": [
{
"name": "ABC",
"result": "success"
}
]
},
{
"number": 80,
"checks": []
},
{
"number": 444
}
]
})
Now that I have a sample document, let’s define some variables that I can use as query parameters.
const number = 21
const name = "DEF"
const description = "my new description"
const result = "my new result"
And here is the update query. This query loops through the ports array elements. When the provided number is found, it removes the existing document with the provided name from the checks array (if it exists) and then appends the new document at the end.
db.c.updateOne({"ip": "192.168.1.1", "ports.number": number}, [{
"$set": {
"ports": {
"$map": {
input: "$ports",
as: "p",
in: {
"$cond": {
if: {"$eq": ["$$p.number", number]},
then: {
"$mergeObjects": ["$$p", {
"checks": {
"$concatArrays": [
{
"$filter": {
"input": "$$p.checks",
"cond": {"$ne": ["$$this.name", name]}
}
},
[{"name": name, "description": description, "result": result}]
]
}
}]
},
else: "$$p"
}
}
}
}
}
}]
)
Note that to support this query, you need the index:
db.c.createIndex({"ip": 1, "ports.number": 1})
Here is the result after the first execution of this query. As DEF doesn’t exist in the checks, it’s added in the array:
{
_id: ObjectId("64cbf22a5f5937b78f2b78b4"),
ip: '192.168.1.1',
ports: [
{
number: 21,
checks: [
{ name: 'ABC', result: 'success' },
{
name: 'DEF',
description: 'my new description',
result: 'my new result'
}
]
},
{ number: 80, checks: [] },
{ number: 444 }
]
}
Now if I provide new values for description and result but with the same name and run the query again, this time the array entry is “updated”. (It’s actually removed and re-added in the query but you get the idea…).
const description = "my OTHER description"
const result = "my OTHER result"
Result:
{
_id: ObjectId("64cbf22a5f5937b78f2b78b4"),
ip: '192.168.1.1',
ports: [
{
number: 21,
checks: [
{ name: 'ABC', result: 'success' },
{
name: 'DEF',
description: 'my OTHER description',
result: 'my OTHER result'
}
]
},
{ number: 80, checks: [] },
{ number: 444 }
]
}
Enjoy!
Maxime 