How can i paginate an array of a document using node and mongoose or mongo? - node.js

{
"_id" : ObjectId("5f0083848f162b38900dc113"),
"isEmailVerified" : false,
"isProfileSetup" : true,
"my_events" : [
ObjectId("5f005a63b5524eb74813de11"),
ObjectId("5f005a5bb5524eb74813de0c"),
ObjectId("5f017dfcf8e6d8615cddfd6f")
]
}
I have this document in user's collection and i am trying to paginate the array my_events only. I am sorry if this is a stupid question.
Firstly is this possible to paginate this array without event fetching it completely from the db and if yes please share the way here.
{{url_local}}/api/event?user_id=5f0083848f162b38900dc113&page=1&limit=2
Above call should find the user with mentioned user_id and should return only these values :-
ObjectId("5f005a63b5524eb74813de11"),
ObjectId("5f005a5bb5524eb74813de0c")
And,
{{url_local}}/api/event?user_id=5f0083848f162b38900dc113&page=2&limit=2
it should return this :-
ObjectId("5f017dfcf8e6d8615cddfd6f")

This can be achieved with aggregation in MongoDB, pls check https://docs.mongodb.com/manual/reference/operator/aggregation/arrayElemAt/
But in general, the advantage of paging will be lost as aggregations are heavy on the database, you should consider to change the document structure and create a collection for subdocuments and add a reference to your parent document if you can.

Related

Struggling with Mongoose query operator syntax

sorry for the noob question.
I'm trying to write the CRUD endpoints for a Friendship model, which holds two users' IDs.
To create a Friendship the first thing I want to do is check if there is already an instance of that model, which would hold both IDs in any given order, so I wrote:
Friendship.findOne.all({users: [user1.id, user2.id]})
.then(.....
But the server responds with a 500 error: Friendship.findOne.all is not a function
What would be the proper way to do this?
I am assuming that you want to check if both id records/documents are present in your collection or not so for that you use $in operator like this
Friendship.find({id: {$in : [user1.id, user2.id]} })
.then(.....
This will return an array of records if any of id records will be present. And it will return empty array if non of the id records will present in your db

mongoose query using sort and skip on populate is too slow

I'm using an ajax request from the front end to load more comments to a post from the back-end which uses NodeJS and mongoose. I won't bore you with the front-end code and the route code, but here's the query code:
Post.findById(req.params.postId).populate({
path: type, //type will either contain "comments" or "answers"
populate: {
path: 'author',
model: 'User'
},
options: {
sort: sortBy, //sortyBy contains either "-date" or "-votes"
skip: parseInt(req.params.numberLoaded), //how many are already shown
limit: 25 //i only load this many new comments at a time.
}
}).exec(function(err, foundPost){
console.log("query executed"); //code takes too long to get to this line
if (err){
res.send("database error, please try again later");
} else {
res.send(foundPost[type]);
}
});
As was mentioned in the title, everything works fine, my problem is just that this is too slow, the request is taking about 1.5-2.5 seconds. surely mongoose has a method of doing this that takes less to load. I poked around the mongoose docs and stackoverflow, but didn't really find anything useful.
Using skip-and-limit approach with mongodb is slow in its nature because it normally needs to retrieve all documents, then sort them, and after that return the desired segment of the results.
What you need to do to make it faster is to define indexes on your collections.
According to MongoDB's official documents:
Indexes support the efficient execution of queries in MongoDB. Without indexes, MongoDB must perform a collection scan, i.e. scan every document in a collection, to select those documents that match the query statement. If an appropriate index exists for a query, MongoDB can use the index to limit the number of documents it must inspect.
-- https://docs.mongodb.com/manual/indexes/
Using indexes may cause increased collection size but they improve the efficiency a lot.
Indexes are commonly defined on fields which are frequently used in queries. In this case, you may want to define indexes on date and/or vote fields.
Read mongoose documentation to find out how to define indexes in your schemas:
http://mongoosejs.com/docs/guide.html#indexes

How to select documents on a collection with unique field in mongodb and meteor?

How to select documents in a collection with a unique field in MongoDB?
I have this document schema:
{
_id: someid,
createdAt: new Date(),
message: somemessage,
eadd: eadd
}
I would like to get recent messages with unique email address. So the output will be recent messages per email address.
I don't know how to use Group by - can I use it here?
to get aggregation in Meteor, you'll have add a package. e.g. meteorhacks:aggregate
c.f. https://themeteorchef.com/tutorials/aggregations-in-mongodb
You will have to use the mongo aggregate function
db.messages.aggregate(
[
{
$group : {
_id : "$eadd"}
}
]);
Just include the fields you want to show
You can try http://grapher.cultofcoders.com/ package. It will allow you to create relationships between your mongo collections. You will use links to create them and you can filter your requests to the database, pass parameters and more.
To install it
meteor add cultofcoders:grapher
Documentation can be found here: http://grapher.cultofcoders.com/

Autoconvert `_id` to `ObjectID`

Is there a way to tell the native MongoDB driver for NodeJS to automatically convert the contents of an _id field into an ObjectID?
Say, in this situation:
db.collection("collection").updateOne({_id: data._id}, data)
It's not that data._id = ObjectID(data.id) is hard, but it's another thing to miss each and every time.
There is no way to do that natively. You can make some function for wrapping your mongo queries where you will check params and if it's "_id" parse it to ObjectId.

How to properly use 'exist' function in mongodb like in sql?

I'm using Node.js + mongodb. I have few documents in my collection and i want to know does my collection have any document matched my condition. Of course i can simply use
myModel.find({ myField: someValue }) and check is anything comes or not. But i want to use solution like sql provides exists keyword? Help me, please
Edit: my bad. I forget to tell that "performance first".
MongoDB's $exists actually doesn't help you very much to find out if a certain document exists in your collection. It is used for example to give you all documents that have a specific field set.
MongoDB has no native support for an sql like exists. What you can use, however, is myModel.findOne({ myField: someValue }) and then check if it is null.
To enhance performance you can tell MongoDB to only load the object id via projection, like this:
myModel.findOne({ myField: someValue }, {_id: 1})
There is an exist mechanism in mongodb, I'll demonstrate a sample below.
For example below, I'm looking for records that have tomato.consensus fields and that it's empty, so I can delete them or avoid them. In case I was looking for "tomato.consensus": Dublin, I'd change Null to Dublin, to match that.
I hope this is helpful, if not fire away any questions
tomato
----consensus
db.movieDetails.updateMany({$and: [
{"tomato.consensus": {$exists: true} },
{"tomato.consensus": null} ] },
]})

Resources