grapher/docs/linker_engine.md

174 lines
5 KiB
Markdown
Raw Normal View History

2017-11-30 22:11:43 +02:00
# Linker Engine
The linker engine is composed of 3 components:
2017-12-01 12:30:09 +02:00
- **Definition of Links** (the `addLinks()` thingie, which we already covered)
- **Linked Data Retrieval** (fetching related linked data)
- **Setting Links** (actually updating the database)
2017-11-30 22:11:43 +02:00
2017-12-01 12:30:09 +02:00
Let's explore how we can play with `Linked Data Retrieval` and `Setting Links`, after we already defined our links
2017-11-30 22:11:43 +02:00
using `addLinks()` method.
Each collection gets extended with a `getLink` function:
```js
const linker = Collection.getLink(collectionItemId, 'linkName');
```
A real life example (assuming you have a `direct` or `inversed` link with groups)
```js
const userGroupLinker = Meteor.users.getLink(userId, 'groups');
```
Linker is polymorphic and it allows you to do almost magical things. It is so flexible that it will
allow you to use it very naturally.
## Linked Data Retrieval
```js
const userGroupLinker = Meteor.users.getLink(userId, 'groups');
// fetching the groups for that user:
const groups = userGroupLinker.find().fetch();
// or for ease of use
const groups = userGroupLinker.fetch();
2017-12-01 12:30:09 +02:00
// or to filter the linked elements
2017-11-30 22:11:43 +02:00
const groups = userGroupLinker.find(filters, options).fetch();
// and again simpler
const groups = userGroupLinker.fetch(filters, options);
2017-12-01 12:30:09 +02:00
// and if you want to get a count()
2017-11-30 22:11:43 +02:00
const groups = userGroupLinker.find(filters, options).count();
```
This works with any kind of links from any side.
## Setting Links
This allows you to very easily link collections to each other, without relying on knowing the fields and how are they stored.
2017-12-01 12:30:09 +02:00
It also allows you to set links from any place `direct` and `inversed`, of any type `one` or `many` and `meta` links as well,
enabling doing this in a natural way:
2017-11-30 22:11:43 +02:00
2017-12-01 12:30:09 +02:00
### One Links
2017-11-30 22:11:43 +02:00
```js
const userPaymentProfileLink = Meteor.users.getLink(userId, 'paymentProfile');
userPaymentProfileLink.set(paymentProfileId);
// but it also works if you have the object directly if it has _id, for ease of use:
userPaymentProfileLink.set(paymentProfile);
// it works from the other side as well
const paymentProfileUserLink = PaymentProfiles.getLink(paymentProfileId, 'user');
paymentProfileUserLink.set(userId); // or a user object that contains `_id`
```
2017-12-01 12:30:09 +02:00
You can also `set()` objects that aren't in the database yet.
Performing a `set()` will automatically execute the update or insert in the database.
2017-11-30 22:11:43 +02:00
```js
const userPaymentProfileLink = Meteor.users.getLink(userId, 'paymentProfile');
userPaymentProfileLink.set({
last4digits: '1234',
});
```
This will insert into the `PaymentProfiles` collection and link it to user and it works from both `direct` and `inversed` side as well.
To remove a link for a `one` relationship (no arguments required):
```js
2017-12-01 12:30:09 +02:00
// from direct or inversed side
2017-11-30 22:11:43 +02:00
userPaymentProfileLink.unset();
paymentProfileUserLink.unset();
```
2017-12-01 12:30:09 +02:00
### Many Links
2017-11-30 22:11:43 +02:00
Same principles as above apply, with some minor changes, this time we use `add` and `remove`
```js
const userGroupsLink = Meteor.users.getLink(userId, 'groups');
userGroupsLink.add(groupId);
userGroupsLink.add(group); // object containing an _id
userGroupsLink.add({
name: 1,
}); // will add the group to the database and link it accordingly
```
The methods `add()` and `remove()` also accept arrays
```js
userGroupsLink.add([
groupId1,
groupId2
]);
userGroupsLink.remove(groupIds)
```
2017-12-01 12:30:09 +02:00
The same logic applies, you can:
- Single string *OR* Object with _id *OR* Object without _id
- Array of any mixture of the first ^
2017-11-30 22:11:43 +02:00
2017-12-01 12:30:09 +02:00
The `remove()` cannot accept objects without `_id` as it makes no sense to do so.
2017-11-30 22:11:43 +02:00
2017-12-01 12:30:09 +02:00
### Meta Links
2017-11-30 22:11:43 +02:00
Now things get very interesting, because `metadata` allows us to store additional information about the link,
2017-12-01 12:30:09 +02:00
it lets us **describe** the relationship. This works from `direct` and `inversed` side as well, with the
2017-11-30 22:11:43 +02:00
same principles described as above.
The `add()` and `set()` allow an additional parameter `metadata`:
```js
2017-12-01 12:30:09 +02:00
// assumming our link now have {metadata: true} in their definition
2017-11-30 22:11:43 +02:00
// one
const userPaymentProfileLink = Meteor.users.getLink(userId, 'paymentProfile');
userPaymentProfileLink.set(paymentProfileId, {
createdAt: new Date()
});
// many
const userGroupsLink = Meteor.users.getLink(userId, 'groups');
userGroupsLink.add(groupId, {
createdAt: new Date(),
})
// if you add multiple objects, they will receive the same metadata
userGroupsLink.add([groupId1, groupId2], {
createdAt: new Date(),
})
```
Updating existing metadata:
```js
// one
const userPaymentProfileLink = Meteor.users.getLink(userId, 'paymentProfile');
userPaymentProfileLink.metadata({
updatedAt: new Date()
});
// many
userGroupsLink.metadata(groupId, {
createdAt: new Date(),
})
userGroupsLink.metadata([groupId1, groupId2], {
createdAt: new Date(),
})
```
Updating metadata only works with strings or objects that contain `_id`, and it works from both sides.
2017-12-01 12:58:36 +02:00
## Conclusion
2017-11-30 22:11:43 +02:00
By using this Programatic API to set your links instead of relying on updates, it makes your code much simpler to read,
2017-12-01 12:30:09 +02:00
and makes schema migration easier in the future.
2017-12-01 12:58:36 +02:00
## [Continue Reading](query_options.md) or [Back to Table of Contents](index.md)
2017-11-30 22:11:43 +02:00