在单个查询中从 Mongo DB 中删除最新文档 [英] Removing Latest document from Mongo DB in single query

查看:16
本文介绍了在单个查询中从 Mongo DB 中删除最新文档的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

解决方案

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

然后,您基本上有两个last"选项,或者通过包含您存储在文档中的 BSONdate"属性的字段,您可以对其进行排序:

Model.findOneAndDelete({字段":一个"},{排序":{日期":-1}})

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

Model.findOneAndDelete({字段":一个"},{排序":{_id":-1}})

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

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

const { Schema } = mongoose = require('mongoose');const uri = 'mongodb://localhost/test';猫鼬.Promise = global.Promise;mongoose.set('debug', true);const testSchema = 新架构({字段:字符串,其他:字符串,日期:日期});const Test = mongoose.model('Test', testSchema);const log = 数据 =>console.log(JSON.stringify(data, undefined, 2));(异步函数(){const now = Date.now();const 今天 = 现在 - (现在 % (1000 * 60 * 60 * 24));尝试 {const conn = await mongoose.connect(uri);await Promise.all(Object.entries(conn.models).map(([k,m]) => m.remove()));等待 Test.insertMany([...[ ...Array(4)].map((e,i) =>({字段:一个",...(我 === 3) ?{ 其他:最后"}:(我=== 2)?{其他:倒数第二"}:{},日期:新日期(今天+(i * 1000 * 60 * 60 * 24))})),{字段:b",日期:新日期(今天+(5 * 1000 * 60 * 60 * 24))}]);让移除 = 等待 Test.findOneAndDelete({字段:a"},{排序:{日期":-1}});日志({ 删除});让剩余 = 等待 Test.find();日志({剩余});让 next_removed = await Test.findOneAndDelete({字段:a"},{排序:{_id":-1}});日志({ next_removed });让 still_remaining = await Test.find();日志({仍然剩余});猫鼬.disconnect();}赶上(e){控制台错误(e)} 最后 {进程.退出()}})()

这将返回预期的输出:

猫鼬:tests.remove({}, {})猫鼬:tests.insertMany([ { _id: 5b0cb4a60cf8000c7ebd4402, field: 'a', date: 2018-05-29T00:00:00.000Z, __v: 0 }, { _id: 5b0cb4a60cf8000c7ebd4402, field: 'a', date: 2018-05-29T00:00:00.000Z, __v: 0 }, { _id: 5b0cb4a60cf8000c7ebd4402-05-30T00:00:00.000Z, __v: 0 }, { _id: 5b0cb4a60cf8000c7ebd4404,字段:'a',其他:'倒数第二',日期:2018-05-31T00:00:Z }000., { _id: 5b0cb4a60cf8000c7ebd4405, 字段: 'a', 其他: 'last', 日期: 2018-06-01T00:00:00.000Z, __v: 0 }, { _id: 5b0cb8:8040cf, date8040cf, date8040c'-06-03T00:00:00.000Z, __v: 0 } ], {})猫鼬:tests.findOneAndDelete({ field: 'a' }, { sort: { date: -1 } }){已删除":{"_id": "5b0cb4a60cf8000c7ebd4405","字段": "a","其他": "最后","日期": "2018-06-01T00:00:00.000Z",__v":0}}猫鼬:tests.find({}, { 字段:{} }){其余的": [{"_id": "5b0cb4a60cf8000c7ebd4402","字段": "a","日期": "2018-05-29T00:00:00.000Z",__v":0},{"_id": "5b0cb4a60cf8000c7ebd4403","字段": "a","日期": "2018-05-30T00:00:00.000Z",__v":0},{"_id": "5b0cb4a60cf8000c7ebd4404","字段": "a","other": "倒数第二","日期": "2018-05-31T00:00:00.000Z",__v":0},{"_id": "5b0cb4a60cf8000c7ebd4406","字段": "b","日期": "2018-06-03T00:00:00.000Z",__v":0}]}猫鼬:tests.findOneAndDelete({ field: 'a' }, { sort: { _id: -1 } }){next_removed":{"_id": "5b0cb4a60cf8000c7ebd4404","字段": "a","other": "倒数第二","日期": "2018-05-31T00:00:00.000Z",__v":0}}猫鼬:tests.find({}, { 字段:{} }){仍然剩余":[{"_id": "5b0cb4a60cf8000c7ebd4402","字段": "a","日期": "2018-05-29T00:00:00.000Z",__v":0},{"_id": "5b0cb4a60cf8000c7ebd4403","字段": "a","日期": "2018-05-30T00:00:00.000Z",__v":0},{"_id": "5b0cb4a60cf8000c7ebd4406","字段": "b","日期": "2018-06-03T00:00:00.000Z",__v":0}]}

<块引用>

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

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

I want to delete the latest document from my MongoDB in a single query.

I have tried some commands but they doesn't seem to work.

解决方案

The basic operation you are looking for is findOneAndDelete() in mongoose which is an atomic operation returning the "removed" document with the response. This only ever affects a single document and you get the "last" by applying a sort specification in the options.

You basically then have two options for "last", either being by a field containing a BSON "date" property you have stored in the documents which you can sort on:

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

Or by using the _idfield where an ObjectId was used, as without any other intervention this value will "always increase" with every inserted document:

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

That's generally your option if you did not store a field within the document with a BSON Date as a means of determining the "latest inserted" or "last modified". If you want "last modified" then you really have no other option that to record such a BSON date property within the document since the _id itself is immutable and does not change, and at best is a "fallback" for a "created date" when you did not explicitly store any other field to record such information.

A full example follows, which demonstrates adding multiple documents to a collection and then "removing" only the "last" document meeting the supplied query criteria. Both using a stored date and the _id field are demonstrated:

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()
  }

})()

And this returns the expected output of:

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
    }
  ]
}

NOTE: For the actual Node Driver it's findOneAndDelete() is essentially identical and is the actual call made by mongoose to the server, but older versions of mongoose only support findOneAndRemove() which is almost identical in options but instead issues a findAndModify() request through the core API.

From a technical standpoint these are all actually the findAndModify command, however it is generally preferred to use the modern API since the methods have "clarity" in their intended purpose, and also choose reasonable "defaults" to the range of available options to the broader "command" which the server actually processes.

这篇关于在单个查询中从 Mongo DB 中删除最新文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆