how to serialize using entityframework ICollection 'my way' - json

i have
table of users. - key IdUser , and other colsumns...
table of perms key IdPerm, and column PermName
and table of UserPerms key IdUserPermand columns IdPerm IdUser and Value
so when i select this user using Entity Framework and return it as json from api i get
{ IdUser : 1, login: "xx", name: "xxx",
UserPerms : [
{IdUserPerm : 1, IdUser : 1, idPerm: 1, value: 1, idPermNavigation: {idperm: 1, PermName:"Feature1"}}
{IdUserPerm : 2, IdUser : 1, idPerm: 2, value: 2, idPermNavigation: {idperm: 2, PermName:"Feature2"}}
{IdUserPerm : 3, IdUser : 1, idPerm: 3, value: 5, idPermNavigation: {idperm: 3, PermName:"Feature3"}}
]
}
is there any way i can configure this json serializer or .net core EF so i get result
UserPerms :{permname:value, next..}
so in this example to get
{IdUser:1, login:"xx", name:"yy",..., UserPerms:{Feature1:1, Feature2:2, Feature3:5}}
or any way to redesign DB so EF got this as 'default' ?
thanks and regards !

You can workaround by create DTO like
class UserPermResult {
int IdUser;
string Login;
...
ICollection<Perm> UserPerms;
}
class Perm {
string Name;
int Value;
}
and use Select linQ
values.Select(f=> new UserPermResult {
IdUser = f.IdUser,
...
UserPerms = f.UserPerms.Select(p=> new Perm{
Name = p.IdPermNavigation?.PermName,
Value = p.Value
})
});

Related

Gorm - query on one to many relation does not return required results

In relation store has many products.
I created the struct like this:
type Store1 struct {
StoreSeq uint `json:"storeSeq" gorm:"primaryKey; column:store_seq"`
NickName string `json:"nickName" gorm:"column:nick_name"`
RegDate *domain.CTime `json:"regDate" gorm:"column:reg_date"`
Product1 []Product1 `json:"products" gorm:"foreignKey:ProductSeq"`
}
func (*Store1) TableName() string {
return "store"
}
type Product1 struct {
ProductSeq uint `json:"productSeq"`
ProductTitle string `json:"productTitle"`
RegDate *domain.CTime `json:"regDate"`
StoreSeq *uint `json:"store_seq" `
}
func (*Product1) TableName() string {
return "product"
}
and I queried it like this:
pro := new(entity.Product1)
store := new(entity.Store1)
orm.GetData().
Model(pro).
Preload("Product1").
Joins("left join store on store.store_seq = product.store_seq").
Where("store.store_seq = ?", 1).
Find(&store)
In my database table has data like this
STORE
1 testStore 2022-03-01 23:19:18
PRODUCT
1 1 test 2022-03-01 23:19:18
2 1 testaaa 2022-03-01 23:19:18
I expect
"storeSeq": 1,
"nickName": "",
"regDate": "2022-03-01 23:19:18",
"products": [
{
"productSeq": 1,
"productTitle": "test",
"regDate": "2022-03-01 23:19:18",
"store_seq": 1
},
{
"productSeq": 2,
"productTitle": "testaaa",
"regDate": "2022-03-01 23:19:18",
"store_seq": 1
}
]
but it only returns one result:
"storeSeq": 1,
"nickName": "",
"regDate": "2022-03-01 23:19:18",
"products": [
{
"productSeq": 1,
"productTitle": "test",
"regDate": "2022-03-01 23:19:18",
"store_seq": 1
}
]
I checked the SQL query then I found that it executes two SQL queries
[1.725ms] [rows:2] SELECT `product`.`product_seq`,`product`.`product_title`,`product`.`reg_date`,`product`.`store_seq` FROM `product` WHERE `product`.`product_seq` = 1
AND
[6.370ms] [rows:1] SELECT `product`.`product_seq`,`product`.`product_title`,`product`.`reg_date`,`product`.`store_seq` FROM `product` left join store on store.store_seq = product.store_seq WHERE store.store_seq = 1
I don't know why it executes the first SQL query; I want it to execute the second query only.
I have no idea and this is my firstime to use Golang with gorm with serverless framework
I found out that I make wrong releation between product and store
store has many produts so I have to relation product1 []Product1 foriegnKey
with storeSeq but i set foriegnkey as product_seq
and i also find out that execute two queries it because of preload option.

Prisma 2 - Unkown arg 'where' in select.fruit.where for type UserFruit. Did you mean 'select'? Available args

Trying to query in prisma and filter results from a related object but get the error:
Unknown arg 'where' in select.fruit.where for type UserFruit. Did you
mean 'select'? Available args fruit{}
async findShops(req) {
const userId = parseInt(req.params.id);
const shop = await prisma.shop.findMany({
select: {
id: true,
name: true,
logo: true,
fruit:{
select:{
id:true,
userId:true,
fruitNumber:true,
created: true,
updated: true,
},
where: {
userId: userId
}
}
}
})
return shop;
};
example payload expected:
[
{ id: 1001, name: 'test1', logo: 'log.png', fruit: null },
{ id: 1002, name: 'test2', logo: 'log2.jpg', fruit: null },
{ id: 1003, name: 'test3', logo: 'log3.jpg', fruit: null },
{
id: 1005,
name: 'test4',
logo: 'log4.png',
fruit: {
id: '62450ee5-e75d-4a67-8d79-120d11ddf508',
userId: 111,
fruitNumber: '123456',
created: 2022-07-01T06:39:52.924Z,
updated: 2022-07-01T06:39:52.936Z
}
},
{
id: 1004,
name: 'test5',
logo: 'log5.jpg',
fruit: {
id: '20e9af37-2e6f-4070-8475-c5a914f311dc',
userId: 111,
fruitNumber: '123878',
created: 2022-07-01T07:21:27.898Z,
updated: 2022-07-01T07:21:27.901Z
}
}
]
I can easily achieve the expected output by not having the "where" but I need it because the fruit object can contain more than 1 object so I need to filter by userId e.g.
fruit: {
id: '62450ee5-e75d-4a67-8d79-120d11ddf508',
userId: 111,
fruitNumber: '123456',
created: 2022-07-01T06:39:52.924Z,
updated: 2022-07-01T06:39:52.936Z
},
{
id: '62450ee5-e75d-4a67-8d79-120d11ddf508',
userId: 999,
fruitNumber: '123456',
created: 2022-07-01T06:39:52.924Z,
updated: 2022-07-01T06:39:52.936Z
}
For the fruit object I need nulls and anything that matches the userId and based on design it should only ever be 1 record for each shop for the specific user.
At somepoint my code seemed to work but after I did a prisma generate it stopped working. Is there another way I can achieve the same result or is there someway to fix this?
Note:version info below.
model UserFruit {
id String #id #default(uuid())
fruitNumber String #map("fruit_number")
shopId Int #unique #map("shop_id")
userId Int #map("user_id")
created DateTime #default(now())
updated DateTime #updatedAt
fruit Fruit #relation(fields: [fruitId], references: [id])
##unique([userId, fruitId], name: "userFruit")
##map("user_Fruit")
}
model Shop {
id Int #id #default(autoincrement())
name String #unique
logo String
created DateTime #default(now())
updated DateTime #updatedAt
fruit UserFruit?
##map("Shop")
}
model User {
id Int #id #default(autoincrement())
created DateTime #default(now())
updated DateTime #updatedAt
uid String #unique
email String #unique
phone String #unique
firstName String #map("first_name")
lastName String #map("last_name")
dob DateTime?
gender String?
roleId Int #default(1) #map("role_id")
role Role #relation(fields: [roleId], references: [id])
##map("user")
}
Why not do a nested where at the top level to only search for shops whose fruit has the userId you need, rather than doing a nested select? It should make your query simpler and also solve your problem.
const userId = parseInt(req.params.id);
const shop = await prisma.shop.findMany({
select: {
id: true,
name: true,
logo: true,
fruit: {
select: {
id: true,
userId: true,
fruitNumber: true,
created: true,
updated: true,
},
// Removed the nested "where" from here
},
},
where: {
// One of the following conditions must be true
OR: [
// Return shops who have a connected fruit AND
// the fruit's "userId" attribute equals the variable "userID"
{
fruit: {
is: {
userId: userId,
// Can also simplify this to the below line if you want
// userId
},
},
},
// Return shops who do not have a connected fruit
// this will be true if "fruitId" is null
// could also write this as {fruit: {is: {}}}
{
fruitId: {
equals: null,
},
},
],
},
});
This query should output an array of shops where the connected fruit model's userId property equals your userId variable.

Retrive all the value that satisfy the condition of first table

I have two tables users and location. I need to join both tables
what i need is get all the area number of all the users which are present in the user table.
ie user 1 has 3 entries in the second table so i need to join the table in such a way that is,
id1 = 1
area = 2,3
area 2 is repeating so do not include it twice
i tried the join but now getting the correct way to doing it.
What i tried?
$location = User::
join('addresses','users.id1','=','addresses.id1') ->select('users.id1','addresses.area')
->get();
Expected Output
User 1 -> area ->2,3
Here are the two ways to do this.
Firstly you can use Laravel relationship:-
In your model User create relationship:-
function addresses()
{
return $this->hasMany(Address::class, 'id1', 'id1');
}
Now in your User controller you can get User addresses (areas) like this
$users = User::with('addresses')->get();
dd($users->toArray());
This will print something like this
[
{
id1: 1,
name: abaa
pwd: 12345
addresses: [
{
id2: 1,
id1: 1,
area: 2
},
{
id2: 2,
id1: 1,
area: 3
},
{
id2: 3,
id1: 1,
area: 3
}
]
},
{
...
}
]
Second you can use Laravel relationship:-
$builder = new User;
$builder->join('addresses','users.id1','=','addresses.id1')
->selectRaw("users.*, GROUP_CONCAT(DISTINCT addresses.area SEPARATOR ',') as distinct_areas")
->groupBy("users.id1")
->get();
This query will give you result something like this
[
{
id1: 1,
name: abaa,
pwd: 12345,
distinct_areas: 2,3
},
{
...
}
]
I think this will help you.

Sequelize attribute with alias seems undefined

I'm trying to get id of AttributeValue model with an alias of attribute_value_id as below but attribute_value_id seems undefined in otherOptions constant.
const otherOptions = await AttributeValue.findAll({
where: {
id: {
[Op.in]: attributeValueIds
} },
attributes: [
['id', 'attribute_value_id'],
'attribute_id',
'value'
]
})
I'm fallowing sequlize documantation about querying and the below query is built by sequelize but there is no alias attribute in the resulting object.
SELECT `id` AS `attribute_value_id`, `attribute_id`, `value` FROM `attribute_values` AS `attribute_value` WHERE `attribute_value`.`id` IN (1, 1, 1, 1, 19);
You can get it with otherOptions[0].getDataValue('attribute_value_id')

How to return nested JSON in node js

I have three different tables.
1. Order details (id, itemId,date,userId)
2. Item details (id, itemName, quantity)
3. User details (id, userName)
I want to return a JSON as:
{[
{
orderId = 1,
items = [
{
itemId = 1,
itemName = ITEM_DEMO,
},
{
itemId = 2,
itemName = ITEM_DEMO2,
}
],
userDetails = {
userId = 1,
userName = TEST_USER
}
}
]}
How can we do this in Node JS. Im using MySQL.
First of all you should read about object and json in javascript.
For parsing your data from mySql to json do the following steps:
Create an object that is filled with your data from mySql.
const ArrayObjectFilledWithMysqlData = [
{
orderId: 1,
items: [{
itemId: 1,
itemName: ITEM_DEMO,
},
{
itemId: 2,
itemName: ITEM_DEMO2,
}]
},
{
userDetails: {
userId: 1,
userName: TEST_USER
}
}
]
Parse the Array to json.
const jsonFromData = JSON.stringify(ArrayObjectFilledWithMysqlData)