A bit lost with join


#1

Hi there,

I new with meteor, I realy enjoy it, but i’m stucked with an app that i do to learn. I’m trying to do a join.
Here is the case :
I have a list of car and each cars have passengers. There is a collection cars and a collection users (which are the passengers). I’d like to display on a page all the cars with their passengers. But i cannot figure out how to make it work. I’m trying with reywood:publish-composite

here is my source code, if anybody want to have a look at it to help :
https://xavierva@bitbucket.org/xavierva/caroster.git

Thanks a lot


#2

HI, I couldn’t find some parts in your code, ( I am also new to Meteor) specifically where you have the JS events to add a document to the car collection and to add a passenger?

what you need to do is have an insert event on the users that will have a carId attached to it {carId:template.data._id } and you join the user Id to that car and then do a helper to return Passengers.find({carId: }}, (or depending where will be the form etc but is something along those lines)

in general You need to add the ID of the document you want to join together to the object when inserting and then to show it in your view create a query with a helper that will return those objects…


#3

This line of code you need to change to:

return Users.find({ carid: this._id });

And in your template, because the passengers helper returns a cursor of many passengers, you need to do:

{{#each passengers}}
  ...
  {{passengername}}
  ...
{{/each}}

#4

Personally I think you should take a look at this package https://github.com/dburles/meteor-collection-helpers. This package will help you organize your collections and how you manipulate them or even join them. Lets assume your using Template subscriptions and you subscribe to multiple things like so

Template.carView.onRendered(function () {
  var instance = this;
  var current = Router.current().params;

  instance.autorun(function () {
    var carSubscription = instance.subscribe('car', current._id);

    if (carSubscription.ready()) {

      //Find all passengers in our car
      var userIds = instance.car().passengers;

      // subscribe to the users publication
      var passengerSubscription = instance.subscribe('users', userIds);

      //Hide the loader
      Session.set('loading', false);
    } else {
      //Display the loader
      Session.set('loading', true);
    }
});

  instance.car = function() {
    return Cars.findOne(current._id);
  };

});

I can then call something like this on the project document its self

Projects.helpers({

  /**
   * Finds the passengers associated with the car
   * @returns {Mongo.Cursor}
   */
  'passengers' : function () {
    return Meteor.users.find({ $ne : { _id : Meteor.userId()} );
  }
});

and you can then in handlebars call the data like so

{{#with car}}

{{make}} - {{model}}

    {{#each passengers}}

        {{profile.fullName}}

    {{/each}}

{{/with}}

FYI I wrote this code on here so im not 100% it will run as is but I hope this helps you find your answer

EDIT:

Also if you had helpers on the Meteor.users collection then you could continue the calls like so

{{#with car}}
    
    {{make}} - {{model}}
    
        {{#each passengers}}
    
            {{profile.SomeOtherHelperOnUsersCollection}}
    
        {{/each}}
    
{{/with}}

#5

Thanks a lot, I figured out this, just before reading your post, but my passengers still doesn’t displays.

But I’m realy not sure of this part


#6

Thank !

If I definitely fail with my way, I’ll try it and let you know


#7

@vonaa Im not too sure about how to use the package you are using for publishing a collection like that but I have created my publication for the user list like so

/**
 * Publish users from an array of id's
 */
Meteor.publish('users', function(userIds) {
  return Meteor.users.find({ _id : { $in: userIds } });
});

And if you look at my previous post I get the list of ids as like so

//Find all passengers in our car 
var userIds = instance.car().passengers;//this should be an array on the document like passengers : [ "D4gad6sc", "c4gad6sc", "f4bAd6sc"...]

// subscribe to the users publication
var passengerSubscription = instance.subscribe('users', userIds);

#8

Hi there, It has been a long time, but i’m back to my code now !

I quit using the package.

So where I’m know ? I can display all my cars, but i still stuck to display the user linked to the car. If anybody can help me a bit, thanks to him already !

Server side :

//List all cars
Meteor.publish('allCars', function() {
	return Cars.find();
});

//Find users linked to the car
Meteor.publish('usersByCar', function(carId) {
	return Users.find({carid: carId});
}); 

My router :

Router.route('/organizer', function (){
	this.render('organizer');
},
{
	name: "organizer",
	waitOn: function(){
		Meteor.subscribe('allCars');
		Meteor.subscribe('usersByCar', Cars._id);
	},
	
});

My application side car.js :

Template.allCars.helpers({
    cars: function() {
        return Cars.find();
    },

  passengers: function() {
	  return userByCar(Cars._id);
    }
})

and Finaly my template :

<template name="allCars">
	<ul>
	{{#each cars}}
	<div class= 'car'>
		<h3>{{carname}}</h3> <br>
			{{#with cars this}}
				{{#each passengers}}
				{{this.passengername}}
				{{/each}}
			{{/with}}
		<button type="add">+</button>
	</div>
	{{/each}}
	</ul>
	<p>{{passengers}}</p>
</template>

#9

Hello there, juste to let you know that I finally figured out how to do it.

Here is my code for those interested.

My template

<template name="allCars">
	<ul>
	{{#each cars}}
	<div class= 'car'>
		<h3>{{carname}}{{theCar._id}}</h3> <br>
			{{#each passengers theCar._id}} <!-- Call passengers helper and put the id of the current car in parameter and then display all the names of users linked to this car -->
			<p>{{username}}</p>
			{{/each}}
		<button type="add">+</button>
	</div>
	{{/each}}
	</ul>
</template>

My helpers

Template.allCars.helpers({
// get all the cars in database    
	cars: function() {
        return Cars.find();
    },
	
//Get the current car listed, we use this to get his _id
	theCar: function() {
		return Cars.findOne(this);
	},

//Find all users linked to this car _id
	passengers: function(carId) {
	  //var carId = "557c2d338eb346a21821aaej";
	  return Users.find({carid: carId});
    }
	
})

Note : I also created a seed.js to generate my data, because before I was generating them via the mongo consol and it add “ObjectID(…))” on all id in the db, which isn’t really convenient.


#10

@vonaa take a look at https://github.com/englue/meteor-publish-composite to get the data to the client and take a look at https://atmospherejs.com/dburles/collection-helpers to create the relationship