Order and limit results in a query with a callback

2020-07-07 04:47发布

问题:

Using Mongoose, I'd like to make a query with MongoDB and order and limit the results I get. I am doing this with Node.js so I am using callbacks.

So far, I have managed to order my results like this:

  myModel.find({ $query: {}, $orderby: { created_at : -1 }}, function (err, items) {
    callback( null, items )
  });  

How can I limit the results I get selecting and index and the number of items I want to get?

回答1:

Using mongodb native: http://mongodb.github.io/node-mongodb-native/api-generated/collection.html#find

myModel.find(filter)
            .limit(pageSize)
            .skip(skip)
            .sort(sort)
            .toArray(callback);

You can also specify the items in your query:

myModel.find(filter, {sort: {created_at: -1}, limit: 10}, function(err, items){

});

There is no $orderby in node mongodb native, so I'm not sure what library or other tool you're using.

...

Now that you've clarified Mongoose (which in general I recommend against):

myModel.find(filter).limit(10).exec(function(err, items){
//process
});


回答2:

To sort documents, we can apply sort on a cursor object. To enforce order of sort, instead of passing an object, we need to pass an array to the sort method.


var MongoClient = require('mongodb').MongoClient,
  commandLineArgs = require('command-line-args'),
  assert = require('assert');


var options = commandLineOptions();


MongoClient.connect('mongodb://localhost:27017/crunchbase', function(err, db) {

  assert.equal(err, null);
  console.log("Successfully connected to MongoDB.");

  var query = queryDocument(options);
  var projection = {
    "_id": 0,
    "name": 1,
    "founded_year": 1,
    "number_of_employees": 1
  };

  var cursor = db.collection('companies').find(query);
  cursor.project(projection);
  cursor.limit(options.limit);
  cursor.skip(options.skip);
  cursor.sort([
    ["founded_year", 1],
    ["number_of_employees", -1]
  ]);

  var numMatches = 0;

  cursor.forEach(
    function(doc) {
      numMatches = numMatches + 1;
      console.log(doc.name + "\n\tfounded " + doc.founded_year +
        "\n\t" + doc.number_of_employees + " employees");
    },
    function(err) {
      assert.equal(err, null);
      console.log("Our query was:" + JSON.stringify(query));
      console.log("Documents displayed: " + numMatches);
      return db.close();
    }
  );

});

function queryDocument(options) {

  console.log(options);

  var query = {
    "founded_year": {
      "$gte": options.firstYear,
      "$lte": options.lastYear
    }
  };

  if ("employees" in options) {
    query.number_of_employees = {
      "$gte": options.employees
    };
  }

  return query;

}


function commandLineOptions() {

  var cli = commandLineArgs([{
    name: "firstYear",
    alias: "f",
    type: Number
  }, {
    name: "lastYear",
    alias: "l",
    type: Number
  }, {
    name: "employees",
    alias: "e",
    type: Number
  }, {
    name: "skip",
    type: Number,
    defaultValue: 0
  }, {
    name: "limit",
    type: Number,
    defaultValue: 20000
  }]);

  var options = cli.parse()
  if (!(("firstYear" in options) && ("lastYear" in options))) {
    console.log(cli.getUsage({
      title: "Usage",
      description: "The first two options below are required. The rest are optional."
    }));
    process.exit();
  }

  return options;

}


One thing to notice is the order in which MongoDB applies skip, limit and sort

  • sort
  • skip
  • limit

There's also a possibility that we can sort data on the MongoDB side as well, provided that we've setup the indexing.

Notice that MongoDB driver will send a query when we call a cursor method passing a callback function to process query results.