Get All Relationship Data in AdonisJS - node.js

does anyone know how to retrieve all the data including from the relationship in AdonisJS ? ,
so I want to retrieve the user data from the User Model including the relationship data in the Post Model.
get All users
public async getUsers({ response }: HttpContextContract) {
try {
const data = await User.all()
return response.status(200).send({ "result": data })
} catch(err) {
return response.status(400).json({ error: err.message })
}
}

First, you will need to define the relationships on your model.
A User has many Posts:
export default class User extends BaseModel {
...
#hasMany(() => Post) // 👈 One-to-many relationship
public posts: HasMany<typeof Post>
}
A Post belongs to a User:
export default class Posts extends BaseModel {
...
#belongsTo(() => User) // 👈 a Post belongs to a User
public user: BelongsTo<typeof User>
}
Now, in your query, you can preload the relationship.
const users = await User
.query()
.preload('posts')

First:
You can use belongsTo in User model to make relationship data with Post model
post_model() {
return this.belongsTo("App/Models/Post")
}
Second:
Call the model use query like this:
await User.query()
.with("post_model", builder => {
builder.select("id", "name", "post")
})

Related

TypeGraphQL Field Resolver with mongoose relationship

I have trouble dealing with populating the field using TypeGraphQL.
Situation summary with an example:
TypeGraphQL
TypeDef
#ObjectType()
class User {
...
}
#ObjectType()
class Post {
...
#Field()
user: User
}
Resolver
import { Post, User } from '#/models' // mongoose schema
#Resolver(() => Post)
class PostResolver {
#Query(() =>. Post)
async getPost(id: string) {
return await Post.findById(id);
}
...
#FieldReoslver(() => User)
async user(#Root() post: Post) {
return await User.findById(post.user) // Error Occurs here.
}
}
Mongoose
PostSchema
const PostSchema = new Schema({
...
user: {
type: Schema.ObjectId,
ref: "User",
}
})
I want to populate user field when the data Post is requested, with the field User type.
So, I used #FieldResolverlike above, but I encountered the Type Error because post.user is a type of User, not ObjectId of mongoose.
The user field is a type of ObjectId first when the getPost resolver was executed, but I want to populate this field to User when the client gets the response.
How can I get through this?
Thanks in advance.

Statement .with builder in Adonisjs to select specifict column doesn't work

I want to get data from table relation in Adonisjs. I using .with function to get data from table relation but just for some column, but it doesn't work.
My controller code like this:
const cart = await Shop.query()
.with('products',(builder)=>{
builder.select('id','product_name')
})
.select('id_shop')
.fetch()
return response.json({
status:true,
message: false,
data: cart
})
But the result of code above is only id_shop, like this:
[
{
'id_shop': '1'
'products': []
},
{
'id_shop': '2'
'products': []
}
]
edited
I added my shop's model here:
class Shop extends Model {
static get table()
{
return 'shop'
}
static get primaryKey()
{
return 'id_shop'
}
products ()
{
return this.hasMany('App/Models/Product','id_shop', 'shop_id')
}
}
And my product's model:
class Product extends Model {
static get table()
{
return 'product'
}
static get primaryKey()
{
return 'id_product'
}
}
Whats wrong with my code?
you put wrong hasMany relation in Model
hasMany relationship like this
products ()
{
return this.hasMany('App/Models/Product','shop_id', 'id_shop')
}
or change in controller where you use builder change like this
const cart = await Shop.query()
.with('products',(builder)=>{
builder.select('id_product','product_name')
})
.select('id_shop')
.fetch()
change you id to id_product
you can try this

TypeORM OneToMany filter in relations not effect to result

I have two tables:
#Entity('Reviews')
class Review {
...
#OneToMany((type) => MapCategory, map => map.review)
public categories: MapCategory[];
}
And:
#Entity('MapCategories')
export class MapCategory {
...
#ManyToOne(type => Review, (review) => review.categories)
public review: Review;
}
When I try the filter on 'categories' but the result doesn't filter 'categories' following the key that I already push.
const items = await this.reviewRepository.findAndCount({
relations: ['categories'],
where: {
categories: {
id: 1
}
}
});
We need to use queryBuilder for cases like this since find doesn't allow filtering relations:
const items = await reviewRepository.createQueryBuilder("review")
.leftJoinAndSelect("review.categories", "category")
.where("category.id = :id", { id })
.getManyAndCount()
I prefer to avoid query builder when possible.
There's a workaround for filtering based on relation fields for findOne()/find() methods that I've discovered recently. The problem with filtering related table fields only exists for ObjectLiteral-style where, while string conditions work perfectly.
Assume that we have two entities – User and Role, user belongs to one role, role has many users:
#Entity()
export class User {
name: string;
#ManyToOne(() => Role, role => role.users)
role: Role;
}
#Entity()
export class Role {
#OneToMany(() => User, user => user.role)
users: User[];
}
Now we can call findOne()/find() methods of EntityManager or repository:
roleRepository.find({
join: { alias: 'roles', innerJoin: { users: 'roles.users' } },
where: qb => {
qb.where({ // Filter Role fields
a: 1,
b: 2
}).andWhere('users.name = :userName', { userName: 'John Doe' }); // Filter related field
}
});
You can omit the join part if you've marked your relation as an eager one.

How to insert an entity with OneToMany relation in NestJS?

There is the description how to do this in typeorm official docs https://typeorm.io/#/many-to-one-one-to-many-relations. But I can't do the same in NestJS with Repository and insert method.
I have written these entities (other columns were omitted)
#Entity()
export class News {
#OneToMany(type => NewsImage, image => image.news)
public images: NewsImage[];
}
#Entity()
export class NewsImage {
#ManyToOne(type => News, news => news.images)
public news: News;
}
I have tried something like this
function first() {
const news = new News();
const image = new NewsImage();
news.images = [ image ];
return from(this.newsRepo.insert(news))
.pipe(
switchMap(() => this.imageRepo.insert(image)),
);
}
function second() {
const news = new News();
const image = new NewsImage();
image.news = news;
return from(this.imageRepo.insert(image))
.pipe(
switchMap(() => this.newsRepo.insert(news)),
)
}
It inserts news and image, but image's newsId is null.
Check cascade property
#Entity()
export class News {
#OneToMany(type => NewsImage, image => image.news, { cascade: ['insert', 'update'] })
public images: NewsImage[];
}
Then if you do something like
let news = {
images: [{
date: "",
etc: ""
}],
title: ""
}
If then you call this.repository.save(news) it will save the news and the images. And updates too. Check more docs about this on typeorm docs.
Declaring new News() creates a new entity but does not save it to the database. You first need to insert or .save() the news object and then add it to image.
async function first() {
// you can .save() it however you want, the point is it must be saved to the db
const news = await News.create({ title: 'Async rules the world' }).save()
const image = new NewsImage()
image.news = news // now news has an id from the database
// ...
}

Sequelize - How to set association, save entity and return the saved entity with the associated entity

I am trying to create an association between an existing (user) entity and save the new entity (visit).
I've read the sequelize docs and can't see a better way of doing this than saving the first entity using async/await, then fetching it again passing include as an option. See below.
export const createVisit = async(req, res) => {
req.assert('BusinessId', 'Must pass businessId').notEmpty();
req.assert('UserId', 'Must pass customerId').notEmpty();
const visit = await new Visit({
UserId: req.body.UserId,
BusinessId: req.body.BusinessId,
redemption: false,
})
.save()
.catch((error) => {
res.status(400).send({ error });
});
const visitWithUser = await Visit.findById(visit.id, {include: [{model: User, attributes: ['firstName','lastName','facebook', 'gender','email']}]})
res.status(200).send({ visit: visitWithUser })
};
Is there a way to save the entity and get sequelize to return the saved entity along with any associations?
I think it supports this feature , as per the doc , you can do it like this :
Visit.create({
UserId: req.body.UserId,
BusinessId: req.body.BusinessId,
redemption: false,
}, {
include: [User]
}).then(function(comment) {
console.log(comment.user.id);
});
Here is the git discussion if you want to read.

Resources