0

I have following code:

.find(callback).limit(limit).sort({ id: -1 });

Which works like a charm, actually. However, few of the collections may have approved field undefined (it may not exist). If so, they should be moved at the end of the list.

Question: Can I just pass to that sort function instead of that object { id: -1 }?

My custom sorting function:

const o = [{
  id: 4,
  approved: true,
}, {
  id: 1,
  approved: true,
}, {
  id: 2,
  approved: true,
}, {
  id: 3,
}];

const r = o.sort((a, b) => {
   return b.approved ? b.id - a.id : b;
});

console.log(r);

Edit: passing a custom function doesnt work, since sort expects a string/object or array.

Akrion
  • 18,117
  • 1
  • 34
  • 54
Patrickkx
  • 1,740
  • 7
  • 31
  • 60
  • You can do this using `aggregate` by projecting a custom value to sort on and then sorting on that. See https://stackoverflow.com/questions/3212919/mongo-complex-sorting – JohnnyHK Aug 16 '18 at 14:19
  • What happens if you [sort](https://docs.mongodb.com/manual/reference/method/cursor.sort/) on `{approved: -1, id: -1}`? That should work given that undefined fields compare smaller than booleans. – Bergi Aug 16 '18 at 18:30
  • Confirmed `db.getCollection('').find().sort({ approved: -1, id: -1 })` returned what the OP wants. – Akrion Aug 17 '18 at 01:08
  • @Akrion It did move the elements without `approved` at the end, however the elements with `approved` field are not sorted correctly. Do you have any ideas why? – Patrickkx Aug 17 '18 at 18:26
  • @Patrickkx based on my test all objects with no `approved` went on the bottom. Above them are all objects with `approved` false and then the remaining with `approved: true`. Is this not the desired output? – Akrion Aug 17 '18 at 18:34
  • @Akrion First should go elements with `approved = true` and they should be sorted by `date` (I used `id` because its easier to show the problem, but in real im sorting them by `date`) AND THEN should go elements with `approved = false` and also should be sorted by `id` (`date`) – Patrickkx Aug 17 '18 at 18:36
  • 1
    OK got it. You should have specified all that in the question. It is a little guess work to get to here – Akrion Aug 17 '18 at 18:38
  • @Akrion Hello, did you find any solution on it? – Patrickkx Aug 18 '18 at 10:20

1 Answers1

1

No, that's not a consistent comparison function. You can't return the b object, and you should check for only b.approved.

Instead, use

arr.sort((a, b) => {
    return !!b.approved - !!a.approved || b.id - a.id;
});
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    This doesn't really answer the question as you can't use a JS function for sorting with mongodb regardless. – JohnnyHK Aug 16 '18 at 14:17
  • @JohnnyHK Oh, you're probably right. I don't know mongodb, but the OP talked about functions and used arrays in his question… But surely you can make mongodb sort by `approved` and then by `id`? – Bergi Aug 16 '18 at 15:16
  • Sure, but the OP is looking to customize the standard sorting you'd get with that. – JohnnyHK Aug 16 '18 at 15:56
  • Dear Bergi, your solution moved the elements without `approved` down the list, however these elements WITH approve are not sorted properly :( just random... – Patrickkx Aug 17 '18 at 18:31
  • Some of them got `approved = true` and some of them got `approved = false`. The solution u gave me works fine, I mean, it pushes the elements with `approved = false` down the list, but elements with `approved = true` are not sorted properly (they should be sorted by `id` (in real it's `date`, but it was easier for me to reproduce the problem with just `id`)) – Patrickkx Aug 18 '18 at 10:07
  • Im talking about solution `{approved: -1, id: -1}` – Patrickkx Aug 18 '18 at 10:08
  • @Patrickkx That's weird, MongoDB docs claim that it would sort all values with the same `approved` value by `id` with that solution. – Bergi Aug 19 '18 at 13:48
  • Does lack of `approved` field make a problem? Because it's not like approved can be true or false. It's `approved = true` or there's no approved at all (the field just do not exist) – Patrickkx Aug 19 '18 at 15:09
  • @Patrickkx I don't think that matters. MongoDB can compare non-existing fields just fine, treating them as nil. – Bergi Aug 19 '18 at 15:35