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

如何在Node.js中查询MongoDB集合里history数组最新状态为running的文档

Node.js中MongoDB查询:筛选history数组最新条目state为'running'的文档

要实现你需要的查询(找出history数组中按createdAt排序后的最新条目state为'running'的文档),Node.js里可以通过聚合管道或MongoDB 5.2+的表达式查询两种方式实现,以下是具体方案:

方案一:聚合管道(兼容所有MongoDB版本)

如果你的MongoDB版本低于5.2(无$sortArray运算符),可以用$unwind+$sort+$group的组合定位每个文档的最新history条目:

// 原生MongoDB驱动示例
const { MongoClient } = require('mongodb');

async function getRunningDocs() {
  const client = await MongoClient.connect('your-mongodb-uri');
  const db = client.db('your-db-name');
  
  const result = await db.collection('your-collection').aggregate([
    // 拆分history数组为独立文档
    { $unwind: '$history' },
    // 按文档ID分组,同时按createdAt降序排序(确保最新条目排在最前)
    { $sort: { _id: 1, 'history.createdAt': -1 } },
    // 重新组合文档,保留原字段,并提取最新的history条目
    {
      $group: {
        _id: '$_id',
        name: { $first: '$name' },
        history: { $push: '$history' }, // 保留完整的history数组
        latestHistory: { $first: '$history' } // 存储最新的history条目
      }
    },
    // 筛选最新条目state为'running'的文档
    { $match: { 'latestHistory.state': 'running' } },
    // 可选:移除临时字段latestHistory,恢复原文档结构
    { $project: { latestHistory: 0 } }
  ]).toArray();
  
  await client.close();
  return result;
}

如果你的MongoDB版本在5.2及以上,可用$sortArray简化聚合逻辑:

async function getRunningDocs() {
  const client = await MongoClient.connect('your-mongodb-uri');
  const db = client.db('your-db-name');
  
  const result = await db.collection('your-collection').aggregate([
    // 添加临时字段:按createdAt降序排序后的history数组
    {
      $addFields: {
        sortedHistory: { $sortArray: { input: '$history', sortBy: { createdAt: -1 } } }
      }
    },
    // 筛选排序后数组第一个元素(最新条目)state为'running'的文档
    { $match: { 'sortedHistory.0.state': 'running' } },
    // 移除临时字段
    { $project: { sortedHistory: 0 } }
  ]).toArray();
  
  await client.close();
  return result;
}

方案二:表达式查询(MongoDB 5.2+ 简洁版)

利用$expr结合$sortArray和$first,直接在find查询中完成筛选,无需聚合管道:

async function getRunningDocs() {
  const client = await MongoClient.connect('your-mongodb-uri');
  const db = client.db('your-db-name');
  
  // 逻辑:将history按createdAt降序排序后取第一个元素,判断其state是否为'running'
  const result = await db.collection('your-collection').find({
    $expr: {
      $eq: [
        { $first: { $sortArray: { input: '$history', sortBy: { createdAt: -1 } } } }.state,
        'running'
      ]
    }
  }).toArray();
  
  await client.close();
  return result;
}

逻辑说明

你的C#代码中w.history.OrderBy(o => o.createdAt).Last().status == "running"的逻辑,对应MongoDB里就是:

  • 将history数组按createdAt升序排序后取最后一个元素,或
  • 按createdAt降序排序后取第一个元素
    两种方式等价,都能定位到时间最新的条目。

验证示例文档

对于你提供的示例数据:

  • 文档_id:1的最新history条目state为'stopped',不会被返回
  • 文档_id:2的最新history条目state为'running',会被筛选出来

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:44:50