Skip to content

Function NewRelation

basic has many eager loading

typescript
let user: FedacoTestUser = await FedacoTestUser.createQuery().create({
  email: 'linbolen@gradii.com'
});
await user.NewRelation('posts').create({
  name: 'First Post'
});
user = await FedacoTestUser.createQuery()
  .with('posts')
  .where('email', 'linbolen@gradii.com')
  .first();
typescript
const post = await FedacoTestPost.createQuery()
  .with('user')
  .where('name', 'First Post')
  .get();

see also prerequisites

basic morph many relationship

typescript
const user = await FedacoTestUser.createQuery().create({
  email: 'linbolen@gradii.com'
});
await user.NewRelation('photos').create({
  name: 'Avatar 1'
});
await user.NewRelation('photos').create({
  name: 'Avatar 2'
});
const post = await user.NewRelation('posts').create({
  name: 'First Post'
});
await post.NewRelation('photos').create({
  name: 'Hero 1'
});
await post.NewRelation('photos').create({
  name: 'Hero 2'
});
const userPhotos = await user.photos;
ReferenceLooks LikeValue
isArray(await user.photos)exactly matchtrue
(await user.photos)[0]instance type exactly matchFedacoTestPhoto
isArray(await post.photos)exactly matchtrue
(await post.photos)[0]instance type exactly matchFedacoTestPhoto
(await user.photos).lengthexactly match2
(await post.photos).lengthexactly match2
(await user.photos)[0].nameexactly match'Avatar 1'
(await user.photos)[1].nameexactly match'Avatar 2'
(await post.photos)[0].nameexactly match'Hero 1'
(await post.photos)[1].nameexactly match'Hero 2'
ReferenceLooks LikeValue
isArray(photos)exactly matchtrue
photos.lengthexactly match4
await photos[0].imageableinstance type exactly matchFedacoTestUser
await photos[2].imageableinstance type exactly matchFedacoTestPost
(await photos[1].imageable).emailexactly match'linbolen@gradii.com'
(await photos[3].imageable).nameexactly match'First Post'

see also prerequisites

basic nested self referencing has many eager loading

typescript
let user: FedacoTestUser = await FedacoTestUser.createQuery().create({
  email: 'linbolen@gradii.com'
});
const post: FedacoTestPost = await user.NewRelation('posts').create({
  name: 'First Post'
});
await post.NewRelation('childPosts').create({
  name: 'Child Post',
  user_id: user.id
});
user = await FedacoTestUser.createQuery()
  .with('posts.childPosts')
  .where('email', 'linbolen@gradii.com')
  .first();
ReferenceLooks LikeValue
head(await user.posts).nameexactly match'First Post'
head(await head(await user.posts).childPosts)exactly not matchnull
head(await head(await user.posts).childPosts as any[]).nameexactly match'Child Post'
ReferenceLooks LikeValue
(await head(posts).parentPost)exactly not matchnull
(await head(posts).parentPost).userexactly not matchnull
(await head(posts).parentPost).user.emailexactly match'linbolen@gradii.com'

see also prerequisites

belongs to many custom pivot

typescript
const john = await FedacoTestUserWithCustomFriendPivot.createQuery().create({
  id: 1,
  name: 'John Doe',
  email: 'johndoe@example.com'
});
const jane = await FedacoTestUserWithCustomFriendPivot.createQuery().create({
  id: 2,
  name: 'Jane Doe',
  email: 'janedoe@example.com'
});
const jack = await FedacoTestUserWithCustomFriendPivot.createQuery().create({
  id: 3,
  name: 'Jack Doe',
  email: 'jackdoe@example.com'
});
const jule = await FedacoTestUserWithCustomFriendPivot.createQuery().create({
  id: 4,
  name: 'Jule Doe',
  email: 'juledoe@example.com'
});
await FedacoTestFriendLevel.createQuery().create({
  id: 1,
  level: 'acquaintance'
});
await FedacoTestFriendLevel.createQuery().create({
  id: 2,
  level: 'friend'
});
await FedacoTestFriendLevel.createQuery().create({
  id: 3,
  level: 'bff'
});
await john.NewRelation('friends').attach(jane, {
  friend_level_id: 1
});
await john.NewRelation('friends').attach(jack, {
  friend_level_id: 2
});
await john.NewRelation('friends').attach(jule, {
  friend_level_id: 3
});
const johnWithFriends = await FedacoTestUserWithCustomFriendPivot.createQuery()
  .with('friends')
  .find(1);
ReferenceLooks LikeValue
await (await johnWithFriends.friends.find(it => it.id === 3).getAttribute( 'pivot').level).levelexactly match'friend'
(await johnWithFriends.friends.find(it => it.id === 4).getAttribute( 'pivot').friend).nameexactly match'Jule Doe'

see also prerequisites

belongs to many relationship models are properly hydrated over chunked request

typescript
const user = await FedacoTestUser.createQuery().create({
  email: 'linbolen@gradii.com'
});
const friend = await user.NewRelation('friends').create({
  email: 'xsilen@gradii.com'
});
const user1: FedacoTestUser = await FedacoTestUser.createQuery().first();
await user1
  .NewRelation('friends')
  .chunk(2)
  .pipe(
    tap(({ results: friends }) => {
      expect(friends.length).toBe(1);
      expect(head(friends).email).toBe('xsilen@gradii.com');
      expect(head(friends).getRelation('pivot').getAttribute('user_id')).toBe(
        user.id
      );
      expect(head(friends).getRelation('pivot').getAttribute('friend_id')).toBe(
        friend.id
      );
    })
  )
  .toPromise();

see also prerequisites

belongs to many relationship models are properly hydrated over each request

typescript
const user = await FedacoTestUser.createQuery().create({
  email: 'linbolen@gradii.com'
});
const friend = await user.NewRelation('friends').create({
  email: 'xsilen@gradii.com'
});
await (
  await FedacoTestUser.createQuery().first()
)
  .NewRelation('friends')
  .each()
  .pipe(
    tap(({ item: result, index }) => {
      expect(result.email).toBe('xsilen@gradii.com');
      expect(result.getAttribute('user_id')).toBe(user.id);
      expect(result.getAttribute('friend_id')).toBe(friend.id);
    })
  )
  .toPromise();

see also prerequisites

count for pagination with grouping and sub selects

typescript
const user1 = await FedacoTestUser.createQuery().create({
  id: 1,
  email: 'linbolen@gradii.com'
});
await FedacoTestUser.createQuery().create({
  id: 2,
  email: 'xsilen@gradii.com'
});
await FedacoTestUser.createQuery().create({
  id: 3,
  email: 'foo@gmail.com'
});
await FedacoTestUser.createQuery().create({
  id: 4,
  email: 'foo@gmail.com'
});
const friendsRelation = user1.NewRelation('friends');
await friendsRelation.create({
  id: 5,
  email: 'friend@gmail.com'
});
const query = await FedacoTestUser.createQuery()
  .select({
    0: 'id',
    friends_count: await FedacoTestUser.createQuery()
      .whereColumn('friend_id', 'user_id')
      .count()
  })
  .groupBy('email')
  .getQuery();

see also prerequisites

has on nested self referencing belongs to many relationship with where pivot

typescript
const user = await FedacoTestUser.createQuery().create({
  id: 1,
  email: 'linbolen@gradii.com'
});
const friend = await user.NewRelation('friends').create({
  id: 2,
  email: 'xsilen@gradii.com'
});
await friend.NewRelation('friends').create({
  id: 3,
  email: 'foo@gmail.com'
});
const results = await FedacoTestUser.createQuery()
  .has('friendsOne.friendsTwo')
  .get();
ReferenceLooks LikeValue
head(results).emailexactly match'linbolen@gradii.com'

see also prerequisites

has on nested self referencing belongs to many relationship

typescript
const user = await FedacoTestUser.createQuery().create({
  email: 'linbolen@gradii.com'
});
const friend = await user.NewRelation('friends').create({
  email: 'xsilen@gradii.com'
});
await friend.NewRelation('friends').create({
  email: 'foo@gmail.com'
});
const results = await FedacoTestUser.createQuery().has('friends.friends').get();
ReferenceLooks LikeValue
head(results).emailexactly match'linbolen@gradii.com'

see also prerequisites

has on self referencing belongs to many relationship with where pivot

typescript
const user = await FedacoTestUser.createQuery().create({
  id: 1,
  email: 'linbolen@gradii.com'
});
await user.NewRelation('friends').create({
  id: 2,
  email: 'xsilen@gradii.com'
});
const results = await FedacoTestUser.createQuery().has('friendsOne').get();
ReferenceLooks LikeValue
head(results).emailexactly match'linbolen@gradii.com'

see also prerequisites

has on self referencing belongs to many relationship

typescript
const user = await FedacoTestUser.createQuery().create({
  email: 'linbolen@gradii.com'
});
await user.NewRelation('friends').create({
  email: 'xsilen@gradii.com'
});
typescript
const results = await FedacoTestUser.createQuery().has('friends').get();
ReferenceLooks LikeValue
head(results).emailexactly match'linbolen@gradii.com'

see also prerequisites

has with non where bindings

typescript
const user = await FedacoTestUser.createQuery().create({
  id: 1,
  email: 'linbolen@gradii.com'
});
await (
  await user.NewRelation('posts').create({
    name: 'Post 2'
  })
)
  .NewRelation('photos')
  .create({
    name: 'photo.jpg'
  });
const query = await FedacoTestUser.createQuery().has('postWithPhotos');
const { result: sql, bindings } = query.toSql();
const bindingsCount = bindings.length;
const questionMarksCount = sql.match(/\?/g)?.length || 0;

see also prerequisites

isset loads in relationship if it isnt loaded already

typescript
const user = await FedacoTestUser.createQuery().create({
  email: 'linbolen@gradii.com'
});
await user.NewRelation('post').create({
  name: 'First Post'
});

see also prerequisites

morph map is used for creating and fetching through relation

typescript
Relation.morphMap({
  user: FedacoTestUser,
  post: FedacoTestPost
});
const user = await FedacoTestUser.createQuery().create({
  email: 'linbolen@gradii.com'
});
await user.NewRelation('photos').create({
  name: 'Avatar 1'
});
await user.NewRelation('photos').create({
  name: 'Avatar 2'
});
const post = await user.NewRelation('posts').create({
  name: 'First Post'
});
await post.NewRelation('photos').create({
  name: 'Hero 1'
});
await post.NewRelation('photos').create({
  name: 'Hero 2'
});
ReferenceLooks LikeValue
(await user.photos)[0]instance type exactly matchFedacoTestPhoto
isArray(await post.photos)exactly matchtrue
(await post.photos)[0]instance type exactly matchFedacoTestPhoto
(await user.photos).lengthexactly match2
(await post.photos).lengthexactly match2
(await user.photos)[0].nameexactly match'Avatar 1'
(await user.photos)[1].nameexactly match'Avatar 2'
(await post.photos)[0].nameexactly match'Hero 1'
(await post.photos)[1].nameexactly match'Hero 2'
(await user.photos)[0].getAttribute('imageable_type')exactly match'user'
(await user.photos)[1].getAttribute('imageable_type')exactly match'user'
(await post.photos)[0].getAttribute('imageable_type')exactly match'post'
(await post.photos)[1].getAttribute('imageable_type')exactly match'post'

see also prerequisites

morph map is used when fetching parent

typescript
Relation.morphMap({
  user: FedacoTestUser,
  post: FedacoTestPost
});
const user = await FedacoTestUser.createQuery().create({
  email: 'linbolen@gradii.com'
});
await user.NewRelation('photos').create({
  name: 'Avatar 1'
});
const photo = await FedacoTestPhoto.createQuery().first();
ReferenceLooks LikeValue
await photo.imageableinstance type exactly matchFedacoTestUser

see also prerequisites

one to many relationship

typescript
const user = await FedacoTestUser.createQuery().create({
  email: 'linbolen@gradii.com'
});
await user.NewRelation('posts').create({
  name: 'First Post'
});
await user.NewRelation('posts').create({
  name: 'Second Post'
});
const posts = await user.posts;
const post2 = await user
  .NewRelation('posts')
  .where('name', 'Second Post')
  .first();
ReferenceLooks LikeValue
posts.lengthexactly match2
posts[0]instance type exactly matchFedacoTestPost
posts[1]instance type exactly matchFedacoTestPost
post2instance type exactly matchFedacoTestPost
post2.nameexactly match'Second Post'
await post2.userinstance type exactly matchFedacoTestUser
(await post2.user).emailexactly match'linbolen@gradii.com'

see also prerequisites

pluck with join

typescript
const user1 = await FedacoTestUser.createQuery().create({
  id: 1,
  email: 'linbolen@gradii.com'
});
const user2 = await FedacoTestUser.createQuery().create({
  id: 2,
  email: 'xsilen@gradii.com'
});
await user2.NewRelation('posts').create({
  id: 1,
  name: 'First post'
});
await user1.NewRelation('posts').create({
  id: 2,
  name: 'Second post'
});
const query = FedacoTestUser.createQuery().join(
  'posts',
  'users.id',
  '=',
  'posts.user_id'
);
ReferenceLooks LikeValue
await query.pluck('posts.name', 'users.id')match`({
  2: 'First post',
  1: 'Second post'
});` |

| await query.pluck('posts.name', 'users.email AS user_email') | match | ({ 'xsilen@gradii.com': 'First post', 'linbolen@gradii.com' : 'Second post' }); |


see also prerequisites

where has on nested self referencing belongs to many relationship

typescript
const user = await FedacoTestUser.createQuery().create({
  email: 'linbolen@gradii.com'
});
const friend = await user.NewRelation('friends').create({
  email: 'xsilen@gradii.com'
});
await friend.NewRelation('friends').create({
  email: 'foo@gmail.com'
});
const results: FedacoTestUser[] = await FedacoTestUser.createQuery()
  .whereHas('friends.friends', (query) => {
    query.where('email', 'foo@gmail.com');
  })
  .get();
ReferenceLooks LikeValue
head(results).emailexactly match'linbolen@gradii.com'

see also prerequisites

where has on self referencing belongs to many relationship

typescript
const user = await FedacoTestUser.createQuery().create({
  email: 'linbolen@gradii.com'
});
await user.NewRelation('friends').create({
  email: 'xsilen@gradii.com'
});
const results: FedacoTestUser[] = await FedacoTestUser.createQuery()
  .whereHas('friends', (query) => {
    query.where('email', 'xsilen@gradii.com');
  })
  .get();
ReferenceLooks LikeValue
head(results).emailexactly match'linbolen@gradii.com'

see also prerequisites

Released under the MIT License.