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

Node.js+Mongoose插入数据时无法自动创建时间序列集合

解决Mongoose自动创建MongoDB时间序列集合问题

问题概述

你已通过Mongoose定义了包含timeseries配置的Schema,插入数据后却生成普通集合而非预期的时间序列集合,且确认MongoDB版本符合要求、手动创建时间序列集合功能正常。

核心原因

你在saveData函数中混用了**原生MongoDB驱动的MongoClient**和Mongoose Model,直接调用coll.insertOne()插入Mongoose实例的方式,不会触发Mongoose的Schema初始化逻辑(包括时间序列集合的创建规则)。只有使用Mongoose Model提供的方法(如save()、create())时,才会按照Schema配置自动创建对应类型的集合。


方法1:使用Mongoose Model方法插入数据(推荐)

完全依托Mongoose的连接和Model操作,避免混用原生驱动。

步骤1:创建Mongoose连接文件

新建db.js文件统一管理数据库连接:

const mongoose = require('mongoose');
require('dotenv').config();

async function connectDB() {
  try {
    await mongoose.connect(process.env.MONGO_COMPASS_URI, {
      useUnifiedTopology: true
    });
    console.log('Mongoose 已连接数据库');
  } catch (err) {
    console.error('Mongoose 连接失败:', err);
    process.exit(1);
  }
}

module.exports = connectDB;

步骤2:修改定时任务脚本

require('dotenv').config();
const mongoose = require('mongoose');
const connectDB = require('./db');
const DailyMeasurementModel = require('../app/Models/AQDataDaily');

const data_files = [
    '../test-data-json/asdasdasdasd.json',
    '../test-data-json/aaaa.json',
    '../test-data-json/sssss.json',
]

const getData = async () => {
    await connectDB();
    try {
        for (let i = 0; i < data_files.length; i++) {
            const response = require(data_files[i]);
            await saveData(response);
        }
    } catch (error) {
        console.log('getData 执行错误: ', error);
    } finally {
        await mongoose.disconnect();
    }
}

async function saveData(data) {
    try {
        const newDailyMeasurement = new DailyMeasurementModel({
            time: new Date(), // 直接传入Date对象,匹配Schema定义的Date类型
            daily: data.historical.daily,
            name: data.name
        });
        const result = await newDailyMeasurement.save(); // 使用Mongoose的save方法触发Schema逻辑
        console.log('文档保存成功:', result);
    } catch (err) {
        console.error('保存文档失败:', err);
    }
}

getData();

方法2:原生驱动手动创建时间序列集合

若坚持使用MongoClient,需先检查集合是否存在,不存在则按时间序列规则手动创建后再插入数据。

修改saveData函数:

async function saveData(data) {
    const client = new MongoClient(process.env.MONGO_COMPASS_URI, {useUnifiedTopology: true});
    try {
        await client.connect();
        const db = client.db("iq-air-database");
        const collName = "daily-collection-ts";
        
        // 检查集合是否已存在
        const collections = await db.listCollections({name: collName}).toArray();
        if (collections.length === 0) {
            // 创建时间序列集合
            await db.createCollection(collName, {
                timeseries: {
                    timeField: 'time' // 与Schema配置保持一致
                }
            });
        }
        
        const coll = db.collection(collName);
        const newDailyMeasurement = {
            time: new Date(), // 传入Date类型而非时间戳数字
            daily: data.historical.daily,
            name: data.name
        };

        const result = await coll.insertOne(newDailyMeasurement);
        console.log('文档保存成功:', result);
    } catch (error) {
        console.log('saveData 执行错误: ', error);
    } finally {
        await client.close();
    }
}

额外注意事项

  1. 时间字段类型:确保time字段传入的是Date对象,而非new Date().getTime()返回的数字(MongoDB时间序列集合要求timeField为Date类型)。
  2. 清理旧集合:若之前已生成普通集合,需先删除该集合,再重新运行代码(Mongoose的timeseries配置仅在集合首次创建时生效)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 23:52:50