Home Journey to understanding mongoose findOne().sort()
Post
Cancel

Journey to understanding mongoose findOne().sort()

Why Sort in findOne?

While listening to a lecture, I came across the following code snippet:

1
const maxOrderByUserId = await Todo.findOne().sort("-order").exec();

This code retrieves the data with the highest “order” value by sorting in descending order based on the “order” field.

But I’ve read it left->right in order so far, so I really didn’t understand findOne() You’re pulling one out, but you’re aligning it from there?

So, I decided to experiment with the following code:

1
const maxOrderByUserId = await Todo.sort("-order").findOne().exec();

But it resulted in an error:

1
TypeError: Todo.sort is not a function

Cursor…?

Upon researching, I found that in Mongoose, the sort() method should be preceded by a cursor value. (Source: Mongoose Query Sort Documentation)

It seems that find() typically returns a cursor value. (Source: Mongoose Aggregate Cursor Documentation)

Understanding what exactly a cursor is proved to be difficult for me…

Anyway, it seems that the sort should come after the cursor value.

How about using find, sort, and limit instead?

This led me to another curiosity: since findOne() is used to retrieve a single item, wouldn’t using find() with limit(1) achieve the same result?

1
const maxOrderByUserId = await Todo.find().sort("-order").limit(1).exec();

However, this also resulted in an error:

1
ValidationError: Todo validation failed: order: Cast to Number failed for value "NaN" (type number) at path "order"

The maxOrderByUserId.order value turned out to be undefined instead of a number.

I couldn’t understand why…

In the original lecture code, the type was correctly detected as a number:

1
2
3
4
5
const maxOrderByUserId = await Todo.find();
console.log(typeof maxOrderByUserId.order); // undefined

const maxOrderByUserId = await Todo.findOne();
console.log(typeof maxOrderByUserId.order); // number

What a fool I am!

I couldn’t understand it, so I asked around…..

The find() method retrieves an array of objects, even if it is limited to only one item. So, even when limiting the result to one item, it will still be wrapped in an array and accessible at index 0.

To access the value at index 0, you can use parentheses to wrap the variable name, or access it directly using test[0].order.

By doing so, the type will be correctly detected as a number. 🙂

Oh…?

1
2
const maxOrderByUserId = await Todo.find();
console.log(typeof maxOrderByUserId[0].order); // number

Oh…?

Wow, I was really being foolish…

Conclusion

1
2
const maxOrderByUserId = await Todo.find().sort("-order").limit(1).exec();
const maxOrderByUserId = await Todo.findOne().sort("-order").exec();

These two code snippets achieve the same result. The time it takes to execute them will likely be similar.
Let’s use something that suits our taste…

This post is licensed under CC BY 4.0 by the author.

Cookie and Session

What is middleware?