How add links that link to non-_id in grapher or How to make _id non-unique

Hi there,

I am using grapher with meteor and I have the following collections:

Meteor.users (Or Users) as usual,

GroupAccount:

export default new SimpleSchema({
	groupName: {
		type: String,
		optional: true,
	},
	userId: {
		type: String,
		optional: true
	},
        .
        .
        .
});

Where _id is the group Id

GroupMembers:

export default new SimpleSchema({
	groupId: {
		type: String
	},
	userId: {
		type: String
	},
        .
        .
        .
});

Where groupId corresponds to the GroupAccount _id, and userId to Users _id as expected

I have the following links added to to GroupMember:

GroupMembers.addLinks({
    account: {
		type: 'one',
        collection: GroupAccount,
        field: 'groupId',
        index: true,
	},
    member: {
        type: 'one',
        collection: Users,
        field: 'userId',
        unique: true,
        index: true,
    },
    members: {
		type: 'many',
		collection: GroupMembers,
		field: 'groupId',
		index: true,
	}
});

the first two links work okay. The last one does not as groupId in GroupMember matches to GroupMember’s _id. This would work if _id was changed to groupId, and that would mean _id is no longer unique. In simple terms members link is trying to find all users that are in the same group as the current userId. So Users define the users, GroupAccount define the group itself and then GroupMember stores all members (users) that are in groups. If groupId is the same in GroupMember for two or more members it means they are in the same group. I see the way grapher defines members is by using arrays which is moving away from the sql standards. I am not sure which approach is faster: arrays or using indexes. My question is how do I solve this. If the answer is making GroupMember’s _id to be groupId then how do I make mongodb _id non unique while still working as expected with meteor’s grapher. All answers are welcome, but I’d appreciate it more if people who know grapher respond.

And of-course there is the inverses for the first two links:

GroupAccount.addLinks({
    member: {
        inversedBy: 'account',
        collection: GroupMembers
    }
});
Users.addLinks({
    groupMember: {
        inversedBy: 'member',
        collection: GroupMembers
	}
});

The third link links back to GroupMember so it would not have an inverse.

Example of a query for the first two links would be:

export default createQuery({
    users: {
        $filter({filters, params}) {
            filters._id = params._id
        },
        username: 1,
        emails: 1,
        groupMember: {
			userId: 1,
			account: {
				groupName: 1,
			}
        }
    }
});

I think the query for the third link as I envisage it would be something like:

	members: {
		groupId: 1,
		userId: 1,
		member: {
			username: 1
		}
	}

Where members is returned as some kind of an array of users in the same groupId.

Thanks for your help in advance.

I got it. members link is useless and not correct. All I have to do to get the users that are in the same group as the current user is extend/ change the query for the first two links (above) as follows:

export default createQuery({
    users: {
        $filter({filters, params}) {
            filters._id = params._id
        },
        username: 1,
        emails: 1,
        groupMember: {
			userId: 1,
			account: {
				groupName: 1,
				member: {
					groupId: 1,
					userId: 1,
					member: {
						username: 1
					}
			}
        }
    }
});

What to note here is that inverse links are important and very powerful. All you have to do is think from the other end. In this case I link back the group account to members using inverses and that gets all the members and from there it is simple get the member in GroupMembers and then get the Users (Meteor.users). See you are working back. The result is an array of users. Hope it helps someone.