Has many through
A classe de relacionamento HasManyThrough permite que você defina um relacionamento has many por meio de um modelo intermediário. Um ótimo exemplo disso é, "um país tem muitas postagens por meio de usuários".
Você não trabalhará diretamente com essa classe. No entanto, uma instância da classe pode ser acessada usando o método Model.$getRelation
.
import {
BaseModel,
hasManyThrough,
HasManyThrough,
} from '@ioc:Adonis/Lucid/Orm'
import Post from 'App/Models/Post'
import User from 'App/Models/User'
class Country extends BaseModel {
@hasManyThrough([() => Post, () => User])
public posts: HasManyThrough<typeof Post>
}
Country.$getRelation('posts').relationName
Country.$getRelation('posts').type
Country.$getRelation('posts').relatedModel()
Métodos/Propriedades
A seguir está a lista de métodos e propriedades disponíveis no relacionamento HasManyThrough
.
type
O tipo do relacionamento. O valor é sempre definido como hasManyThrough
.
class Country extends BaseModel {
@hasManyThrough([() => Post, () => User])
public posts: HasManyThrough<typeof Post>
}
Country.$getRelation('posts').type // 'hasManyThrough'
relationName
O nome do relacionamento. É um nome de propriedade definido no modelo pai.
class Country extends BaseModel {
@hasManyThrough([() => Post, () => User])
public posts: HasManyThrough<typeof Post>
}
Country.$getRelation('posts').relationName // 'posts'
serializeAs
O nome a ser usado para serializar o relacionamento. Você pode defini-lo usando as opções do decorador.
class Country extends BaseModel {
@hasManyThrough([() => Post, () => User], {
serializeAs: 'articles'
})
public posts: HasManyThrough<typeof Post>
}
booted
Descubra se o relacionamento foi inicializado. Caso contrário, chame o método boot
.
boot
Inicialize o relacionamento. As APIs públicas dos modelos Lucid chamam esse método internamente, e você nunca precisa inicializar o relacionamento manualmente.
model
Referência ao modelo pai (aquele que define o relacionamento).
class Country extends BaseModel {
@hasManyThrough([() => Post, () => User])
public posts: HasManyThrough<typeof Post>
}
Country.$getRelation('posts').model // Country
relatedModel
Referência ao modelo de relacionamento. O valor da propriedade é uma função que retorna o modelo relacionado.
class Country extends BaseModel {
@hasManyThrough([() => Post, () => User])
public posts: HasManyThrough<typeof Post>
}
Country.$getRelation('posts').relatedModel() // Post
throughModel
Referência ao throughModel
. O valor da propriedade é uma função que retorna o throughModel.
class Country extends BaseModel {
@hasManyThrough([() => Post, () => User])
public posts: HasManyThrough<typeof Post>
}
Country.$getRelation('posts').throughModel() // User
localKey
A localKey
para o relacionamento. Você deve ler o documento NamingStrategy para saber mais sobre como o nome da chave é computado.
Você também pode definir a localKey
explicitamente. Certifique-se de mencionar o nome da propriedade do modelo e NÃO o nome da coluna do banco de dados.
class Country extends BaseModel {
@column()
public id: number
@hasManyThrough([() => Post, () => User], {
localKey: 'id', // coluna id no modelo "Country"
})
public posts: HasManyThrough<typeof Post>
}
foreignKey
A foreignKey
para o relacionamento. A chave estrangeira é a referência no modelo through e não no modelo relacionado.
Você também pode definir a foreignKey
explicitamente. Certifique-se de mencionar o nome da propriedade do modelo e NÃO o nome da coluna do banco de dados.
class Country extends BaseModel {
@hasManyThrough([() => Post, () => User], {
foreignKey: 'countryId', // coluna countryId no modelo "User"
})
public posts: HasManyThrough<typeof Post>
}
throughLocalKey
A throughLocalKey
para o relacionamento. Geralmente é a chave primária no modelo through.
Você também pode definir a throughLocalKey
explicitamente. Certifique-se de mencionar o nome da propriedade do modelo e NÃO o nome da coluna do banco de dados.
class Country extends BaseModel {
@hasManyThrough([() => Post, () => User], {
throughLocalKey: 'id', // coluna id no modelo "User"
})
public posts: HasManyThrough<typeof Post>
}
throughForeignKey
A throughForeignKey
para o relacionamento. É a chave estrangeira entre o through e o modelo relacionado.
Você também pode definir a throughForeignKey
explicitamente. Certifique-se de mencionar o nome da propriedade do modelo e NÃO o nome da coluna do banco de dados.
class Country extends BaseModel {
@hasManyThrough([() => Post, () => User], {
throughForeignKey: 'userId', // coluna userId no modelo "Post"
})
public posts: HasManyThrough<typeof Post>
}
onQuery
O método onQuery
é um gancho opcional para modificar as consultas de relacionamento. Você pode defini-lo no momento da declaração da relação.
class Country extends BaseModel {
@hasManyThrough([() => Post, () => User], {
onQuery(query) {
query.where('isPublished', true)
}
})
public posts: HasManyThrough<typeof Post>
}
Se você quiser pré-carregar um relacionamento aninhado usando o gancho onQuery
, certifique-se de colocá-lo dentro do condicional !query.isRelatedSubQuery
porque as subconsultas NÃO são executadas diretamente, elas são usadas dentro de outras consultas.
class Country extends BaseModel {
@hasManyThrough([() => Post, () => User], {
onQuery(query) {
if (!query.isRelatedSubQuery) {
query.preload('comments')
}
}
})
public posts: HasManyThrough<typeof Post>
}
setRelated
Defina um relacionamento na instância do modelo pai. Os métodos aceitam o modelo pai como o primeiro argumento e a instância do modelo relacionada como o segundo argumento.
Você deve garantir que ambas as instâncias do modelo estejam relacionadas entre si antes de chamar este método.
const country = new Country()
const post = new Post()
Country.$getRelation('posts').setRelated(country, [post])
pushRelated
O método pushRelated
envia o relacionamento para a matriz de valores de relacionamento existente.
const country = new Country()
Country.$getRelation('posts').pushRelated(country, new Post())
Country.$getRelation('posts').pushRelated(country, new Post())
Country.$getRelation('posts').pushRelated(country, new Post())
country.posts.length // 3
setRelatedForMany
Defina os relacionamentos em mais de um modelo pai. O método aceita uma matriz dos modelos pais como o primeiro argumento e uma matriz de modelos relacionados como o segundo argumento.
O Lucid chama isso internamente com os resultados do pré-carregador.
const countries = [
Country {
id: 1,
},
Country {
id: 2,
},
Country {
id: 3,
}
]
const posts = [
Post {
id: 1,
$extras: {
through_country_id: 1,
}
},
Post {
id: 2,
$extras: {
through_country_id: 1,
}
},
Post {
id: 3,
$extras: {
through_country_id: 2,
}
},
Post {
id: 4,
$extras: {
through_country_id: 3,
}
}
]
Country.$getRelation('posts').setRelatedForMany(countries, posts)
client
Retorna a referência ao HasManyThroughQueryClient. O cliente de consulta expõe a API para buscar linhas relacionadas do banco de dados.
eagerQuery
Retorna uma instância do HasManyThroughQueryBuilder. O construtor de consultas tem a mesma API que o Construtor de consultas do modelo
subQuery
Retorna uma instância do HasManyThroughSubQueryBuilder. As subconsultas não devem ser executadas e são usadas principalmente pelos métodos withCount e whereHas.
Cliente de consulta
O cliente de consulta expõe a API para buscar linhas relacionadas do banco de dados. Você pode acessar o cliente de consulta para um relacionamento usando o método related
.
:::note Você não pode persistir um relacionamento hasManyThrough
diretamente e, em vez disso, usar o relacionamento mais próximo para persistência. Por exemplo: Use o relacionamento posts
no modelo User
para criar posts relacionados. :::
const country = await Country.find(1)
country.related('posts') // HasManyThroughClientContract
Usando o cliente de consulta, você pode acessar a instância do construtor de consulta para fazer consultas relacionadas.
Construtor de consulta
O HasManyThroughQueryBuilder tem os seguintes métodos adicionais em cima de um construtor de consulta de modelo padrão.
Você pode acessar o construtor de consulta de relacionamento da seguinte forma:
const country = await Country.find(1)
country.related('posts').query() // HasManyThroughQueryBuilder
groupLimit
O método groupLimit
usa funções de janela SQL para adicionar um limite a cada grupo durante o pré-carregamento do relacionamento. Leia o guia de pré-carregamento para saber por que e quando você precisa do método groupLimit
.
await Country.query().preload('posts', (query) => {
query.groupLimit(10)
})
groupOrderBy
Adicione uma cláusula order by à consulta de limite de grupo. O método tem a mesma API que o método orderBy
no construtor de consultas padrão.
:::note Você só precisa aplicar groupOrderBy
ao usar o método groupLimit
. :::
await Country.query().preload('posts', (query) => {
query
.groupLimit(10)
.groupOrderBy('posts.created_at', 'desc')
})