MongoDB agregation: get next and previous element [duplicate] - mongodb

I have a blog. On the individual post page I want to display a link to the previous, and if there is one, next post published in the bottom. The link should be the title of the specific post.
How do I do that the simplest way with Mongoose?
My current controller looks like this:
Post.findOne { slug : req.params.slug }, (err, post) ->
res.render "blog/show.jade", locals: title: "This post", post: post
And the schema looks like this:
PostSchema = new Schema(
title:
type: String
required: true
index: true
preamble: String
body: String
slug: String
createdAt: Date
updatedAt: Date
)

So let suppose you have schema like this:
{
_id,
text
}
I suppose that _id is mongo ObjectId, so we it contains post date and i can sort on it
Lets consider that i have opened current post with id equal to ObjectId( "43cc63093475061e3d95369d") (instead of this i will use curId) and i need to know next one and previous. Also lets consider that we need get all posts one by one ordered by created date descending:
Get next post you can like this:
db.posts.find({_id: {$gt: curId}}).sort({_id: 1 }).limit(1)
Get previous post you can like this:
db.posts.find({_id: {$lt: curId}}).sort({_id: -1 }).limit(1)
Few things:
If you don't use mongodb ObjectId above code will not work for you, but you can still use postDate instead of id and current post postDate instead of curId.
Take care about order when getting next/prev posts, to retrieve next post you need sort asc, to retrieve prev post you need sort desc.
I am not familiar with mongoose, so above scripts is mongodb shell scripts.

Find previous item:
Post.findOne({_id: {$lt: curId}}).sort({_id: -1}).exec(cb)
Find next item:
Post.findOne({_id: {$gt: curId}}).sort({_id: 1}).exec(cb)

Related

How do you fetch users posts with accurate sorting order, using mongo db, in a facebook like application

I am building a social media application similar to facebook with mongodb, I will like the users post feeds to be sorted by
if user is following the author of the post
how popular the post is, for example, the number of likes and the number of comments
the location of the user, (if it is same with the author of the post)
sort by the value of (count of "like reaction" for last 6 months - count of value of "sad reaction" for last 6 months)
lastly the time at which the post was created
here is the schema of the database
user: {
_id: mongoId
username: string
location_id: ref location _id
}
post: {
_id: mongoId
content: string
author: ref user _id
}
comment: {
_id: mongoId
content: string
post: ref post _id
author: ref user _id
}
reaction: {
_id: mongoId
type: enum['like', 'love', 'sad']
post: ref post _id
author: ref user _id
}
follow: {
_id: mongoId
follower: ref user _id of the one who is following another
following: ref user _id of the one who is being followed another
}
location: {
_id: mongoId
country: string
}
i will like a mongo query that will fetch this posts in the order of the sort i mentioned, i will really appreciate any help at all, even though not all the sort values can be accomplished, just mention which ones can and how i can achieve that
I have tried using the $sort, $sortByCount, $group $sum and some other aggregate methods, but i am not getting the right order
I am expecting to see the posts fetched in desending order

How to update in nested schema in mongodb?

I am working on meteor. I am trying to make blog with commmenting system.For post insertion my schema is this:
Posts.insert({
post:post,
author:username,
date:date,
createdAt:new Date(),
comment:{
commentBy:'',
commentMsg:''
},
userId:Meteor.userId()
})
At first the comment section will be blank. when user comment on particular post then comment section is filled.
I am trying to update this schema:
Posts.update(thisPost,{$addToSet:{comment.commentedBy:Name,comment.commentMsg:post}});
But its not working.How to do it right way??
for entering multiple comments the field should be an array.
comments:[{
Commentedby:String,
CommentedMsh:string
}]
You can either use $addtoset or $push,
db.update({_id:post._id},{$push:{comments:newComment}})
OR
db.update({_id:post._id}, { $addToSet: { comments : comment });
I think you need to put quotes around any dot references, like this:
Posts.update(thisPost,{$addToSet:{"comment.commentedBy":Name,"comment.commentMsg":post}});
The reason is because if you don't, your compiler will try and do object references locally, which is not what you want, if you pass it as a string, then Mongo will do it as expected.
There are two issues that I could find in your provided information.
First is that the comment property should be an array/collection, so you should initiate it as following (renamed to comments):
Posts.insert({
...
comments:[],
...
})
And second, and most important to answer you question, according to the documentation the first parameter on update should be either a selector, a ObjectID or a string id.
https://docs.meteor.com/api/collections.html#Mongo-Collection-update
So your update should look like this:
var comment = { commentBy: 'user-id', commentMsg: 'le-message' }
Posts.update(post._id, { $addToSet: { comments : comment });

Mongoose find elements with value in subdocuments

My models
ActivityLanguage
language_id: ID
name: String
Activity
price: Int
languages: [ActivityLanguage]
what i want to do is to find the Activities that have an ActivityLanguage with certain language_id.
This works like i need (in mongo):
db.activities.find({"languages.language_id": "59640de1675c1481820a543e" }, {"languages.$": 1})
How can i achieve it in mongoose?
I already tried using:
Activity.find({'languages.language_id': language_id})
and
Activity.find({"languages": {$elemMatch: { language_id: language_id }}})
both of them return an empty array (i already triple checked my database that there are Activities with that condition). I also tried all the answers i found here in StackOverflow without success
How can i achieve it in mongoose?
You can use Mongoose model.populate
From your example:
Activity.
find({}).
populate({
path: 'languages',
model: 'ActivityLanguage',
match: { language_id: ID } //here you define your language_id criteria
}).
exec()

How can I query for a subdocument full of objects in Mongo?

So I have a document with an unknown number of objects in it, each with 2 properties. It's a collection of friend lists, and I'm trying to confirm if someone has a friend with a certain username before I allow a user to send a request. I'm keeping the list of friends in a subdocument, like this:
>>all the _id and other properties<<, "ownerFriends":[{"friendId":"an id goes here", "friendUsername": "username"}, {"friendId":"another id", "friendUsername":"username2"}]
I'm trying to do a query that will return username2 if given that as input, but I don't know how to do that with dot notation because I think you need to know the specific property to look for, and these are heterodox amounts of friend objects in the ownerFriends property.
If you want to select the ownerFriend object that has username as the friendUserName you can use the following selector (assuming your collection is called Friends):
Friends.find({
"ownerFriends.friendUsername": "username2"
}, {
fields: { "ownerFriends.$": 1}
});
You can find a detailed explanation of how to query an array of objects based on a property here:
http://www.curtismlarson.com/blog/2015/08/08/meteor-mongodb-array-property-selector/
In summary you have an object that contains keys, one of whose values is an array of objects. You can perform queries on the arrays using $elemMatch In your case:
MyCollection.find({ ownerFriends: { $elemMatch: { friendUsername: searchString }}});
Although I think you'll need to also query on the current user's _id. Not knowing the details of your collection, I can only speculate with:
MyCollection.find({ userId: Meteor.userId(), ownerFriends: { $elemMatch: { friendUsername: searchString }}});

Mongodb querying document with linked id

I have a document that has an id of another document from a different collection embedded in it.
My desired result is to return (I'm using python and pymongo) the all the fields of the first collection, and all of the friends from the document that was embedded.
I understand mongo doesn't do joins and I understand I'll need to make two queries. I also don't want to duplicate my data.
My question is how to piece the two queries together in python/pymongo so I have one results with all the fields from both documents in it.
Here is what my data looks like:
db.employees
{_id: ObjectId("4d85c7039ab0fd70a117d733"), name: 'Joe Smith', title: 'junior',
manager: ObjectId("4d85c7039ab0fd70a117d730") }
db.managers
{_id: ObjectId("ObjectId("4d85c7039ab0fd70a117d730"), name: 'Jane Doe', title: 'senior manager'}
desired result
x = {_id: ObjectId("4d85c7039ab0fd70a117d733"), name: 'Joe Smith', title: 'junior',
manager: 'Jane Doe' }
Your basically doing something that Mongo does not support out of the box and would actually be more painful than using the two records separately.
Basically (in pseudo/JS code since I am not a Python programmer):
var emp = db.employees.find({ name: 'Joe Smith' });
var mang = db.managers.find({ _id: emp._id });
And there you have it you have the two records separately. You cannot chain as #slownage shows and get a merged result, or any result infact since MongoDB, from one qauery, will actually return a dictionary not the value of the field even when you specify only one field to return.
So this is really the only solution, to get the the two separately and then work on them.
Edit
You could use a DBRef here but it is pretty much the same as doing it this way, only difference is that it is a helper to put it into your own model instead of doing it youself.
If it works it should be something like:
db.managers.find({
'_id' => db->employees->find({ ('_id' : 1),
('_id': ObjectId("4d85c7039ab0fd70a117d733") }))
})
updated