Grapher - Collection Relationship Manager + GraphQL Like Data Fetcher

can you show me the full exposure in a pastebin ?

Itā€™s nothing too fancy, actually.

collection.js

import {Meteor} from 'meteor/meteor';
const Users = Meteor.users;
export default Users;

and expose.js

import Users from './collection';
import {Exposure} from 'meteor/cultofcoders:grapher';

Users.expose({
    firewall(filters, options, userId) {
        Exposure.restrictFields(filters, options, ['services', 'emails', 'roles']);
        filters._id = userId;
    }
});

From what I understand, this should remove the services emails roles fields from the publication. At least, thatā€™s what it does when I try it with another collection.

Are you sure ā€œServicesā€ is published ? Otherwise it may be due to the fact that when you login ā€œusernameā€, ā€œemailsā€, ā€œprofileā€ is published by default for the current logged in user:

This is due to Meteorā€™s mergebox, which tries to combine the publication from the exposure with the publication of the actually logged in user. If you do it via method query.fetch({}) does it still happen ?

Related to tutorials, you could take as example great Redux tutorial series(by Dan Abramov) on egghead
For example, after a video itself, theres a section at bottom of page, containing transcript and code sections.
Could be nice choice to satisfy both camps.

Yes, if I remove the filters._id = userId; then I can see everything from all the users if Iā€™m then doing a Users.find().fetch()

So you are saying even if you have restrictFields you can still see everything from all users ?

UPDATE:
Bug found & fixed. Pushed new version. Updated boilerplate.

Thank you!

2 Likes

Okay, I had changed the code in the meantime and canā€™t quite reproduce it.

However, I now have the complete opposite condition:

If I change collection.js to

Users.expose({});
(so, no filters, no firewall)

then I get my own complete document, but only the _ids for everyone else.

Yes, this makes sense because. You are by default subscribed to yourself as a User. Read the link I gave you for Meteor.user().

And you see only the _ids of everyone else because you need to query the fields you need:

createQuery({users: {emails: 1}}).subscribe()

and you should see the emails of everyone else as well.

Ah, now it works.

Thanks. Will take a while until I have this memorized.

edit: Oh, bugger. Thereā€™s still something wonky.
edit2: Nope.

I somewhat agree with @rhywden in regards to video tutorials for this purpose. I would like to suggest an approach Angular-meteor took for creating the tutorials, they are easy to follow, organized and searchable.
Here is the link: https://www.angular-meteor.com/tutorials/socially/angular2/bootstrapping

Really looking forward to some tutorials.

@diaconutheodor, just want to demystify some doubtsā€¦

So basically, Grapher has no opinions/suggestions to how data is inserted to the collections, what it does is structure and optimize data fetching and subscriptions, please correct me if I not correct?
If that is the case Collection allow/deny rules still apply/or not?

Cheers!

Does it complement SimpleSchema/Collection2 or replace? I have a lot of client side form validation logic within SimpleSchema, if Grapher is a replacement, will that transfer over somehow?

Sorry mate, from reading whatā€™s out there, Iā€™m myself not very clear on many things but to me it seems itā€™s not a drop-in replacement for SimpleSchema instead depends on it for things like GrapherLive etc.

I am going to go through the docs more throughly today to see how it will fit in my Meteor app with Blaze.

1 Like

So basically, Grapher has no opinions/suggestions to how data is inserted to the collections

Exactly. Itā€™s sole focus is data fetching, link management, secure exposure.

Does it complement SimpleSchema/Collection2 or replace? I have a lot of client side form validation logic within SimpleSchema, if Grapher is a replacement, will that transfer over somehow?

They are completely separated concepts. It complements SS because when you store ā€œlink dataā€, you actually have to have a SimpleSchema entry like {userId: {type: String}}. It does this automatically for you, it extends the schema depending on link type.

@aadams

Does it complement SimpleSchema/Collection2 or replace? I have a lot of client side form validation logic within SimpleSchema, if Grapher is a replacement, will that transfer over somehow?

It complements it. It blends in with your previous schema when you add links.

Sorry mate, from reading whatā€™s out there, Iā€™m myself not very clear on many things but to me it seems itā€™s not a drop-in replacement for SimpleSchema instead depends on it for things like GrapherLive etc.

It doesnā€™t replace SimpleSchema indeed. However it uses SimpleSchema internally to do some validation.

1 Like

Hi mate,

I have a question, I am going through the docs and the boilerplate sample, I hope they are not stupid questions.

With Grapher lets say there is a collection Posts as in the sample and defines links:

import Posts from './collection.js';
import Users from '/imports/api/users/collection.js';
import Comments from '/imports/api/comments/collection.js';
import Tags from '/imports/api/tags/collection.js';
import Groups from '/imports/api/groups/collection.js';

Posts.addLinks({
    owner: {
        type: 'one',
        collection: Users,
        field: 'ownerId',
        index: true
    },
    comments: {
        collection: Comments,
        inversedBy: 'post'
    },
    tags: {
        collection: Tags,
        type: 'many',
        field: 'tagIds',
        index: true
    },
    commentsCount: {
        resolve(post) {
            return Comments.find({postId: post._id}).count();
        }
    },
    group: {
        type: 'one',
        collection: Groups,
        metadata: {}
    }
});

Now, once the links on a collection are defined, will Grapher automatically take care of linking colletions and resolvers data fetching when queried for data or Do have to link every single doc. manually when inserted like in the /imports/server/fixtures.js file

_.each(users, (user) => {
        const userPostLink = Users.getLink(user, 'posts');
        const userGroupLink = Users.getLink(user, 'groups');

        userGroupLink.add(_.sample(groups), {
            isAdmin: _.sample([true, false])
        });

        _.each(_.range(POST_PER_USER), (idx) => {
            let post = {
                title: `User Post - ${idx}`
            };

            userPostLink.add(post);
            const postCommentsLink = Posts.getLink(post, 'comments');
            const postTagsLink = Posts.getLink(post, 'tags');
            const postGroupLink = Posts.getLink(post, 'group');
            postGroupLink.set(_.sample(groups), {random: Random.id()});

            postTagsLink.add(_.sample(tags));

            _.each(_.range(COMMENTS_PER_POST), (idx) => {
                let comment = {
                    text: _.sample(COMMENT_TEXT_SAMPLES)
                };

                postCommentsLink.add(comment);
                Comments.getLink(comment, 'user').set(_.sample(users));
            })
        })
    });

I really appreciate you taking the time to answer.
Cheers!

You have to explictly link your documents. I think I donā€™t understand yoour question.

Cool. I was just checking your thoughts on the possibility of using graph queries for some types of analysis, such as ā€˜recommendationsā€™. I will open the thread for further discussion in the Grapher issue queue.

@diaconutheodor I really like grapher. I currently integrating it to my project. It works well so fare.

But I have one stupid question related to grapher live.
How can I fetch all documents with all fields of one collection ?

I tried:
{
my_collection:1
}

but then I get only all documents with the id fields.
with
{
my_collection: {
details:1
}
}

I get all documents of my_collection and all data in details.

Fetching all fields is currently disabled. At first we had something like $all: 1, but decided to disable it because it was very prone to mistakes.

We are going to think about it, because I sometimes feel the need of it too, especially when you are debugging.

Ok, thanks.

You are right. The $all is very helpful for debugging.
Would also great, to have the $filter working in grapher live. Then we could develop our queries in the live tool.