PUBSUB with relational collections?

Is there a right way of publishing relational collections? I’m using reywood:publish-composite but I’m not sure if its the best way of doing it.

1 Like

publish-composite works well, if you are familiar with Mongo aggregation framework, you should check out reactive aggregate package

Using $lookup and $facet You can and publish related documents and or built custom documents based on your front end requirements. (GraphQL) like experience.

Hope this helps

You can also use grapher. Under the hood it uses publish-composite as well but the queries are highly optimized.

curious, have you done any performance comparisons? I’ve been thinking of swapping publish composite with reactive aggregate.

I can’t find in the docs how is the publish made, or is it fetch only?

This package seems to be really nice, but I kinda liked Grapher structure, will see if it fits my needs and if it don’t I will check this one! :grinning:

Just link collections and query one of them reactively (probably with a named query). This way you can query data from the linked collection easily.

1 Like

Right now I was studying the Grapher and how to use it and them I found Grapher with GraphQL and Apollo, did you used it before?

Where I found it:

and

but one thing I can’t understand is grapher-schema-directives

Now I just found this page https://www.meteor-tuts.com/, wich just helped me to understand how to “expose” a query to the front-end, thats amazing!

Still testing things, but everything seems pretty straight forward…

Now I’m able to expose and subscribe to the queries, it’s just amazing how things are working now, but I still have one problem thats when I do a query clone it throws me an error, heres the code:

The query:

// meteor
import { Meteor } from 'meteor/meteor';

// db
import { UserToken } from '../db';

// query
export const authQuery = UserToken.createQuery('authQuery', {
	$filter({ filters, options, params }: any) {
		console.log('test', { filters, options, params });
	},
	user: {
		email: 1,
		profile: {
			name: 1,
		},
	},
});

// check for server
if (Meteor.isServer) {
	authQuery.expose({
		firewall(filters: any, options: any, userId: any) {
			console.log('authQuery.expose', { filters, options, userId });
		},
	});
}

The subscription:

// meteor
import { useTracker } from 'meteor/react-meteor-data';

// npm
import React from 'react';

// api
import { authQuery } from '../../../imports/api/auth';

// store
import { useSelector } from '../../store';

// app
export const App = () => {
	const { token } = useSelector((s) => s.auth);

	const { ready, auth } = useTracker(() => {
		try {
			const sub = authQuery.subscribe();
			const auth = authQuery.clone({ token }).fetchOne();

			const ready = sub.ready();

			return { ready, auth };
		} catch (ex) {
			console.log({ ex });
			return {};
		}
	}, [token]);

	console.log({ ready, auth });

	return <h1>APP</h1>;
};

Error:

{
   "isClientSafe": true,
   "error": "You did not provide a valid callback",
   "message": "[You did not provide a valid callback]",
   "errorType": "Meteor.Error"
}

Hope someone can help me out :joy:

Actually just solved that by doing the clone before the subscription, as follow:

const tokenQuery = authQuery.clone({ token });

const sub = tokenQuery.subscribe();
const auth = tokenQuery.fetchOne();

This should be something like this:

// clone the query so we don't mutate the original one
const query = authQuery.clone({ foo: 'bar' })
// set up subscription
const handle = query.subscribe()
// fetch data
const auth = query.fetchOne()
// check if the sub is ready
const ready = handle.ready()

return {ready, auth}
1 Like