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

MongoDB查询需求:列出集合中不含NaN值的字段

解决MongoDB提取无NaN值字段的问题

我来帮你搞定这个需求~针对你提到的sample1集合,我们可以通过MongoDB的聚合管道来实现两种常见的需求:要么提取每个文档中无NaN值的字段名称列表,要么直接返回只包含这些有效字段的文档,下面分别给出实现方式:

1. 获取每个文档的无NaN字段名称列表

这个查询会为每个文档返回其_id以及所有值不为NaN的字段名称数组:

db.sample1.aggregate([
  // 将整个文档转换成键值对数组,方便后续过滤
  {
    $addFields: {
      keyValuePairs: { $objectToArray: "$$ROOT" }
    }
  },
  // 过滤掉值为NaN的键值对,再提取字段名称
  {
    $addFields: {
      nonNaNFields: {
        $map: {
          input: {
            $filter: {
              input: "$keyValuePairs",
              // 利用NaN不等于自身的特性,判断值是否为非NaN
              cond: { $expr: { $eq: ["$$this.v", "$$this.v"] } }
            }
          },
          as: "pair",
          in: "$$pair.k"
        }
      }
    }
  },
  // 只保留需要的字段
  {
    $project: {
      _id: 1,
      nonNaNFields: 1
    }
  }
])

执行后,第一个文档会返回:

{ "_id" : 123456, "nonNaNFields" : [ "_id", "name", "day", "field1" ] }

第二个文档会返回:

{ "_id" : 7896321, "nonNaNFields" : [ "_id", "name", "day", "field5" ] }

2. 直接返回仅包含无NaN值字段的文档

如果需要直接得到去掉所有NaN值字段的文档,可以用下面的查询:

db.sample1.aggregate([
  // 将文档转为键值对数组
  {
    $addFields: {
      keyValuePairs: { $objectToArray: "$$ROOT" }
    }
  },
  // 过滤掉值为NaN的键值对
  {
    $addFields: {
      filteredPairs: {
        $filter: {
          input: "$keyValuePairs",
          cond: { $expr: { $eq: ["$$this.v", "$$this.v"] } }
        }
      }
    }
  },
  // 将过滤后的键值对数组转回文档,作为新的根文档
  {
    $replaceRoot: {
      newRoot: { $arrayToObject: "$filteredPairs" }
    }
  }
])

执行后会得到两个精简后的文档:

{ "_id" : 123456, "name" : "question", "day" : "2018-03-21", "field1" : 10 }
{ "_id" : 7896321, "name" : "question", "day" : "2018-03-22", "field5" : 20 }

关键逻辑说明

这里利用了NaN不等于自身的特性来判断字段值是否为NaN:在MongoDB中,$expr: { $eq: ["$$this.v", "$$this.v"] }会返回true当且仅当字段值不是NaN,因为非NaN的值和自身相等,而NaN和任何值(包括自己)都不相等。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:38:14