mongodb aggregate $nin condition with another collection - mysql

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

Related

Sequlize bulkCreate with updateOnDuplicates return all values(duplicated and not duplicated)

I have this code
const users = await User.bulkCreate(newUsers, {
updateOnDuplicate: ['name'],
});
Its query return all values in response like
[
{
id:1,
name: 'Andrew'
},
{
id:2,
name: 'John'
},
{
id:3,
name: 'Andrew'
},
]
But in database that query writes only unique value. Only 1 Andrew and 1 John.
I need to return only 2 records not 3

MySQL query equivalent in MongoDB

I am looking for help from someone who is expert on Mongodb Development.
Below is My MySQL query :
select column_1,column_2,group_concat(column3 order by column4 asc ) as data_1 , group_concat(column5 order by column4 asc) as data_2
from table_name
where column4>=DATE_SUB(NOW(),INTERVAL 15 MINUTE)
group by column_1,column_2
Basically I want data for past 15 minutes and group concat column data based on group by certain columns.
Please help me get through this query.
Below is the sample data stored in Mongodb
{
"_id" : ObjectId("6364fd1ae855d15c22632077"),
"column3" : 1,
"column_1" : 123456789,
"column5" : "xyz",
"source" : 1,
"column_2" : NumberLong("22116755"),
"column4" : ISODate("2022-11-04T11:51:55Z")
}
Try this one:
db.collection.aggregate([
{ $match: { column4: { $gte: new Date(ISODate().getTime() - 1000 * 60 * 15) } } },
{ $sort: { column4: 1 } },
{
$group: {
_id: { column_1: "$column_1", column_2: "$column_2" },
data: { $push: { data_1: "$column3", data_2: "$column5" } },
}
},
{ $replaceWith: { $mergeObjects: ["$_id", "$data"] } }
])

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 }
]

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.

Sequelize: get MIN/MAX Dates from association

I have to tables - one for events and another one for the dates (start-end) this event is "active".
id name
-- ----
1 event 1
2 event 2
And then the EventDates
eventId start end
------- ----- ---
1 2018-01-14 2018-01-15
1 2018-01-17 2018-01-18
2 2018-02-14 2018-02-18
Events and EventDates are setup using hasMany()
Event.DATES = Event.hasMany(models.EventDates, {
as: 'dates',
foreignKey: 'eventId',
});
Querying for all Events including the EventDates like this:
await Event.findAll({
include: [{ association: Event.DATES }]
});
returns a nested Event list with all the EventDates - great.
[
{
id: 1,
name: 'event 1',
dates: [
{
start: '2018-01-14',
end: '2018-01-15',
},
{
start: '2018-01-17',
end: '2018-01-18',
},
],
},
{
id: 2,
name: 'event 2',
dates: [
{
start: '2018-02-14',
end: '2018-02-18',
},
],
}
]
But now I want to add a maxEndDate to an Event so I can check if it still active or if all EventDates are in the past. I can do that manually adding another LEFT JOIN like this:
# ...
LEFT OUTER JOIN (SELECT eventId, MAX(end)
FROM `EventDates`
GROUP BY eventId) dates
ON `Event`.`id` = `dates`.`eventId`
# ...
But how could I achieve the same thing with Sequelize?
[
{
id: 1,
name: 'event 1',
maxEndDate: ??,
dates: [
{
start: '2018-01-14',
end: '2018-01-15',
},
{
start: '2018-01-17',
end: '2018-01-18',
},
],
},
{
id: 2,
name: 'event 2',
maxEndDate: ??,
dates: [
{
start: '2018-02-14',
end: '2018-02-18',
},
],
}
]
It very tricky to get result with group by and has many association , but at last I found the way and here it is :
Event.findAll({
raw : true,
attributes : [ 'Event.*' , 'EventDates.eventId' , [sequelize.fn('max', sequelize.col('EventDates.end')),'end']],
include : {
model : EventDates ,
attributes :[]
},
group : ['Event.id','EventDates.eventId']
})
I think you can achieve your last out put that by this , I haven't tried this but this is the way you can go ahead
Event.findAll({
raw : true,
attributes : [ 'Event.*' , 'dates.*' , 'EventDates.eventId' , [sequelize.fn('max', sequelize.col('EventDates.end')),'end']],
include : [
{
model : EventDates ,
attributes :[]
},
{
model : EventDates ,
as : 'dates',
required : false,
separate : true
}
]
group : ['Event.id','EventDates.eventId']
})