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

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.

Related

Prisma One-to-One update Parent or update Parent and Child

I have a Parent Child (One-To-One) Relationship like this:
model Account {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
billingAddress Address?
name String
##map("Accounts")
}
model Address {
id Int #id #default(autoincrement())
city String?
country String?
postalCode Int?
state String?
street String?
accountId Int #unique
account Account #relation(fields: [accountId], references: [id])
}
I want to be able to Update the Parent Record without the need of updating also the Child Record. Furthermore, it would be great, if I can update the Parent Record and the Child Record at the same time. Right now I am getting an Error when only trying to send the Data for the Parent Record.
Here are my DTOs to Create and Edit the Entities:
Create / Edit Account:
export class CreateAccountDto {
#IsString()
#IsOptional()
name: string;
#IsOptional()
billingAddress?: CreateAddressDto;
}
Create / Edit Addresss:
export class EditAddressDto {
#IsString()
#IsOptional()
city?: string;
#IsString()
#IsOptional()
country?: string;
#IsNumber()
#IsOptional()
postalCode?: number;
#IsString()
#IsOptional()
state?: string;
#IsString()
#IsOptional()
street?: string;
#IsInt()
#IsOptional()
accountId: number;
}
I'm creating and editing the Account like this:
async editAccount(accountId: number, dto: EditAccountDto) {
let account;
console.log({dto})
account = await this.prisma.account.update({
where: {
id: accountId
},
data: {
...dto,
billingAddress: {
update: {
...dto.billingAddress
}
}
},
include: {
billingAddress: true
}
});
console.log(account)
return account;
}
When i try to Edit the Account with the following Data
{
"name": "Test Account Create2",
"billingAddress": {
"id": 2,
"city": "Dortmund",
"state": "NRW",
"postalCode": 44442,
"country": "Germany",
"street": "Benninghofer Heide 63",
"accountId": 10000001
}
}
i am getting the following Error:
Unknown arg `accountId` in data.billingAddress.update.accountId for type AddressUncheckedUpdateWithoutAccountInput. Did you mean `country`? Available args:
type AddressUncheckedUpdateWithoutAccountInput {
id?: Int | IntFieldUpdateOperationsInput
city?: String | NullableStringFieldUpdateOperationsInput | Null
country?: String | NullableStringFieldUpdateOperationsInput | Null
latitude?: Decimal | NullableDecimalFieldUpdateOperationsInput | Null
longitude?: Decimal | NullableDecimalFieldUpdateOperationsInput | Null
postalCode?: Int | NullableIntFieldUpdateOperationsInput | Null
state?: String | NullableStringFieldUpdateOperationsInput | Null
street?: String | NullableStringFieldUpdateOperationsInput | Null
}
at Document.validate (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:29297:20)
at serializationFn (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:31876:19)
at runInChildSpan (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:25100:12)
at PrismaService._executeRequest (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:31883:31)
at consumer (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:31810:23)
at C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:31815:51
at AsyncResource.runInAsyncScope (node:async_hooks:199:9)
at C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:31815:29
at runInChildSpan (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:25100:12)
at PrismaService._request (C:\Users\Simon\IdeaProjects\crm-tool\crm-backend\node_modules\#prisma\client\runtime\index.js:31812:22)
The error says, you are not allowed to specify accountId when you are updating the address in this way. You can just remove it from your DTO and everything should be fine.

how to count records in prisma io?

I am executing a query but the result of the account adds the letter "n", I don't understand why when I execute the query in mysql console it shows it correctly.
const client = await prisma.$queryRaw`SELECT idClient, COUNT(*) as totalCount FROM sales GROUP BY idClient`;
console.log(client)
executing the same query but in heidiSQL.
Numbers with an n postfix denote the BigInt type in JavaScript MDN. This is probably due to some queryRaw changes that were made in v4.0.0. The Integer results are now being returned as BigInt. You must change your code to handle the new type. See this section of the upgrade guide.
Example: Given this Schema file
model Customers {
id Int #id #default(autoincrement())
customerName String
country String
}
and this script file
async function main() {
await prisma.customers.createMany({
data: [
{
country: 'USA',
customerName: 'John Doe',
},
{
country: 'Germany',
customerName: 'Jane Doe',
},
{
country: 'Canada',
customerName: 'Adams Doe',
},
],
});
const clients = await prisma.customers.groupBy({
by: ['country'],
_count: true,
});
console.log("Using normal client query with groupBy ")
console.log(clients);
const clientsWithRawQuery =
await prisma.$queryRaw`SELECT Country, COUNT(country) as totalCount
FROM Customers GROUP BY Country`;
console.log("\n Using queryRaw")
console.log(clientsWithRawQuery);
console.log(
'Before Conversion: Typeof Count:',
typeof clientsWithRawQuery[0].totalCount
);
clientsWithRawQuery.forEach((countryObject) => {
countryObject.totalCount = Number(countryObject.totalCount);
});
console.log(
'After Conversion: Typeof Count:',
typeof clientsWithRawQuery[0].totalCount
);
console.log('\n', clientsWithRawQuery)
}
The output is
Using normal client query with groupBy
[
{ _count: 2, country: 'Canada' },
{ _count: 2, country: 'Germany' },
{ _count: 2, country: 'USA' }
]
Using queryRaw
[
{ Country: 'Canada', totalCount: 2n },
{ Country: 'Germany', totalCount: 2n },
{ Country: 'USA', totalCount: 2n }
]
Before Conversion: Typeof Count: bigint
After Conversion: Typeof Count: number
[
{ Country: 'Canada', totalCount: 2 },
{ Country: 'Germany', totalCount: 2 },
{ Country: 'USA', totalCount: 2 }
]

mongodb aggregate $nin condition with another collection

SELECT * FROM collection1 c1 WHERE c1.mobileNum NOT IN(SELECT mobileNumer FROM collection2) ORDER by c1.createdAt DESC
collection 1 :
=============
[{
name: 'abc',
mobileNum: 1234,
createdAt: DateTime
},{
name: 'efg',
mobileNum: 5678,
createdAt: DateTime
},
{
name: 'ijk',
mobileNum: 222222,
createdAt: DateTime
},
{
name: 'mno',
mobileNum: 33333,
createdAt: DateTime
}
]
collection 2 :
=============
[{
age: 24,
mobileNumer : 1234,
createdAt: DateTime
},{
age: 25,
mobileNumer : 0000,
createdAt: DateTime
},
{
age: 25,
mobileNumer : 1111,
createdAt: DateTime
}]
first have the mysql query.
second i have the mongodb collections are collection1 and collection 2.
need to convert the mysql statement into equivalent mongodb aggregate query.
can someone help?
$lookup - Join collection 1 (mobileNum) with collection 2 (mobileNumer).
$match - Filter document with matchedDocs is empty array ($size: 0).
$sort - Sort by createdAt descending.
$unset - Remove matchedDocs field.
db.col1.aggregate([
{
"$lookup": {
"from": "col2",
"localField": "mobileNum",
"foreignField": "mobileNumer",
"as": "matchedDocs"
}
},
{
$match: {
"matchedDocs": {
$size: 0
}
}
},
{
$sort: {
createdAt: -1
}
},
{
"$unset": "matchedDocs"
}
])
Sample Mongo Playground

TypeORM inserts an additional empty row for no reason when saving an entity

I've been making an application for tracking user finances with NestJS, TypeORM and MySQL on the backend and all was going swell until I ran into a brick wall which was saving an entity called Financialchange which represents one unit of financial expense or gain. The problem is that in a table that represents a many to many relationship of user defined tags with the financial change, an empty row is inserted every time I save this entity along with the row that is correctly inserted.
The saving is done like this:
const financialChange = await this.financialChangeRepository.save({
amount: payload.amount,
description: payload.description,
expense: payload.expense,
paymentSourceId: payload.paymentSourceId,
appUserId: payload.appUserId,
createdAt: format(new Date(), "yyyy-MM-dd hh:mm:ss")
});
payload.tagIds.forEach(async (tagId) => {
await this.financialChangeTagRepository.save({
financialChangeId: financialChange.id,
tagId
});
});
An example of sent data:
mutation {
addFinancialChange(
financialChange: {
appUserId: 1
amount: 200
description: "Description"
expense: true
paymentSourceId: 1
tagIds: [1]
}
)
}
And when selecting data from the many to many table I get this:
The entity data is as follows, first the MySQL table creation:
CREATE TABLE financialchange (
id INT AUTO_INCREMENT PRIMARY KEY,
amount DOUBLE,
createdAt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(),
description VARCHAR(255),
expense BOOLEAN,
paymentSourceId INT,
appUserId INT,
FOREIGN KEY (appUserId) REFERENCES appuser(id),
FOREIGN KEY (paymentSourceId) REFERENCES paymentsource(id)
);
And then the TypeORM entity in Nest:
#Index("appUserId", ["appUserId"], {})
#Index("paymentSourceId", ["paymentSourceId"], {})
#Entity("financialchange", { schema: "finapp" })
export class Financialchange {
#PrimaryGeneratedColumn({ type: "int", name: "id" })
public id?: number;
#Column("double", { name: "amount", nullable: true, precision: 22 })
public amount?: number | null;
#Column("datetime", { name: "createdAt", default: () => "CURRENT_TIMESTAMP" })
public createdAt?: Date;
#Column("varchar", { name: "description", nullable: true, length: 255 })
public description?: string | null;
#Column("tinyint", { name: "expense", nullable: true, width: 1 })
public expense?: boolean | null;
#Column("int", { name: "paymentSourceId", nullable: true })
public paymentSourceId?: number | null;
#Column("int", { name: "appUserId", nullable: true })
public appUserId?: number | null;
#ManyToOne(() => Appuser, (appuser) => appuser.financialchanges, {
onDelete: "NO ACTION",
onUpdate: "NO ACTION"
})
#JoinColumn([{ name: "appUserId", referencedColumnName: "id" }])
public appUser?: Appuser;
#ManyToOne(
() => Paymentsource,
(paymentsource) => paymentsource.financialchanges,
{ onDelete: "NO ACTION", onUpdate: "NO ACTION" }
)
#JoinColumn([{ name: "paymentSourceId", referencedColumnName: "id" }])
public paymentSource?: Paymentsource;
#OneToMany(
() => Financialchangetag,
(financialchangetag) => financialchangetag.financialChange
)
public financialchangetags?: Financialchangetag[];
}
It is in concept defined as having N amounts of tags binded to it, which is why I have created a table that represents a many to many relation called financialchangetags:
CREATE TABLE financialchangetag (
id INT AUTO_INCREMENT PRIMARY KEY,
financialChangeId INT,
tagId INT,
FOREIGN KEY (financialChangeId) REFERENCES financialchange(id),
FOREIGN KEY (tagId) REFERENCES tag(id)
);
#Index("financialChangeId", ["financialChangeId"], {})
#Index("tagId", ["tagId"], {})
#Entity("financialchangetag", { schema: "finapp" })
export class Financialchangetag {
#PrimaryGeneratedColumn({ type: "int", name: "id" })
public id?: number;
#Column("int", { name: "financialChangeId", nullable: true })
public financialChangeId?: number | null;
#Column("int", { name: "tagId", nullable: true })
public tagId?: number | null;
#ManyToOne(
() => Financialchange,
(financialchange) => financialchange.financialchangetags,
{ onDelete: "NO ACTION", onUpdate: "NO ACTION" }
)
#JoinColumn([{ name: "financialChangeId", referencedColumnName: "id" }])
public financialChange?: Financialchange;
#ManyToOne(() => Tag, (tag) => tag.financialchangetags, {
onDelete: "NO ACTION",
onUpdate: "NO ACTION"
})
#JoinColumn([{ name: "tagId", referencedColumnName: "id" }])
public tag?: Tag;
}
And the tag table is defined in this manner:
CREATE TABLE tag (
id INT AUTO_INCREMENT PRIMARY KEY,
description VARCHAR(255)
);
#Entity("tag", { schema: "finapp" })
export class Tag {
#PrimaryGeneratedColumn({ type: "int", name: "id" })
public id?: number;
#Column("varchar", { name: "description", nullable: true, length: 255 })
public description?: string | null;
#OneToMany(
() => Financialchangetag,
(financialchangetag) => financialchangetag.tag
)
public financialchangetags?: Financialchangetag[];
}
I have no clue why this is, I have tried inserting a record into financialchange with a transaction manager and through other methods of saving data that TypeORM offers, but I still get an empty row in my M:N table.

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)