Show users who liked a post from 2 different collections in Meteor

How do I retrieve a list of users who have "liked" this post from a collection and display it in a template?

Collections:

likes: {
    "_id": 1234,
    "userId": "1dsaf8sd2",
    "postId": "123445"
}, {
    "_id": 1235,
    "userId": "23f4g4e4",
    "postId": "123445"
}

users: {
    "_id": 1 dsaf8sd2,
    "profile": {
        "name": "Bob",
        "details": "Cool sentence about Bob."
    }

}, {
    "_id": 23 f4g4e4,
    "profile": {
        "name": "Sam",
        "details": "Cool sentence about Sam."
    }

}

Publish:

Meteor.publish('likes', function(postSlug) {
    check(postSlug, Object);

    // find the post with matching slug and get its id
    var postId = Posts.findOne({
        slug: postSlug
    }, {
        _id: 1
    });

    // find all users who liked this post
    var data = Likes.find({
        postId: postId
    }).forEach(function(doc) {
        return Meteor.users.find({
            _id: doc.userId
        });
    });

    if (data) {
        return data;
    }
    return this.ready();
});

Helper for template:

Template.listLikers.helpers({
    likers: function(){
        return this;
    }
});

Display each user who liked this post in the template:

{{#each likers}}
    <h1>{{name}}</h1>
    <p>{{details}}</p>
    <a href="/profile/{{_id}}">See Full Profile</a>
{{/each}}

I'm unsure if my collections are structured correctly or if there is an issue with my forEach() function.

Answer №1

To tackle your issue, consider utilizing Mongo's $in: selector in the following way:

Meteor.publish('likes', function (postSlug) {
  check(postSlug, Object);
  var postId = Posts.findOne({ slug: postSlug},{ _id: 1 }); // locate post matching the slug

  var relatedLikes = Likes.find({ postId: postId },
    { fields: { userId: 1 }}).fetch(); // retrieve userId field from likes. _id will also be included

  var userIdArray = _.pluck(relatedLikes,'userId'); // extract only the userIds into an array
  return Meteor.users.find({ _id: { $in: userIdArray }});
});

Have you explored reywood:publish-composite? This package is highly effective for solving collection joining challenges like the one you're facing.

Answer №2

According to a suggestion by Michel Floyd, you might consider implementing the use of the reywood:publish-composite package:

Meteor.publishComposite('likes', function (postSlug) {
    return {
        find: function () {
            return Posts.find({slug: postSlug});
        },
        children: [
            {
                find: function (post) {
                    return Likes.find({postId: post._id});
                },
                children: [
                    {
                        find: function (like) {
                            return Meteor.users.find({_id: like.userId});
                        }
                    }
                ]
            }
        ]
    }
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Establish an angular scope within the DOM element

I am facing a challenge in creating a new Angular scope and attaching it to a DOM element. The situation is complicated by the fact that I am working on modifying a third-party control and cannot simply use a directive. My approach so far has been: ... = ...

Effortlessly apply mapping, filtering, reducing, and more in JavaScript

Array#map and Array#filter both create a new array, effectively iterating over the original array each time. In languages like rust, python, java, c#, etc., such expression chains only iterate once, making them more efficient in certain cases. While this ...

What sets apart a space after the ampersand from no space in Material UI?

Could you clarify the difference between using a space after the ampersand compared to not having a space? For example: Why is there a space after the ampersand in & label.Mui-focused but no space in &.Mui-focused fieldset? const WhiteBorderTextF ...

The key to successful filtering in Next.js with Hasura is timing - it's always a step

I am fetching data from Hasura using useRecipe_Filter and passing the searchFilter state as a variable. It seems that every time I press a key, the UI updates with one keystroke delay before filtered data is passed to the results state. const SearchBar = ( ...

Cut off the initial characters in the URL's hash component

Hey there, I'm currently working on a task that involves removing a specific part of a URL string. Here's the scenario: if (window.location.hash == '#super-super-product') { change.window.location.hash.to.this: #product // this i ...

utilize ng-include in angularjs to include a page

For some reason, I am having trouble including a file using ng-include. The file is supposed to be included when a button is pressed: <button type="submit" class="btn btn-primary" ng-click="getPartial()">Compare</button> This is the function ...

How can the 'Read more' feature be modified to impact multiple boxes? (Using jQuery, JS, and CSS)

I am trying to add a 'Read more' feature on my friend's website. I was able to achieve the desired effect, but when I tried to adjust the alignment of the box, it affected the 'Read more' feature. Original design: https://codepen. ...

Service dependency injection error encountered in the controller implementation

After creating a service and attempting to inject dependency into the controller, an error is being displayed: angular.js:12477 Error: [$injector:unpr] Unknown provider: ResultProvider <- Result <- ToolbarController http://errors.angularjs.org/1.4.7 ...

What is the method to determine if a date is larger or smaller than another using Javascript?

Using the inputText function retrieves the value entered in the textbox, while the hidden field value returns the current value. This is my current code snippet: if (inputText.value.length != 0) { if (inputText.value < document.getElementById(&apo ...

Node.js allows for keeping pipe and sockets open even after streaming an HTTP response

My current challenge involves streaming data from an HTTP response to a cloud storage provider within an internal service. const response = await request<Readable>({ headers: httpOpts?.headers, data: httpOpts?.data, url, method, responseTyp ...

The appearance of the pop-up mask is displayed at lightning speed

Check out the demo here Here is the HTML code: <div class="x"> </div> <input class="clickMe" type="button" value="ClickMe"></input> This is the JS code: $(".clickMe").click( function() { ...

What is the best way to manually decrease the speed of an object's rotation using javascript?

Can anyone assist me with slowing down the mouse-controlled rotation of a 3D object in javascript? The current rotation is too sensitive and difficult to control manually. Below is the code I am using: <html> <head> <script src="js/thr ...

combine multiple select options values in a single function using jQuery

My HTML code includes two select options for users to choose the origin and destination cities. I need to calculate the cost of travel between these cities. How can I compare the selected options using jQuery? </head> <body> <div> ...

How to export HTML table information to Excel using JQuery and display a Save As dialog box

This script has been an absolute lifesaver for my web application. Huge thanks to sampopes for providing the solution on this specific thread. function exportToExcel() { var tab_text="<table border='2px'><tr bgcolor='#87AFC6& ...

Dynamic array of objects in Angular using ng-repeat

When given a JSON array of objects, how can one dynamically display it using ng-repeat? The key error is static and always remains the same. Only the values of error change. For example, if the password field has an error, then the key will be password in ...

Determining the value of an element by examining the clicked element

My goal is to determine the remaining balance in my cart based on the selected item. Let's say I have 3 items in my cart, and I choose one that costs $100. Previously, I stated that I had a total of $300. In my HTML code, there are elements with IDs ...

Error code 12004 encountered during the execution of a service request

While working on a service call in my JavaScript code that retrieves XML data using XMLHttpRequest, everything runs smoothly in Chrome and Firefox, successfully fetching the data over HTTPS. However, when attempting to execute the same code in IE11, it ret ...

JavaScript: What's the best way to update the URL in the address bar without triggering a page refresh?

Similar Question: How can I use JavaScript to update the browser URL without reloading the page? I've observed websites like GMail and GrooveShark altering the URL in the address bar without having to refresh the entire page. Based on my understa ...

The main server is not yielding any results from the MongoDB query

I attempted to utilize promises in order to retrieve all the items from my mongoDB database. Here is the code I used: exports.findAll = function(){ return new Promise(function(resolve, reject){ Collection.find({}, function(err, res){ if(err ...

Exploring MongoDB through a sequence of questions

Scenario Following some data manipulations, I have a string: qwertyuiop. To accomplish the task, I need to search for every possible substring of this string using MongoDB. This involves executing multiple queries such as qwertyuiop, qwertyuio, qwertyui, ...