Monday 4 May 2015

MongoDB M101N Final Exam Question 4

Question 4:

For this problem, you will be implementing the functionality needed to "like" a comment in the blog.
First, download and unpack the blog solution handout from here
Next, find the "XXX" in HomeController.cs. This is where you will need to code in the ability to "like" a comment.
When you are done, the following functionality will be in place:

  • When you are logged in, and you view a post in its own page (/Home/Post/<post_id>), each post will have a number of "Likes".
  • When you click on the "Likes" button, it gets incremented by one.
  • You can like a comment as many times as you wish; each click will increment it by one.
  • You can even like your own comments.
In your "blog.posts" documents, the "Comments" subdocuments will each contain a "Likes" field. Its value will be a number, and that number will be the number of "Likes" for that comment. Here is an example:


{
 "_id" : ObjectId("552a32e84a01d700485c6475"),
 "Author" : "Bender",
 "Title" : "Announcing my Blog",
 "Content" : "This is my blog.",
 "Tags" : [
  "announcements",
  "benderIsGreat"
 ],
 "CreatedAtUtc" : ISODate("3015-04-14T23:34:00.598Z"),
 "Comments" : [
  {
   "Author" : "Bender",
   "Content" : "Another job well done!",
   "CreatedAtUtc" : ISODate("3015-04-14T23:34:17.430Z"),
   "Likes" : 2
  }
 ]
} 
 

Solution:

Here is Comment Like action code to achieve above functionality.

     [HttpPost]
        public async Task<ActionResult> CommentLike(CommentLikeModel model)
        {
            if (!ModelState.IsValid)
            {
                return RedirectToAction("Post", new { id = model.PostId });
            }

            var blogContext = new BlogContext();

            // XXX WORK HERE
            var fieldName = string.Format("Comments.{0}.Likes", model.Index);
           
            UpdateDefinition<Post> updateDef = Builders<Post>.Update.Inc(fieldName, 1);

            await blogContext.Posts.UpdateOneAsync(x => x.Id == model.PostId, updateDef);

           
            return RedirectToAction("Post", new { id = model.PostId });
        }

18 comments:

  1. Hi Mayur,
    Getting error while executing this code ..Let me know if this was completed successfully .

    ReplyDelete
    Replies
    1. Hi Nilesh,

      What error are you getting? Can you please post stack trace of your exception?

      Regards,
      Mayur Patel

      Delete
  2. Hi Marur,

    No Traces as it goes from MongoProc.Getting error with following pop up message:

    Failed to test assignment. Please try again
    Reason:
    413 Request Entity Too Large

    413 Request Entity Too Large
    nginx/1.1.19

    ReplyDelete
    Replies
    1. Hi Nilesh,

      Based on error, I think this happens because the Index action in HomeController tries to get all tags of all posts - "you can review the code, where you will find use of Unwind for tags, which result in data explosion and request entiry becomes too large".

      Soln. -- Try by giving "Limit(some small number)" on the query that returns all tags.

      Hope that work,

      Thanks
      Mayur Patel

      Delete
    2. I got the same error. But giving "Limit(some small number)" on the query that returns all tag worked. Thank you!!

      Delete
    3. Thanks man, limit the result was a easy solution

      Delete
  3. It is just update we are doing in above code...have you changed anything in web.config ? like increase limit of request. i tried that also but it fails...

    var fieldName = string.Format("Comments.{0}.Likes", model.Index);
    UpdateDefinition updateDef = Builders.Update.Inc(fieldName, 1);
    string postid= model.PostId;
    await blogContext.Posts.UpdateOneAsync(x => x.Id ==postid, updateDef);

    ReplyDelete
    Replies
    1. I faced the same issue while working on this problem. I gave Limit on tags fetching code and it worked for me.

      Other solution is - remove all documents from posts collection and let MongoProc create docs on its own to test your code.

      Delete
  4. Other solution is - remove all documents from posts collection and let MongoProc create docs on its own to test your code...Worked for me....Thank you so much for help..keep good work...All the best

    ReplyDelete
  5. Hi Marur,
    You said: "download and unpack the blog solution handout".
    Where to find "blog solution handout"?
    Tthanks

    ReplyDelete
    Replies
    1. Hi AdriaSoft,
      Thanks for your input. I've updated blog.
      You can download handout from below link,
      https://drive.google.com/open?id=0B1g8hUR0YDovRVpKYW1JanVTTWc

      Mayur

      Delete
  6. very helpful. Thanks you all guys..
    Best Answer (As mayur said): remove all documents from posts collection and let MongoProc create docs on its own to test your code.

    ReplyDelete
  7. Hello Mayur.. Can You provide whole maven project with changes..

    ReplyDelete
    Replies
    1. Hi tarang,

      Currently I don't have the whole project with changes, but you can let us know your issues, I or other members will try to help you out.

      Thanks

      Delete
  8. Thanks Mayur. Your trick to limit tags worked for me. Here is the snippet. (added second last line + your sample code at XXX). Thanks Man !

    var tags = await blogContext.Posts.Aggregate()
    .Project(x => new { _id = x.Id, Tags = x.Tags })
    .Unwind(x => x.Tags)
    .Group("{ _id: '$Tags', Count: { $sum: 1 } }")
    .Limit(10)
    .ToListAsync();

    ReplyDelete
  9. Did anyone got this error?
    Expected to find the 'Comments.0.Likes' field of the 'blog.posts' document with _id ObjectId(''), but got a key error instead. You may need to change your schema to get this to work. You cannot pass until this is corrected.

    ReplyDelete