ordering results using mongoose in express - node.js

I'm using mongoose to create and model my document schemas.
I have a user_id attribute on a bunch of different schemas, along with a created_at date attribute on them.
I want to generate a list, ordered by created_at date for display as a feed of recent activity on the user's homepage.
How would I query several different models, and then order these items into an array that I can then pass to my ejs view?

You can sort your mongoose query using the sort function. Here are two examples:
query.sort({ field: 'asc', test: -1 });
or
Person
.find({user_id: 123456})
.sort('-created_at')
.exec(function(err, person) {
// push these results to your array and start another query on a different schema
});

Related

ravendb NodeJS, load related document and create a nested result in a query

I have an index that returns something like this
Company_All {
name : string;
id : string;
agentDocumentId : string
}
is it possible to load the related agent document and then generate a nested result with selectFields and QueryData like this
ICompanyView {
companyName : 'Warner',
user {
documentId : 'A/1'
firstName : 'john',
lastName : 'paul'
}
}
I need something like the below query that obviously doesn't work as I expect:
const queryData = new QueryData(
["name", "agentDocumentId", "agent.firstName", "agent.lastName"],
["companyName", "user.documentId", "user.lastName", "user.firstName"]);
return await session.query<Company_AllResult>({ index: Company_All })
.whereEquals("companyId", request.companyId)
.include(`agents/${agentDocumentId}`) // ????
.selectFields(queryData,ICompanyView)
.single();
Yes, you can do that using:
https://ravendb.net/docs/article-page/5.4/nodejs/indexes/indexing-related-documents
This is called indexing related documents, and is accessible at indexing time, not query time.
Alternatively, you have the filter clause, which has access to the loaded document, but I wouldn't generally recommend doing this.
Generally:
When you query an index, the results of querying the index are the documents from the collection the index was defined on.
Index-fields defined in the index are used to filter the index-query
but the results are still documents from the original collection.
If you define an index that indexes content from a related-document then when making an index-query you can filter the documents by the indexed-fields from the related documents, but the results are still documents from the original collection.
When making an index-query (or any other query) you can project the query results so that Not the full documents of the original collection are returned but some other object.
Now:
To project/get data from the indexed related-document you have 2 options:
Store the index-fields from the related-document in the index.
(Store all -or- specific fields).
This way you have access to that content when making a projection in your query.
See this code sample.
Don't store the index-fields from the related-document,
then you will be able to use the index-fields to filter by in your query,
but to get content you will need to use 'include' feature in your query,
and then use the session.load, which will Not make another trip to the server.
i.e. https://demo.ravendb.net/demos/nodejs/related-documents/query-related-documents

How to sort an array inside a document in mongoose?

In my express app, I have a preference model where users can save their preferences. It has the following structure
{
_id: ...
user: ...
article: [{documentId: ..., addedAt: ...}]
vlogs: [{documentId: ..., addedAt: ...}]
}
In brief, a user will have a single record (document) in preference model that will contain all the vlogs and article that user has added. Each Article/Vlog is an array of objects with a documentId and an addedAt field which holds the date when the article/vlog was added to the user's preference.
When I query this model to fetch a user's preferred vlogs and articles, I have to populate the documentId and then send only and array of populated article/vlog, which I have already done. The problem that I have is with sorting the documents by their addedAt date. How may I do so?
You can use Aggregation pipelining.
Aggregation | MongoDB

Mongodb group by specific field in the collection and also return the count for each

I have collection in mongodb which stores document like the following
ORDERS collection
_id:ObjectId(5f87b9f8f1bfc578dc3d8c9a)
user_id:"5f8465a777b1814c588521e2"
coords:{lat:0,long:0}
price:96
state:"Haryana"
quantity:"1"
timestamp:2020-10-15T02:54:48.104+00:00
status:3
driver_id:"5f7ab962f2bd85066c6f24bd"
monthNumber:9
_id:ObjectId(5f87b9f8f1bfc578dc3d8c9a)
order_id:"200d0019-a4cb-471b-bb70-a22c3056153d"
user_id:"5f8465a777b1814c588521e2"
coords:{lat:0,long:0}
price:96
state:"Haryana"
quantity:"1"
timestamp:2020-10-15T02:54:48.104+00:00
status:3
driver_id:"5f7ab962f2bd85066c6f24bd"
monthNumber:9
_id:ObjectId(5f87b9f8f1bfc578dc3d8c9a)
order_id:"200d0019-a4cb-471b-bb70-a22c3056153d"
user_id:"5f8465a777b1814c588521e2"
coords:{lat:0,long:0}
price:96
state:"Haryana"
quantity:"1"
timestamp:2020-10-15T02:54:48.104+00:00
status:3
driver_id:"5f7ab962f2bd85066c6f24bd"
reviewStatus:2
monthNumber:8
Now what i want is that in frontend i want to group the data and show it according to
"monthNumber"
so that client has idea the how many orders were placed in a particular month (0-Jan... 9-oct)
what i did was i ran a query like
let orders = await db
.collection("orders")
.aggregate({
$group:{
_id:"monthNumber",count:{$sum:1}
}
})
but it gave error of
TypeError: Converting circular structure to JSON
and also i see in console that aggregation cursor was printed instead of actual info.

Maintain a custom order/sort of documents in MongoDB

In my web app XY I'm showing a classic list/table of data (documents) to the user. While all the sort functions provided by MongoDB ( and Mongoose, i'm using Mongoose) are pretty clear to me, I'm not interested in sorting by date or alphabetical order. In my case it would be important to let the user maintain a custom sort as in manually drag/drop items around to set a specific order of the documents (e.g. putting favourites in top of the list ). The UI to do this is a no-brainer but how to actually save the order in the database, brain-freeze.
Problem : How would I go about saving such a custom order of documents ?
What I use : NodeJS / Express / Mongoose (MongoDB)
Ideas
So far I could think of 2 ideas on how to do this.
A : Having an additional key (e.g. orderKey) in the mongoose Schema. Big con : I would need to keep constantly updating all documents orderKeys. Also I would need some sort of auto-increment for new documents.
const mySch = new Schema({
orderKey : { type : Number }
});
B : Creating one Schema/Model only for sorting, with an Array including all documents _ids for example. The order of the elements within the array would be used as reference for the custom order of the documents. Whenever the order changes, this Array would be changed as well.
conts orderSch = new Schema({
orderArray : { type : Array }
});
mongoose.model('Order', orderSch);
/* const customOrder = new Order({
orderArray : [ _id1, _id2, _id3, _id10, _id7, .. ]
}); */
Any more ideas or best practises are highly appreciated !

Mongoose aggregation, how perform 'select as'?

I have just started working with Mongo Db using Mongoose.js library.
I have two schemas, Orders and Payments.
I want to make a simple query to get all orders with property of sum of all payments for that order.
Schemas
Order
{ name : String }
Payment
{ date : Date, order : Schema.ObjectId, sum : Number }
In mysql I would do it this way:
select *,(select SUM(sum) from payments where payments.order = orders.id group by payments.order) as sum from orders
I was looking for aggregation methods to build the query. But all examples I have found is for the single object. I have no trouble to get the sum for single order (using findOne() and aggregation). But how I do it for array of orders?
There is no way to do this with just one query in MongoDB with the schema design you have. Your schema is fine for a relational DB, but it might not be ideal for NoSQL.
With your schema you would have to do two queries:
An aggregation job on payment to sum the payments grouped by order
A a find(),or findOne(), on order to get the name of the order
An alternative schema would be to have just one collection of order documents and storing the payments as sub-documents on the order document, eg. an order would look something like this:
{
name: "Foo"
payments: [ { date: xxxx, sum: 42.00}, { date: yyyy, sum: 12.00} ]
}
Take a look at the Mongo documentation on data models for more: http://docs.mongodb.org/manual/data-modeling/#data-models

Resources