Removing Latest document from Mongo DB in single query

别说谁变了你拦得住时间么 提交于 2020-01-11 13:34:25

问题


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.


回答1:


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.




回答2:


very simple :

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


来源:https://stackoverflow.com/questions/50568108/removing-latest-document-from-mongo-db-in-single-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!