【问题标题】:Removing Latest document from Mongo DB in single query在单个查询中从 Mongo DB 中删除最新文档
【发布时间】:2018-11-07 03:35:59
【问题描述】:

我想在单个查询中从我的 MongoDB 中删除最新的文档。

我尝试了一些命令,但它们似乎不起作用。

【问题讨论】:

  • 你能展示一下你的尝试吗?
  • 我尝试了一些命令,但它们似乎不起作用。它们是什么?
  • 请同时说明您所说的“最新文档”是什么意思,一些示例文档,您所追求的结果,以及到目前为止您尝试过的内容。
  • @KevinAdistambha 最新我的意思是 createdAt:-1
  • 您认为提供的答案中是否有某些内容无法解决您的问题?如果是这样,那么请对答案发表评论,以澄清究竟需要解决哪些尚未解决的问题。如果它确实回答了您提出的问题,请注意Accept your Answers您提出的问题

标签: node.js mongodb mongoose mongodb-query


【解决方案1】:

您正在寻找的基本操作是 findOneAndDelete() in mongoose,这是一个返回“已删除”文档和响应的原子操作。这只会影响单个文档,您可以通过在选项中应用排序规范来获得“最后一个”。

您基本上有两个“最后”选项,或者是一个包含 BSON“日期”属性的字段,您存储在可以排序的文档中:

Model.findOneAndDelete(
   { "field": "a" },
   { "sort": { "date": -1 } }
)

或者通过使用 _id 字段,其中使用了 ObjectId,因为没有任何其他干预,该值将随着每个插入的文档“始终增加”:

Model.findOneAndDelete(
   { "field": "a" },
   { "sort": { "_id": -1 } }
)

如果您没有在文档中存储带有 BSON 日期的字段作为确定“最新插入”或“最后修改”的方法,那么这通常是您的选择。如果您想要“最后修改”,那么您真的没有其他选择可以在文档中记录这样的 BSON 日期属性,因为 _id 本身是不可变的并且不会更改,并且充其量是“创建的”的“后备”当您没有明确存储任何其他字段来记录此类信息时。

下面是一个完整的示例,该示例演示了将多个文档添加到集合中,然后仅“删除”满足所提供查询条件的“最后一个”文档。演示了使用存储日期和_id 字段:

const { Schema } = mongoose = require('mongoose');

const uri = 'mongodb://localhost/test';

mongoose.Promise = global.Promise;
mongoose.set('debug', true);

const testSchema = new Schema({
  field: String,
  other: String,
  date: Date
});

const Test = mongoose.model('Test', testSchema);

const log = data => console.log(JSON.stringify(data, undefined, 2));


(async function() {

  const now = Date.now();
  const today = now - (now % (1000 * 60 * 60 * 24));

  try {
    const conn = await mongoose.connect(uri);

    await Promise.all(Object.entries(conn.models).map(([k,m]) => m.remove()));

    await Test.insertMany([
      ...[ ...Array(4)].map((e,i) =>
        ({
           field: "a",
           ...(i === 3) ? { other: "last" }
            : (i === 2) ? { other: "second last" } : {},
           date: new Date(today + (i * 1000 * 60 * 60 * 24))
        })
      ),
      { field: "b", date: new Date(today + (5 * 1000 * 60 * 60 * 24)) }
    ]);

    let removed = await Test.findOneAndDelete(
      { field: "a" },
      { sort: { "date": -1 } }
    );

    log({ removed });

    let remaining = await Test.find();
    log({ remaining });

    let next_removed = await Test.findOneAndDelete(
      { field: "a" },
      { sort: { "_id": -1 } }
    );
    log({ next_removed });

    let still_remaining = await Test.find();
    log({ still_remaining });

    mongoose.disconnect();

  } catch(e) {
    console.error(e)

  } finally {
    process.exit()
  }

})()

这会返回预期的输出:

Mongoose: tests.remove({}, {})
Mongoose: tests.insertMany([ { _id: 5b0cb4a60cf8000c7ebd4402, field: 'a', date: 2018-05-29T00:00:00.000Z, __v: 0 }, { _id: 5b0cb4a60cf8000c7ebd4403, field: 'a', date: 2018-05-30T00:00:00.000Z, __v: 0 }, { _id: 5b0cb4a60cf8000c7ebd4404, field: 'a', other: 'second last', date: 2018-05-31T00:00:00.000Z, __v: 0 }, { _id: 5b0cb4a60cf8000c7ebd4405, field: 'a', other: 'last', date: 2018-06-01T00:00:00.000Z, __v: 0 }, { _id: 5b0cb4a60cf8000c7ebd4406, field: 'b', date: 2018-06-03T00:00:00.000Z, __v: 0 } ], {})
Mongoose: tests.findOneAndDelete({ field: 'a' }, { sort: { date: -1 } })
{
  "removed": {
    "_id": "5b0cb4a60cf8000c7ebd4405",
    "field": "a",
    "other": "last",
    "date": "2018-06-01T00:00:00.000Z",
    "__v": 0
  }
}
Mongoose: tests.find({}, { fields: {} })
{
  "remaining": [
    {
      "_id": "5b0cb4a60cf8000c7ebd4402",
      "field": "a",
      "date": "2018-05-29T00:00:00.000Z",
      "__v": 0
    },
    {
      "_id": "5b0cb4a60cf8000c7ebd4403",
      "field": "a",
      "date": "2018-05-30T00:00:00.000Z",
      "__v": 0
    },
    {
      "_id": "5b0cb4a60cf8000c7ebd4404",
      "field": "a",
      "other": "second last",
      "date": "2018-05-31T00:00:00.000Z",
      "__v": 0
    },
    {
      "_id": "5b0cb4a60cf8000c7ebd4406",
      "field": "b",
      "date": "2018-06-03T00:00:00.000Z",
      "__v": 0
    }
  ]
}
Mongoose: tests.findOneAndDelete({ field: 'a' }, { sort: { _id: -1 } })
{
  "next_removed": {
    "_id": "5b0cb4a60cf8000c7ebd4404",
    "field": "a",
    "other": "second last",
    "date": "2018-05-31T00:00:00.000Z",
    "__v": 0
  }
}
Mongoose: tests.find({}, { fields: {} })
{
  "still_remaining": [
    {
      "_id": "5b0cb4a60cf8000c7ebd4402",
      "field": "a",
      "date": "2018-05-29T00:00:00.000Z",
      "__v": 0
    },
    {
      "_id": "5b0cb4a60cf8000c7ebd4403",
      "field": "a",
      "date": "2018-05-30T00:00:00.000Z",
      "__v": 0
    },
    {
      "_id": "5b0cb4a60cf8000c7ebd4406",
      "field": "b",
      "date": "2018-06-03T00:00:00.000Z",
      "__v": 0
    }
  ]
}

注意:对于实际的节点驱动程序,findOneAndDelete() 基本相同,是 mongoose 对服务器的实际调用,但旧版本的 mongoose 仅​​支持 findOneAndRemove(),几乎相同在选项中,而是通过核心 API 发出 findAndModify() 请求。

从技术角度来看,这些实际上都是findAndModify 命令,但是通常更喜欢使用现代 API,因为这些方法在其预期目的上具有“明确性”,并且还可以选择合理的“默认值”范围服务器实际处理的更广泛的“命令”的可用选项。

【讨论】:

    【解决方案2】:

    很简单:

    Model.findOneAndDelete({},{"sort": { "_id": -1 }})
    

    【讨论】:

      猜你喜欢
      • 2013-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-15
      • 2012-04-18
      相关资源
      最近更新 更多