首页 > 解决方案 > 如何更新对象数组下嵌套对象数组的增量计数器

问题描述

我有一个这样的嵌套数据结构:

{
    "_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
}

如何增加 192.168.1.2 ip ib TSHIRTS 部分的访问计数器。

我尝试了什么: 我正在使用 node.js 和 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")
}

对于嵌套结构下的增量计数,我们非常感谢任何帮助或建议。请原谅缩进,因为代码很长,所以只需在此处拆分问题部分并手动提及代码。

标签: node.jsmongodbmongoose

解决方案


使用arrayFilters

这个确切的查询在文档Update Nested Arrays in Conjunction with $[] with copy-pasteable 示例中得到了很好的解释。

您只需更新字段名称以匹配您的文档:

db.CollectionName.update(
{}, 
{ $inc: { "count.$[p].guestip.$[ip].visit": 1 } },
{ arrayFilters: [ 
    { "p.page": "TSHIRTS" } , 
    { "ip.ip": "192.168.1.2" } 
] })

请注意,源 ip 为“192.168.1.2”的子文档必须在数组中以供 $inc 递增,因此您可能需要在运行更新查询之前使用 visit:0 推送它。


推荐阅读