简体   繁体   中英

Join two collections and sort them in Mongoose

I have two separate collections, suppose news and pictures . Both collections have a creationDate field that holds a datetime of records creation time.

What I want is to select last 10 records from both collections, join all records (now the list has 20 records) and then sort all records by creationDate field. How it's possible in Mongoose?

Well what you are asking for is essentially a client side operation, and you really only want at most 20 records to sort so that should not be a problem.

The async.concat method should help a little here:

async.concat([News,Picture],function(model,callback) {
  // Get the last 10 results from each collection
  var query = model.find({}).sort({ "creationDate": -1 }).limit(10);
  query.exec(function(err,docs) {
    if (err) throw err;
    callback(err,docs);
  });
},
function(err,result) {
  if (err) throw err;
  // results are merged, now sort by date
  result = result.sort(function(a,b) {
    return (a.creationDate < b.creationDate) 
      ? 1 : (a.creationDate > b.creationDate) ? -1 : 0;
  });
  console.log(result);

});

So really you are just "merging" two arrays, but coding it that way simplifies things.


An end to end listing to clarify the usage here. This sets up some documents for each model before running the code as shown above:

var async = require('async'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/series');

var newsSchema = new Schema({
  type: { type: String, default: "News" },
  index: Number,
  creationDate: { type: Date, default: Date.now }
});

var pictureSchema = new Schema({
  type: { type: String, default: "Picture" },
  index: Number,
  creationDate: { type: Date, default: Date.now }
});

var News = mongoose.model( "News", newsSchema );

var Picture = mongoose.model( "Picture", pictureSchema );

async.series(
  [
    // Clean existing
    function(callback) {
      async.each([News,Picture],function(model,callback) {
        model.remove(function(err) {
          if (err) throw err;
          callback();
        });
      },function(err) {
        callback();
      });
    },

    // Insert 20 of each
    function(callback) {
      console.log("inserting");
      var count = 0;
      async.whilst(
        function() { return count < 20 },
        function(callback) {
          count++;
          async.eachSeries([News,Picture],function(model,callback) {
            var doc = new model({ index: count });
            setTimeout(function() {
              doc.save(function(err) {
                if (err) throw err;
                callback();
              });
            }, 20);
          },function(err) {
            callback();
          });
        },
        function(err) {
          callback();
        }
      );
    }
  ],
  function(err) {
    console.log("listing");

    // Get the last 10 of each
    async.concat([News,Picture],function(model,callback) {
      var query = model.find({}).sort({ "creationDate": -1 }).limit(10);
      query.exec(function(err,docs) {
        if (err) throw err;
        callback(err,docs);
      });
    },
    function(err,result) {
      if (err) throw err;

      // result is merged via "concat" now sort it.
      result = result.sort(function(a,b) {
        return (a.creationDate < b.creationDate)
          ? 1 : (a.creationDate > b.creationDate)
          ? -1 : 0;
      });
      console.log(result);
      mongoose.disconnect();
    });
  }
);

Output is somewhere along these lines:

[ { _id: 53c79f4b7daf2d676ff0f185,
    index: 20,
    __v: 0,
    creationDate: Thu Jul 17 2014 20:02:51 GMT+1000 (EST),
    type: 'Picture' },
  { _id: 53c79f4b7daf2d676ff0f184,
    index: 20,
    __v: 0,
    creationDate: Thu Jul 17 2014 20:02:51 GMT+1000 (EST),
    type: 'News' },
  { _id: 53c79f4b7daf2d676ff0f183,
    index: 19,
    __v: 0,
    creationDate: Thu Jul 17 2014 20:02:51 GMT+1000 (EST),
    type: 'Picture' },
  { _id: 53c79f4b7daf2d676ff0f182,
    index: 19,
    __v: 0,
    creationDate: Thu Jul 17 2014 20:02:51 GMT+1000 (EST),
    type: 'News' },
  { _id: 53c79f4b7daf2d676ff0f181,
    index: 18,
    __v: 0,
    creationDate: Thu Jul 17 2014 20:02:51 GMT+1000 (EST),
    type: 'Picture' },
  { _id: 53c79f4b7daf2d676ff0f180,
    index: 18,
    __v: 0,
    creationDate: Thu Jul 17 2014 20:02:51 GMT+1000 (EST),
    type: 'News' },
  { _id: 53c79f4b7daf2d676ff0f17f,
    index: 17,
    __v: 0,
    creationDate: Thu Jul 17 2014 20:02:51 GMT+1000 (EST),
    type: 'Picture' },
  { _id: 53c79f4b7daf2d676ff0f17e,
    index: 17,
    __v: 0,
    creationDate: Thu Jul 17 2014 20:02:51 GMT+1000 (EST),
    type: 'News' },
  { _id: 53c79f4b7daf2d676ff0f17d,
    index: 16,
    __v: 0,
    creationDate: Thu Jul 17 2014 20:02:51 GMT+1000 (EST),
    type: 'Picture' },
  { _id: 53c79f4b7daf2d676ff0f17c,
    index: 16,
    __v: 0,
    creationDate: Thu Jul 17 2014 20:02:51 GMT+1000 (EST),
    type: 'News' } ]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM