How to use perak:joins?

I’m a bit confused about how to use this package.

In the docs it says :

We have two collections: Companies & Employees

var Companies = new Mongo.Collection("companies");
var Employees = new Mongo.Collection("employees");

Let’s define join (in both server & client scope)

Employees.join(Companies, "companyId", "company", ["name"]);

And at server in publication, instead simply returning cursor, return with Collection.publishJoinedCursors method:

Meteor.publish("employees", function() {

	var cursor = Employees.find(); // do what you normally do here

	return Employees.publishJoinedCursors(cursor); // instead of simply returning resulting cursor
});

Now, if you do:

Employees.find();

You’ll get:

{
	_id: "dySSKA25pCtKjo5uA",
	name: "Jimi Hendrix",
	companyId: "CQKDzmqmQXGhsC6PG",
	company: {
		name: "Acme"
	}
}

What I can’t grasp is surely by doing this it means that you lose access to the original Employees collection doesn’t it?

Every time you subscribe to Employees you will be subscribing to the joined document, is that correct?

If so, how do I use this package and maintain the ability to still query the Employees document separately?

Don’t worry, just realised that you can only join by a matching _id key which renders this package totally useless for me and for most others too I would imagine.

Just found this one which looks a whole lot more promising in case anybody else is lost in the Meteor / Mongo wilderness.

https://atmospherejs.com/reywood/publish-composite

I would advise you to use this: https://github.com/cult-of-coders/grapher it has publish-composite integrated.

Error “Exception from sub my_items id oXCEtGgvnhzGRcHcW Error: Publish function returned an array of non-Cursors”

Items.addLinks({
‘customer’: {
type: ‘one’,
field: ‘customer_id’,
collection: Customer
}
});

Meteor.publish(‘my_items’, function () {
return Items.createQuery({
$filters: {},
text: 1,
customer:{
name:1
}
});
});

Doesn’t work quite like this. Just do a documentation rundown. You would have first to create a named query, expose it, and then use query.subscribe() on the client.

cannot get data

/imports/api/items/queries/itemList.js

import { Meteor } from "meteor/meteor";
import { Mongo } from 'meteor/mongo'

const Items = new Mongo.Collection('items');
const Customer = new Mongo.Collection('customer');
Items.addLinks({
    'customer': {
    	type: 'one',
        field: 'customer_id',
        collection: Customer
    }
});
export default Items.createQuery('itemList', {
    $filters: {},
    text: 1,
    customer:{
    	name:1
    }
});

Cilent

import { Mongo } from 'meteor/mongo';
import { Meteor } from "meteor/meteor";
import itemListQuery from '../imports/api/items/queries/itemList.js';
const query = itemListQuery.clone();
const subscriptionHandle = query.subscribe();
Tracker.autorun(() => {
  	if (subscriptionHandle.ready()) {
  		console.log(query.fetch());
	}
});

subscriptionHandle.ready() not ready (false);
query.fetch() empty

Thank you

You have created a named query, but you have to expose it! This is all specified in the documentation.

Add the following:

if (Meteor.isServer) {
   query.expose()
}

is perfect.
Thank you.

Thanks for the tip but I don’t even know how to start using this package. I can see how the engine runs, but I can’t find the keys to start it up!

Apologies for the incoming rant, it’s not directed at you or anybody else here, but I’m at my wits end with this right now. I don’t think anything has ever made me this frustrated in my life and I’ve been programming for over 20 years (shell, php, jQuery etc - but totally new to full JS stacks and MongoDB).

The problem with a lot of third party Meteor packages that I have found, as a Meteor newb, is that the docs assume the user has a certain amount of knowledge about the base structure that the package is improving on or providing extra support for. This is not a slight on your package, I’m sure it does exactly what I need but the problem is that the whole Meteor/Mongo implementation is the worst documented (and community supported) of all of the aspects of Meteor. It’s almost like they don’t expect anybody to do anything remotely challenging with it, that people will be happy creating Todo lists or scoreboards until the cows come home.

It goes into no depth past the most basic of operations and trying to find help that isn’t older than about 3 or 4 years, and now largely irrelevant due to codebase changes or depreciated packages, on Stack Overflow is near impossible.

I’ve spent days and days trying to figure out to get an array of field values from one collection and use it to search and return the results of another, and it’s still not working. I must have tried a hundred different ways to date.

I’ve tried every package I could find, read as much as I could in the Meteor and Mongo docs and on forums and Stack, but the async nature of Meteor with Mongo is where I keep coming unstuck.

For example, this is my latest attempt where I’m having to use a method now (which I don’t want to do) as I just couldn’t get it to work with publish as this always returns undefined.

'new.get.followers': function(id, PER_PAGE = 5) {
      var followers = [];
      FollowersCollection.find({uid: id}, {limit: PER_PAGE}).forEach(function(u) { followers.push(u.fid) });
      if (followers) {
        var obj_ids = followers.map(function(follower) { return ObjectId(follower); });
        return UserMeta.find({uid: {$in: obj_ids}});
       }
      return null;
 }

But this throws errors in the server console :

Exception while invoking method 'new.get.followers' ReferenceError: ObjectId is not defined
I20180823-01:31:45.409(1)?     at imports/collections/followers.js:66:58

What I’m trying to do in a nutshell…

  1. Pass an id into a function (preferably subscribe / publish functions) along with a limit (for pagination)
  2. Search the FollowersCollection using the id and matching it for every record where it finds the id in the uid field.

Example of a single FollowersCollection document :

{ 
  "_id" : "vMPZi2ipGKf48RSiQ", 
  "uid" : "nskG2euomRcJEKBRs", //user ID
  "fid" : "T4xtun25GJQYjrrzu" //followers user ID (we'll track him below)
}
  1. This should push the results of the fid field into the const followers array which represents each user ID that is following them. It would look something like this :
0: "T4xtun25GJQYjrrzu" //here he is
1: "gq33mc3Ws4agHrGtk"
2: "DCszsAuGfFXgLMi66"
3: "cBQ4bcs4H8EGF89ts"
4: "C8CoJKmFpHZjbuiHG"
  1. Then I map the followers array items to objects obj_ids
  2. Lastly I search the UserMeta collection and want to return an array of each followers meta data using all fields of each document where each item in obj_ids (each followers user ID) matches the uid field in this collection.

Example of a single UserMeta document :

{ 
  "_id" : "aCru7hyhBdnnS7gSb", 
  "uid" : "T4xtun25GJQYjrrzu", //here he is again
  "username" : "dave", 
  "avatar" : "15344635695b760e515b5655b760e515b5aa.jpg", 
  "updatedAt" : ISODate("2018-08-16T23:52:49.469Z"), 
  "name" : "Dave Masterson", 
  "country" : "UK" 
}

If you can show me a way to do this using your package I will be eternally in your debt.

1 Like