为啥 MongoDB 子文档过期会删除父文档?

Posted

技术标签:

【中文标题】为啥 MongoDB 子文档过期会删除父文档?【英文标题】:Why MongoDB subdocument expiration removes parent document?为什么 MongoDB 子文档过期会删除父文档? 【发布时间】:2018-11-28 09:41:15 【问题描述】:

我使用 mongoose 5 并且有这样的架构:

user.js

const mongoose = require('mongoose');
const GeoData = require('./geodata');

const UserSchema = new mongoose.Schema(
  name: 
    type: String,
    required: true
  ,
  createdAt: 
    type: Date,
    default: Date.now()
  ,
  geodata: GeoData
);

UserSchema.index( deviceToken: 1 ,  unique: true );

module.exports = UserSchema;

geodata.js

const mongoose = require('mongoose');
const c2p = require('circle-to-polygon');

const GeoDataSchema = new mongoose.Schema(
  location: 
    coordinates: [Number],
    type: 
      type: String
    
  ,
  createdAt: 
    type: Date,
    default: Date.now()
  ,
  expireAt: 
    type: Date,
    default: new Date().setHours(12,0,0,0)
  
);

GeoDataSchema.index( location: "2dsphere", bounds: "2dsphere" );
GeoDataSchema.index( 'expireAt': 1 ,  expireAfterSeconds: 0 );

module.exports = GeoDataSchema;

假设geodata 子文档被添加到父user 文档中,默认情况下过期设置为当地时间12:00:00。 不幸的是,这会删除带有子文档 geodata 的父 user,而不是像我期望的那样仅删除 geodata

这是正常行为还是我错过了什么?

【问题讨论】:

【参考方案1】:

TTL 索引始终适用于根文档,而不适用于单个子文档或文档的其他部分。

根据documentation:

一个特殊的 TTL 索引属性支持 TTL 的实现 收藏品。 TTL 功能依赖于 mongod 中的后台线程 读取索引中的日期类型值并删除过期的 集合中的文档。

【讨论】:

谢谢 - 我错过的词是 documents。无论如何,如果将来实施它会非常整洁。现在我必须编写一个 cron 作业来迭代并查找过时的文档,或者将 geodata 移动到它自己的集合中并添加它自己的 TTL 索引。 您可以提交功能请求吗? 当然可以!

以上是关于为啥 MongoDB 子文档过期会删除父文档?的主要内容,如果未能解决你的问题,请参考以下文章

mongodb 设置自动删除过期数据

MongoDB:删除文档后更新子文档数组

Mongoose 参考文档的 TTL 过期

使用 mongoose 从 Mongodb 中删除子文档

如果为空,则过滤子文档数组,同时仍返回父数据

我需要删除 MongoDB 中的子文档