MongoDB distinct function and alphabetical sorting - node.js

I have a simple question on sorting results from the distinct command in mongodb.
I'm using Monk in my NodeJS app to get categories from my simple DB:
db.getCollection('citazioni').distinct('category')
But how can I apply a sorting function like I successfully do when I find documents with:
collection.find({}, {sort: {'_id': -1}} ??
Thank you!

Monk has support for the underlying node.js native driver distinct() method and its signature is
Collection.prototype.distinct = function (field, query, fn) { ... }
As you can see from that commit that it implements the distinct method of the node native driver collection type via the .col accessor on the selected collection object:
this.col.distinct(field, query, promise.fulfill);
Thus you can implement it together with the native JavaScript sort() method as follows :
// Perform a distinct query against the category field
db.getCollection('citazioni').distinct('category', function(err, categories) {
console.log(categories.sort());
}

Concatenate it:
db.getCollection('citazioni').distinct('category').sort({'_id': -1})
In a Node app with Mongoose:
collection.distinct('citazioni').sort({'_id': -1}).exec(function(e2, categories) {
... etc ...
}

Related

mongodb mapReduce for sailsjs

I am trying to sort two Collections based on creation time. I searched through stackoverflow and found the solution which was mentioned this link http://tebros.com/2011/07/using-mongodb-mapreduce-to-join-2-collections/ that is you mapReduce the collections to another Collection named joined and later sort using a given parameter(creation time in my case).
The problem now is how we mapReduce in Sailsjs, I have already referred this http://sailsjs.org/documentation/reference/waterline-orm/models/native where we have this code.
Pet.native(function(err, collection) {
if (err) return res.serverError(err);
collection.find({}, {
name: true
}).toArray(function (err, results) {
if (err) return res.serverError(err);
return res.ok(results);
});
});
the collection parameter in the callback carries properties such as find, create and so on. Does collection parameter have the function mapReduce ? Since it was undefined in my case.
Is there any way to mapReduce in Sailsjs apart from opening a raw connection and using the connection opened in config/connection.js(default connection).
Or better any way to sort 2 Collections in mongodb based on a particular attribute?
Sails v0.11.5, node v0.4.4.2
Thanks.

Find documents where object id $in sub array using sails.js and mongodb

So I have a model that is for a recipe where it has a relation of 'ingredients' and that is just an array of ObjectIds. When I run the following query on mongo shell it works fine and returns all my data.
Example model :
{
"name": "...",
"_id": ObjectId("530ca903746515c0161e6b9f"),
"ingredients": [
ObjectId("53069363ff7447a81a3a7a1d"),
ObjectId("53069363ff7447a81a3a7a17")
]
}
Query:
db.drink.find({"ingredients":{"$in":[ObjectId("53069364ff7447a81a3a7a87"), ObjectId("530fb948c1a3ff480d58e43c")]}});
Using sails.js though their waterline orm, they don't really have a way to query this though or at least through any possible google search that I can find. So trying to use the native driver I have something like the following -
var ings = new Array();
for (var i in req.body) {
ings.push(new ObjectID(req.body[i].toString()));
}
Drink.native(function(err, collection){
if(err){
return res.send(err, 500);
} else {
collection.find({"ingredients":{"$in":ings}}).toArray(function(err, data){
console.log(data);
});
}
});
The thing is the data array returned in the callback is always empty. If I check the 'ings' array it is an array of objectids so I am not sure why it won't return any data. If I remove the json object in the 'find' function it does return everything. Anyone have any idea how to make this query return data when using sails.js?
The code above actually is working it was an internal data issue on the mongodb where IDs were not matching between relations. When the relations were rebuilt all is working as it should be.

How to sort a collection by date in MongoDB?

I am using MongoDB with Node.JS. I have a collection which contains a date and other rows. The date is a JavaScript Date object.
How can I sort this collection by date?
Just a slight modification to #JohnnyHK answer
collection.find().sort({datefield: -1}, function(err, cursor){...});
In many use cases we wish to have latest records to be returned (like for latest updates / inserts).
db.getCollection('').find({}).sort({_id:-1})
This will sort your collection in descending order based on the date of insertion
Sorting by date doesn't require anything special. Just sort by the desired date field of the collection.
Updated for the 1.4.28 node.js native driver, you can sort ascending on datefield using any of the following ways:
collection.find().sort({datefield: 1}).toArray(function(err, docs) {...});
collection.find().sort('datefield', 1).toArray(function(err, docs) {...});
collection.find().sort([['datefield', 1]]).toArray(function(err, docs) {...});
collection.find({}, {sort: {datefield: 1}}).toArray(function(err, docs) {...});
collection.find({}, {sort: [['datefield', 1]]}).toArray(function(err, docs) {...});
'asc' or 'ascending' can also be used in place of the 1.
To sort descending, use 'desc', 'descending', or -1 in place of the 1.
Sushant Gupta's answers are a tad bit outdated and don't work anymore.
The following snippet should be like this now :
collection.find({}, {"sort" : ['datefield', 'asc']} ).toArray(function(err,docs) {});
This worked for me:
collection.find({}, {"sort" : [['datefield', 'asc']]}, function (err, docs) { ... });
Using Node.js, Express.js, and Monk
collection.find().sort('date':1).exec(function(err, doc) {});
this worked for me
referred https://docs.mongodb.org/getting-started/node/query/
With mongoose it's as simple as:
collection.find().sort('-date').exec(function(err, collectionItems) {
// here's your code
})
Additional Square [ ] Bracket is required for sorting parameter to work.
collection.find({}, {"sort" : [['datefield', 'asc']]} ).toArray(function(err,docs) {});
if your date format is like this : 14/02/1989 ----> you may find some problems
you need to use ISOdate like this :
var start_date = new Date(2012, 07, x, x, x);
-----> the result ------>ISODate("2012-07-14T08:14:00.201Z")
now just use the query like this :
collection.find( { query : query ,$orderby :{start_date : -1}} ,function (err, cursor) {...}
that's it :)
With mongoose I was not able to use 'toArray', and was getting the error: TypeError: Collection.find(...).sort(...).toArray is not a function.
The toArray function exists on the Cursor class from the Native MongoDB NodeJS driver (reference).
Also sort accepts only one parameter, so you can't pass your function inside it.
This worked for me (as answered by Emil):
collection.find().sort('-date').exec(function(error, result) {
// Your code
})

How to get array of json objects rather than mongoose documents

When I do the .find operation like the following:
Collection.find({name: 'Erik'}, function (err, docs) {
// do momething
});
'docs' variable is populated with an array of fully functional mongoose documents. But I need to get an array of pure JSON objects.
I know I can loop through the 'docs' array by forEach and get an objects by using .toJSON() method. Does mongoose support the feature, I'm interested?
If you're using Mongoose 3.x you can use the lean query option to do this:
Collection.find({name: 'Erik'}).lean().exec(function (err, docs) {
// docs are plain javascript objects instead of model instances
});
.exec(function(err, docs){
docs= docs.map(o => o.toObject());
This will include virtuals and getters
Map through results and convert each to JS object:
const result = await model.find({some: 'query'});
return result.map((r) => r.toObject());

Can't I use an object to query in mongoose?

Ihave a problem when i use an object as criteria when querying in mongoose.
var id = {
cid: 111,
vid: 222,
pid: 333
};
// the following doesn't work at all
Category.find({id: id}, function(err, docs) {
//----returns nothing.
});
// while
Category.find({'id.pid': id.pid, 'id.cid': id.cid,'id.vid': id.vid}, function(err, docs) {
//----returns some docs.
});
// does work`
Is this a problem or a feature?
I don't think querying with an object in that way (nested-object format) works with mongoose, because the underlying driver (mongo-node-native) doesn't support it yet.
If you are always querying on fields id.cid, id.pid, and id.vid, you should make a compound index over all of them - creating separate indexes for each one will not help as much, because the query can only use 1 index at a time during execution.

Resources