Excecute a query from MySql to Mongodb - mysql

I am trying to run a query on MongoDb-3.2, but I cant get the results that I want.
This is the original query on MySQL:
SELECT c.cdg,ten,IFNULL(efe,0) as efe,tcreated_at
FROM
(SELECT numB as cdg,COUNT(*) as ten,created_at as tcreated_at
FROM dat_records cdr
WHERE LEFT(numB,#longitud)= #cod_prov AND type=4
GROUP BY cdg ) c
LEFT JOIN
(SELECT COUNT(*) as efe, numB,MAX(created_at) as ecreated_at
FROM dat_records
WHERE LEFT(numB,#longitud)= #cod_prov AND dat_records.time > 1 AND type=4 GROUP BY numB) d
ON c.cdg=d.numB AND tcreated_at=ecreated_at
WHERE ten > 40
GROUP BY c.cdg
HAVING (efe/ten)*100 <30
ORDER BY ten DESC
LIMIT 25
This is what I am trying on MongoDB-3.2:
I have this, but I need to include all documents who has or not "efectivas". So, I know the 3rd match is affecting results.
db.archivos_cdr.aggregate([
{$match: {$and:[{numB:{$regex:'^7' }},{ tipo_llamada:4}]}},
{$group : {_id : "$numB",tentativas: { $sum: 1 }}},
{$match:{'tentativas': {'$gt': 4}}},
{$sort:{"tentativas":-1}},
{$lookup:{"from": "archivos_cdr","localField": "_id","foreignField": "numB","as": "efecList" } },
{ "$unwind": "$efecList" },
{ "$match": { $or:[ {"efecList.tiempo_conv": {"$gt": 0}}] }},
{
"$group": {
"_id": "$efecList.numB",
"tentativas": { "$first": "$tentativas" },
"efectivas": { "$sum": 1 }
}
}
])
I have this result:
{ "_id" : "123456789", "tentativas" : 5, "efectivas" : 4 }
But this is what I want:
{ "_id" : "123456789", "tentativas" : 5, "efectivas" : 4 }
{ "_id" : "325987741", "tentativas" : 13, "efectivas" : 0 }
Thanks for your help!

I have my own answer!!!! I got it!!!!!
db.dat_records.aggregate([
{$match: {$and:[{numB:{$regex:'^7' }},{ tipo_llamada:4}]}},//WHERE LEFT(numB,#longitud)= #cod_prov AND type=4
{$group : {_id : "$numB",//GROUP BY cdg
ten: { $sum: 1 },//COUNT(*) as ten
efec:{$sum:{$cond:[{$gt:["$tiempo_conv",0]},1,0]}},//
efec_ner:{$sum:{$cond:[{$setIsSubset:[["$causa_fallo"],causas_efec_ner]},1,0]}}}//COUNT(*) as efe_ner
},
{$match: { 'ten': {$gt: 40} }},//WHERE ten > 40
{$sort:{"ten":-1}},//ORDER BY ten DESC
{ $project: {_id:0,
numeracion:"$_id",
ten: 1,
efec: 1,
efec_ner: 1,
asr: { $divide:[{$multiply: [ "$efec", 100 ]},"$ten"]},
ner: { $divide:[{$multiply: [ "$efec_ner", 100 ]},"$ten"]},
peso: { $multiply:[{$divide: [ "$ten", total_inter ]},100]} }},
{$match:{ $and:[ {"asr":{$lt:30}},//HAVING (efe/ten)*100 <30
{"peso":{$gt:10}} ]}},//I had add this tent/total)>10(*100
])
This is the result (All I need!!!!):
{ "ten" : 13, "efec" : 0, "efec_ner" : 13, "numeracion" : "12364567", "asr" : 0, "ner" : 100, "peso" : 10.56 }
Thanks anyway!!!! I hope this helps someone.

Related

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

Laravel calculate sum of two columns with a condition

I have this Warehouse collection I got from the database
[
{
"id": 1,
"warehouse": "India"
"sales": [
{
"id": 1,
"warehouse_id": 1,
"price": "120.00",
"quantity": 1000,
"status": 1
},
{
"id": 2,
"warehouse_id": 1,
"price": "20.00",
"quantity": 100,
"status": 1
},
{
"id": 3,
"warehouse_id": 1,
"price": "40.00",
"quantity": 1000,
"status": 2
}
]
},
{
"id": 2,
"warehouse": "Malaysia"
"sales": [
{
"id": 4,
"warehouse_id": 2,
"price": "160.00",
"quantity": 100,
"status": 1
}
]
}
]
I want to calculate the total income for each warehouse
Total income is calculated based on the sale status attribute
If status = 1, the products are delivered so it should add price * quantity to the total income
If status = 2, the products are returned so it should subtract price * quantity from the total income
A basic example for India warehouse:
total_income = 120*1000 + 20*100 - 40*1000
And for Malaysia:
total_income = 160*100
I tried using Warehouse::withSum(); but it didn't get me anywhere.
I'm wondering if there's a good way to do with collections
You could just pass a few callbacks to the collection's sum() method:
$warehouses_collection->map(function ($warehouse) {
return (object) [
'id' => $warehouse->id,
'warehouse' => $warehouse->warehouse,
'total_income' => collect($warehouse->sales)->sum(function ($sale) {
((int) $sale->price) * $sale->quantity * ($sale->status == 1 ? 1 : -1)
})
];
});
WithSum is a bit tricky to use here but calling withAggregate works.
Warehouse::withAggregate(
'sales as total_income',
'sum(case when status = 1 then price * quantity when status = 2 then price * quantity * -1 else 0 end)'
)->get()
I honestly would go the route below:
Obviously my solution would have to be modified slightly if you aren't using completely whole numbers (as in your example). The if/else can be broadened out as well if you have more then the 2 statuses.
$total_income = 0;
foreach($warehouses as $warehouse)
{
foreach($warehouse->sales as $sale)
{
if($sale->status = 1)
{
$total_income += ($sale->price * $sale->quantity);
}else{
$total_income -= ($sale->price * $sale->quantity);
}
}
}
This is a crude example of what how I would do it. It seems that each 'warehouse' has a different location ex. India vs. Malaysia. My example is more about the grand total, but you could always save the results of each different warehouse in different variables, or as a key/value pair in an array (which is how I would go).

How to select field from a sibling array?

I would like to select value ('Value') from element with FieldName=Field4 where value ('Value') is null from element with FieldName=Field2.
{
"FormName":"Form1",
"Id": "ID1",
"Module":{
"ModuleType":"Form",
"Layout":"Vertical",
"ControlList":[
{
"ControlType":"Widget",
"Layout":"Vertical",
"FieldList":[
{
"FieldType":"TextBox",
"FieldName":"Field1",
"Value":"field1"
},
{
"FieldType":"TextBox",
"FieldName":"Field2",
"Value":null
},
{
"FieldType":"TextBox",
"FieldName":"Field1",
"Value":"field3"
}
]
},
{
"ControlType":"Widget",
"Layout":"Vertical",
"FieldList":[
{
"row":[
{
"FieldType":"TextBox",
"FieldName":"Field3",
"Value":"field3"
},
{
"FieldType":"TextBox",
"FieldName":"Field4",
"Value":"field4"
}
]
}
]
}
]
}
}
I understand how to get the right dataset:
select
form.Id
from
`test` as form
where
any cl in form.Module.ControlList satisfies
any fl in cl.FieldList satisfies fl.FieldName = 'Field2' AND fl.`Value` is null
end
end;
... returning:
[
{
"Id": "ID1"
}
]
But how should my select statement look like to get this:
[
{
"Value": "field4"
}
]
Use ARRAY construct
SELECT
ARRAY_FLATTEN((ARRAY (ARRAY (ARRAY {r.`Value`}
FOR r IN f.`row`
WHEN r.FieldName = "Field4"
END)
FOR f IN c.FieldList
END)
FOR c IN t.Module.ControlList
END),3)[0].*
FROM `test` AS t
WHERE (ANY cl IN t.Module.ControlList
SATISFIES (ANY fl IN cl.FieldList
SATISFIES fl.FieldName = 'Field2' AND fl.`Value` IS NULL
END)
END);

how to implement sub select with where condition in sequelize

I have these tables:
products
stores
produuctProperties
with this structure
[
"products" :
{
"id": 1,
"orginalName": "146153-0100 ",
"title": null,
"stores": [
{
"id": 1,
"stock": 100,
"minOQ": 1,
"maxOQ": 0
},
{
"id": 2,
"stock": 100,
"minOQ": 1,
"maxOQ": 0,
}
],
"productproperties": [
{
"id": 1,
"productId": 1,
"propertyId": 8,
"propertyOptionId": 5
},
{
"id": 2,
"productId": 1,
"propertyId": 9,
"propertyOptionId": 11
},
{
"id": 3,
"productId": 1,
"propertyId": 10,
"propertyOptionId": 9
}
]
}
]
I want filter my products by selected options , Suppose the selected options are 11 and 9
how to implement below sql query in Sequelize 5.6 with findAll , where and... :
select * from products as p
inner join stores as sr on sr.productId = p.id
where (select count(*) from productProperties where propertyOptionId in (11,9) and productId = p.id) >= 2
I've found that using query builder in sequelize is really confusing,
so if you're good with raw sql you could just run them on as below
if Student is you're model
then
const students = Student.query('Select * from students');

How to group users data on mongo db

I am trying to order the result from a monogo database, this is the equivalent in mysql.
SELECT * FROM `test` WHERE user1 = 'josieboy' or user2='josieboy' GROUP by user1, user2
This is my mongoDB query:
var query = Chat.aggregate(
{
$match:{
$or:[
{'user1':data},
{'user2':data}
]
}
},
{
$group : {
_id: '$user1',
receiver : { $first: '$user1' },
sender : { $first: 'user2' }
}
},
{
$project : {"_id":0, "user1":1, "user2":1}
}
);
The query returns more than the expected result :
RETURNED RESULT
id user1 user2 Message
1 fred josieboy HI
2 josieboy fred Wts up
3 racheal josieboy HI
EXPECTED RESULT
id user1 user2 Message
2 josieboy fred Wts up
3 racheal josieboy HIy
I would want to return a single match for Fred and Josieboy regardless of the number of rows returned and who is the user1 or user2 order by the latest id and latest message.
I would also be glad if the update query could be in mongodb ...
THanks
It's long and ugly but I think does what you want:
db.test.aggregate({
$match: {
$or: [{
'user1': data
}, {
'user2': data
}]
}
}, {
$project: {
user1: 1,
user2: 1,
Message: 1,
users: ["$user1", "$user2"]
}
}, {
$unwind: "$users"
}, {
$redact: {
$cond: {
if: {
$eq: ['$users', data]
},
then: '$$PRUNE',
else: '$$KEEP'
}
}
}, {
$group: {
_id: '$users',
__id: {
$last: '$_id'
},
user1: {
$last: '$user1'
},
user2: {
$last: '$user2'
},
Message: {
$last: '$Message'
}
}
}, {
$project: {
_id: '$__id',
user1: 1,
user2: 1,
Message: 1
}
})