You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB如何用单条update/aggregate实现用户会话嵌套数组多条件增改操作

实现方案

前置准备

提前在业务代码中预处理好以下变量,再传入MongoDB语句:

  • targetUserId:当前登录用户ID,对应req.user._id
  • currentDay:当前日期,格式为dd/MM/YYYY,例如14/11/2021
  • currentHour:当前时间,格式为hhmmss
  • reqReferer:请求来源,对应req.headers.referer
  • reqIp:客户端IP,对应req.socket.remoteAddress

单条updateOne实现语句

db['users-sessions'].updateOne(
  // 匹配需要更新的目标文档,示例按_id匹配
  { _id: "abcd" },
  [
    // 第一步:处理usersession数组,响应用户存在/不存在的逻辑
    {
      $set: {
        usersession: {
          $cond: {
            // 判断usersession中是否存在当前用户的记录
            if: { $in: [targetUserId, "$usersession.userId"] },
            then: {
              $map: {
                input: "$usersession",
                as: "user",
                in: {
                  $cond: {
                    if: { $eq: ["$$user.userId", targetUserId] },
                    then: {
                      $mergeObjects: [
                        "$$user",
                        {
                          date: {
                            $let: {
                              vars: {
                                // 判断当前用户的date数组中是否存在当天记录
                                hasCurrentDay: { $in: [currentDay, "$$user.date.day"] },
                                // 新的当天记录结构
                                newDayEntry: {
                                  day: currentDay,
                                  sessionday: [
                                    { hour: currentHour, referer: reqReferer, ip: reqIp }
                                  ]
                                },
                                // 原有date数组
                                originalDate: "$$user.date"
                              },
                              in: {
                                $cond: {
                                  // 情况1:存在当天记录,更新对应sessionday
                                  if: "$$hasCurrentDay",
                                  then: {
                                    $map: {
                                      input: "$$originalDate",
                                      as: "dayEntry",
                                      in: {
                                        $cond: {
                                          if: { $eq: ["$$dayEntry.day", currentDay] },
                                          then: {
                                            $mergeObjects: [
                                              "$$dayEntry",
                                              {
                                                sessionday: {
                                                  $concatArrays: [
                                                    "$$dayEntry.sessionday",
                                                    [{ hour: currentHour, referer: reqReferer, ip: reqIp }]
                                                  ]
                                                }
                                              }
                                            ]
                                          },
                                          else: "$$dayEntry"
                                        }
                                      }
                                    }
                                  },
                                  // 情况2:不存在当天记录,新增日期条目,同时处理长度>=10的替换逻辑
                                  else: {
                                    $cond: {
                                      if: { $gte: [{ $size: "$$originalDate" }, 10] },
                                      // 日期数>=10,删除最早的(第一个元素),添加新日期
                                      then: {
                                        $concatArrays: [
                                          { $slice: ["$$originalDate", 1, 9] },
                                          ["$$newDayEntry"]
                                        ]
                                      },
                                      // 日期数<10,直接追加新日期
                                      else: { $concatArrays: ["$$originalDate", ["$$newDayEntry"]] }
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      ]
                    },
                    else: "$$user"
                  }
                }
              }
            },
            // 情况3:用户不存在,新增用户条目
            else: {
              $concatArrays: [
                "$usersession",
                [
                  {
                    userId: targetUserId,
                    date: [
                      {
                        day: currentDay,
                        sessionday: [
                          { hour: currentHour, referer: reqReferer, ip: reqIp }
                        ]
                      }
                    ]
                  }
                ]
              ]
            }
          }
        }
      }
    }
  ]
)

逻辑说明

完全覆盖全部4个操作条件:

  1. 用户存在且当天记录存在:直接往对应sessionday数组追加新的会话记录
  2. 用户存在但当天记录不存在:往对应用户的date数组新增当天的会话结构
  3. 用户不存在:直接往usersession数组新增完整的用户会话结构
  4. 对应用户date数组长度>=10时,自动移除最早的日期记录,再添加新的日期记录(默认date数组按时间从早到晚排序,最早记录为数组第一个元素,若排序逻辑不同可调整$slice参数即可)

内容的提问来源于stack exchange,提问作者ropo ast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 02:36:04