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

如何从对象数组中按ownerId筛选出endDate最新的文档?

问题描述

我有一个包含startDate、endDate、ownerId和ownerType字段的MongoDB集合,目前用以下查询获取未来30天内到期的文档:

var yesterdayDate = new Date();
yesterdayDate.setDate(yesterdayDate.getDate() - 1);
var next30daysDate = new Date();
next30daysDate.setDate(next30daysDate.getDate() + 29);
const insurances = await Insurances.find({endDate: {$gte: yesterdayDate, $lte: next30daysDate}});

查询返回结果如下:

[
  {
    docIds: [ "6285c7ce9fb2940007e61ce2" ],
    _id: "6285c7cd9fb2940007e61cde",
    startDate: "2022-03-31T18:30:00.000Z",
    endDate: "2022-09-28T18:30:00.000Z",
    ownerId: "61de54e8ae38620006457674",
    ownerType: "vendor",
    createdAt: "2022-05-19T04:30:06.040Z",
    updatedAt: "2022-09-06T09:42:37.497Z",
    __v: 0,
    name: "download"
  },
  {
    docIds: [ "631edc3da1c7060007242fca" ],
    _id: "631edc3da1c7060007242fc2",
    startDate: "2022-09-13T18:30:00.000Z",
    endDate: "2022-09-27T18:30:00.000Z",
    ownerId: "6156aeeb152a3040b82fbc50",
    ownerType: "vendor",
    createdAt: "2022-09-12T07:14:05.616Z",
    updatedAt: "2022-09-12T12:04:57.897Z",
    __v: 0,
    name: "bid manager"
  },
  {
    docIds: [ "631f203b71f6f042243bcb26" ],
    _id: "631f203871f6f042243bcb1f",
    startDate: "2022-09-13T06:30:00.000Z",
    endDate: "2022-09-29T06:30:00.000Z",
    name: "Javascript Training",
    ownerId: "6156aeeb152a3040b82fbc50",
    ownerType: "vendor",
    createdAt: "2022-09-12T12:04:10.938Z",
    updatedAt: "2022-09-12T12:04:11.557Z",
    __v: 0
  },
  {
    docIds: [ "631f203b71f6f042243bcb28" ],
    _id: "631f203871f6f042243bcb20",
    startDate: "2022-09-12T18:30:00.000Z",
    endDate: "2022-09-27T18:30:00.000Z",
    name: "SP-UserAccounts-200622-1021",
    ownerId: "6156aeeb152a3040b82fbc50",
    ownerType: "vendor",
    createdAt: "2022-09-12T12:04:10.943Z",
    updatedAt: "2022-09-12T12:04:47.312Z",
    __v: 0
  },
  {
    docIds: [ "632155e5488a188c34ba5473" ],
    _id: "632155e1488a188c34ba546f",
    startDate: "2022-09-13T06:30:00.000Z",
    endDate: "2022-09-24T06:30:00.000Z",
    name: "bid-project-details",
    ownerId: "6253c6a067a5b83c84855f99",
    ownerType: "vendor",
    createdAt: "2022-09-14T04:17:41.082Z",
    updatedAt: "2022-09-14T04:17:41.674Z",
    __v: 0
  },
  {
    docIds: [ "6321fe4317dfea0007e828fe" ],
    _id: "6321fe2217dfea0007e828c9",
    startDate: "2022-09-14T00:00:00.000Z",
    endDate: "2022-09-15T00:00:00.000Z",
    ownerId: "5bca41cbe5a5c1808da49b1c",
    ownerType: "vendor",
    createdAt: "2022-09-14T16:15:30.986Z",
    updatedAt: "2022-09-14T16:16:03.604Z",
    __v: 0
  },
  {
    docIds: [ "6321ff3e17dfea0007e829dc" ],
    _id: "6321fe2217dfea0007e828c6",
    startDate: "2022-09-15T00:00:00.000Z",
    endDate: "2022-09-15T00:00:00.000Z",
    ownerId: "5bca41cbe5a5c1808da49b1c",
    ownerType: "vendor",
    createdAt: "2022-09-14T16:15:31.215Z",
    updatedAt: "2022-09-14T16:20:14.721Z",
    __v: 0
  },
  {
    docIds: [ "6321fef84377f600061f7f43" ],
    _id: "6321fe2217dfea0007e828c8",
    startDate: "2022-09-14T00:00:00.000Z",
    endDate: "2022-09-24T00:00:00.000Z",
    ownerId: "5bca41cbe5a5c1808da49b1c",
    ownerType: "vendor",
    createdAt: "2022-09-14T16:15:31.233Z",
    updatedAt: "2022-09-14T16:19:04.341Z",
    __v: 0
  },
  {
    docIds: [ "6321ff5c17dfea0007e829f7" ],
    _id: "6321fe2217dfea0007e828c7",
    startDate: "2022-09-14T00:00:00.000Z",
    endDate: "2022-09-15T00:00:00.000Z",
    ownerId: "5bca41cbe5a5c1808da49b1c",
    ownerType: "vendor",
    createdAt: "2022-09-14T16:15:31.298Z",
    updatedAt: "2022-09-14T16:20:44.631Z",
    __v: 0
  }
]

现在需要从结果中按ownerId分组,每个ownerId只保留endDate最新的那一条文档,该怎么实现?

解决方案

方式一:MongoDB聚合查询(推荐)

直接在数据库层面完成筛选和分组,效率更高,避免拉取大量数据到前端处理。使用aggregate管道实现:

var yesterdayDate = new Date();
yesterdayDate.setDate(yesterdayDate.getDate() - 1);
var next30daysDate = new Date();
next30daysDate.setDate(next30daysDate.getDate() + 29);

const latestInsurances = await Insurances.aggregate([
  // 过滤日期范围内的文档
  { $match: { endDate: { $gte: yesterdayDate, $lte: next30daysDate } } },
  // 按endDate降序排序,确保最新的文档排在每组最前面
  { $sort: { endDate: -1 } },
  // 按ownerId分组,保留每组第一个文档(即endDate最新的)
  {
    $group: {
      _id: "$ownerId",
      latestDoc: { $first: "$$ROOT" }
    }
  },
  // 将最新文档作为根文档输出,结构与原文档一致
  { $replaceRoot: { newRoot: "$latestDoc" } }
]);

方式二:前端JavaScript处理

如果已经拿到原查询的insurances数组,可以在前端通过JS处理:

// 先按endDate降序排序,确保每个ownerId的最新文档排在前面
const sortedInsurances = [...insurances].sort((a, b) => b.endDate - a.endDate);

// 用对象去重,只保留每个ownerId的第一个文档
const result = Object.values(
  sortedInsurances.reduce((acc, doc) => {
    if (!acc[doc.ownerId]) {
      acc[doc.ownerId] = doc;
    }
    return acc;
  }, {})
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 07:40:34