Mongoose query, select 10 most recent document without changing order - node.js

I need to select from my messages collection, the 10 most recent messages, and return them as an array form the older to the most recent.
Example : m1, m2, m3, ... [m19, m20, m22] <-- Select last 10 but keep the order.
The slice operator is great because it can take value like -10 and so select 10 last values from an array. The problem is that I want to sort the whole query response, and not a property within the response (slice operator takes 2 arguments, the first one is the path).
Actually what I do is :
.find({ conversation: conversationId })
.sort('-updatedAt')
.limit(10)
.exec(function(err, messages) {
});
But the array it returns contains messages from the most recent to the older.
What can I do to keep the good order, without reverting the whole array after the query execution ? ( messages.reverse(); )

Get 10 latest documents
MySchema.find().sort({ _id: -1 }).limit(10)
Get 10 oldest documents
MySchema.find().sort({ _id: 1 }).limit(10)

You could change the order to ascending(old-to-new) messages and get the last N elements that you need
.find().skip(db.collection.count() - N)
So you will get the most recent messages in ascending orden

Related

mongoose: get documents from to certain position

Currently I working on a news feed and want to fetch more data when the user scrolls down the list. At first I get a specific amount of data from my server sorted by date like this ->
var newsFeed = await NewsFeed.find().sort({createdDate: 'desc'}).limit(parseInt(amount));
When the user know reach the end of the list, I want to load more data by simply increase the amount variable in my api call. With the current call I also get the first elements that I already have. So is there a solution to get like the first 10 documents sorted by date and when from 11 - 20 and so on ?
If your documents are sorted you can use skip.
For example, if you have 10 objects, like this:
{ id:1 }, { id:2 }, { id:3 }, { id:4 } , ... { id:n}
You can query the number of documents you want in this way:
var find = await model.find({}).sort({id:1}).limit(amount)
Then, to get the next values, you can do this query:
find = await model.find({}).sort({id:1}).skip(amount).limit(amount)
The first find (assuming amount is, for example, 2), will return documents wit id 1 and 2.
The second find will return id 3 and 4.
Also, check this stack overflow question and this docs from Mongo.

how to return the latest record by timestamp?

I have a data set that looks similar to this:
{"user":333,"product":943, "rating":2.025743791177902, "timestamp":1481675659}
{"user":333,"product":3074,"rating":2.1070657532324493,"timestamp":1481675178}
{"user":333,"product":3074,"rating":2.108323259636257, "timestamp":1481673546}
{"user":333,"product":943, "rating":2.0211849667268353,"timestamp":1481675178}
{"user":333,"product":943, "rating":2.041045323231024, "timestamp":1481673546}
{"user":333,"product":119, "rating":2.1832303461543163,"timestamp":1481675659}
{"user":333,"product":119, "rating":2.1937538029700203,"timestamp":1481673546}
{"user":111,"product":123, ...
I would like to query all records for a user (e.g. 333), but only return the latest timestamp:
{"user":333,"product":119, "rating":2.1832303461543163,"timestamp":1481675659}
Is this possible with a map/reduce index? If so, how?
Ideally I would also like to sort by the rating value.
If you create a Map function like this
function(doc) {
emit([doc.user, doc.timestamp], null);
}
an index would be created in user & time order.
To return the latest (most recent) timestamp for a given user you can query the index with the following parameters:
startkey=[333,9999999999]
endkey=[333,0]
descending=true
limit=1
We are querying the index in reverse order, starting with the largest timestamp for that user but limiting the result set size to 1 - the newest entry.

using $slice operator i'm not able to get proper set of data ,

I have started creating a small chat application,since im using mongodb i started to implement with $slice for getting only latest 10 messages in my chat history. but the issue is that im not able get the latest set of data{10 messages},(data mismatch happens for every instance) . please any one help me out .
You might need to use a negative value to retrieve the latest elements.
From the $slice docs:
$slice accepts arguments in a number of formats, including negative values and arrays. Consider the following examples:
db.posts.find( {}, { comments: { $slice: 5 } } )
Here, $slice selects the first five items in an array in the comments field.
db.posts.find( {}, { comments: { $slice: -5 } } )
This operation returns the last five items in array.

mongoose limit & nin not working properly

i am trying to limit the number of records returned in a query:
Property.find(searchParams).nin('_id', prop_ids).limit(5).exec(function(err, properties) {
when the first call comes in, i get 5 records back. then i make a second call and pass in an array of ids (prop_ids). This array has all of the ids that were records that were returned in the first call... in this case i get no records back. I have a total of 7 records in my database, so the second call should return 2 records. How should I go about doing this?
I think mongoose might apply the limit before the nin query is applied so you will always just get those five. If it's a type of pagination you want to perform where you get 5 objects and then get 5 others, you can use the option skip instead:
var SKIP = ... // 0, 5, 10...
Property.find(searchParams, null, {
skip: SKIP,
limit: 5,
}, function(err, properties) {
})
This is what I took from your question, maybe you had something other in mind with the nin call?

MongoDB with Node, set starting point and select finite reverse number of records

I'm using mongo as my data store for a list of messages sent. Each message has an id and what I would like to be able to do (as efficiently as possible) is return n number of results starting before a supplied id going in reverse.
So, for example, with a function call like:
getHistory(start, count)
I could supply:
getHistory("a123", 10)
Which would return 10 records prior to the record with 'id="a123"`. Trick is the ID's are GUID and so I can't just increment backward based on that.
This is what I have so far and it's not starting in the correct position:
var cursor = collection.find({id: id}).sort({timestamp: -1}).limit(10)
Not tested, but something along the following lines should work (in mongoose):
collection.find({_id: {$lt: start}}).sort({_id: -1}).limit(10);
This should find all elements before the start id, reverse the order and get the first 10. In other words the last 10 before start.

Resources