Reputation: 1234
I have an nested data structure like this:
{
"_id" : ObjectId("5f51362883fc9424bcc3ed76"),
"count" : [
{
"page" : "SHOE",
"visit_count" : 2,
"guestip" : [
{
"ip" : "192.168.1.4",
"visit" : 1
},
{
"ip" : "192.168.1.5",
"visit" : 1
}
]
},
{
"page" : "TSHIRTS",
"visit_count" : 2,
"guestip" : [
{
"ip" : "192.168.1.1",
"visit" : 1
},
{
"ip" : "192.168.1.2",
"visit" : 1
}
]
}
],
"createdate" : ISODate("2020-09-03T18:30:00.056Z"),
"__v" : 0
}
How I can increment the visit counter for 192.168.1.2 ip ib TSHIRTS section.
What I tried: I am using node.js and mongoose;
const isIPExists = (ip, arr) => arr.some(el => String(el.ip) === ip);
//NOTE: Below code is under async function that is why used the await.
const data = await CollectionName.findOne(
{ createdate: { $gte: finaldate } },
{ assetpage_visit_count: { $elemMatch: { page: req.body.page } } },
).exec();
if (data.count.length === 0) {
//This part works fine
await CollectionName.updateOne(
{ createdate: { $gte: finaldate } },
{
$push: {
count: {
page: req.body.page, //Here let's say TSHIRTS is sending
visit_count: 1,
guestip: [
{
ip: req.body.ip,
visit: 1
}
]
},
},
).exec();
} else {
const storeIpArray = data.count[0].guestip;
let xfilter = {
$inc: {
'count.$.visit_count': 1,
},
$push: {
'count.$.guestip': {
ip: req.body.ip,
visit: 1
}
}
}
if (isIPExists(req.body.ip, storeIpArray) === true) {
xfilter = {
$inc: {
'count.$.visit_count': 1,
'count.$.visit_count.$.visit': 1
},
}
}
await CollectionName.updateOne(
{
createdate: { $gte: finaldate },
'count.page': req.body.page,
},
xfilter,
).exec();
}
return res.send("Done")
}
Any help or suggestion is really appreciated for the increment count under nested structure. Pardon for the indenting as code was very long so just split the issue part here and mentioned the code manually.
Upvotes: 0
Views: 255
Reputation: 37038
Use arrayFilters.
This exactly query is very well explain in the documentation Update Nested Arrays in Conjunction with $[] with copy-pasteable examples.
You just had to update field names to match your documents:
db.CollectionName.update(
{},
{ $inc: { "count.$[p].guestip.$[ip].visit": 1 } },
{ arrayFilters: [
{ "p.page": "TSHIRTS" } ,
{ "ip.ip": "192.168.1.2" }
] })
Please note, the subdocument with source ip "192.168.1.2" must be in the array for $inc to increment it, so you may need to push it with visit:0 before running the update query.
Upvotes: 1