MySQL query equivalent in MongoDB - mysql

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

Related

JSON object: Query a value from unkown node based on a condition

I'm trying to query two values (DISCOUNT_TOTAL and ITEM_TOTAL) from a JSON object in a PostgreSQL database. Take the following query as reference:
SELECT
mt.customer_order
totals -> 0 -> 'amount' -> centAmount DISCOUNT_TOTAL
totals -> 1 -> 'amount' -> centAmount ITEM_TOTAL
FROM
my_table mt
to_jsonb(my_table.my_json -> 'data' -> 'order' -> 'totals') totals
WHERE
mt.customer_order in ('1000001', '1000002')
The query code works just fine, the big problem is that, for some reason out of my control, the values DISCOUNT_TOTAL and ITEM_TOTAL some times change their positions in the JSON object from one customer_order to other:
JSON Object
So i cannot aim to totals -> 0 -> 'amount' -> centAmount assuming that it contains the value related to type : DISCOUNT_TOTAL (same for type: ITEM_TOTAL). Is there any work around to get the correct centAmount for each type?
Use a path query instead of hardcoding the array positions:
with sample (jdata) as (
values (
'{
"data": {
"order": {
"email": "something",
"totals": [
{
"type": "ITEM_TOTAL",
"amount": {
"centAmount": 14990
}
},
{
"type": "DISCOUNT_TOTAL",
"amount": {
"centAmount": 6660
}
}
]
}
}
}'::jsonb)
)
select jsonb_path_query_first(
jdata,
'$.data.order.totals[*] ? (#.type == "DISCOUNT_TOTAL").amount.centAmount'
) as discount_total,
jsonb_path_query_first(
jdata,
'$.data.order.totals[*] ? (#.type == "ITEM_TOTAL").amount.centAmount'
) as item_total
from sample;
db<>fiddle here
EDIT: In case your PostgreSQL version does not support json path queries, you can do it by expanding the array into rows and then doing a pivot by case and sum:
with sample (order_id, jdata) as (
values ( 1,
'{
"data": {
"order": {
"email": "something",
"totals": [
{
"type": "ITEM_TOTAL",
"amount": {
"centAmount": 14990
}
},
{
"type": "DISCOUNT_TOTAL",
"amount": {
"centAmount": 6660
}
}
]
}
}
}'::jsonb)
)
select order_id,
sum(
case
when el->>'type' = 'DISCOUNT_TOTAL' then (el->'amount'->'centAmount')::int
else 0
end
) as discount_total,
sum(
case
when el->>'type' = 'ITEM_TOTAL' then (el->'amount'->'centAmount')::int
else 0
end
) as item_total
from sample
cross join lateral jsonb_array_elements(jdata->'data'->'order'->'totals') as a(el)
group by order_id;
db<>fiddle here

Write mongodb query using Count , DISTINCT & SUM for the following scenario

mysql :
SELECT COUNT(DISTINCT col1, col2) AS 'aggCol1',
SUM(col3 = "2016-03-04 00:00:00" AND col5 = 29) AS 'aggCol2'
FROM table1
WHERE col4 = 50;
I want to write the query on MongoDB.
You can use Aggregation Framework:
To filter by col4 you should use $match
To transform your collection into single result you need $group with _id set to null
To get distinct values for col1 and col2 you can use $addToSet
To use nested filtering for col3 and col5 you need $filter
To get array length you can use $size
So entire aggregation should look like this:
db.col.aggregate([
{
$match: { col4: 50 }
},
{
$group: {
_id: null,
c12: { $addToSet: { col1: "$col1", col2: "$col2" } },
c3: { $push: { col3: "$col3", col5: "$col5" } }
}
},
{
$project: {
c12: 1,
c3: {
$filter: {
input: "$c3",
as: "item",
cond: { $and: [
{ $eq: [ "$$item.col3", ISODate("2016-03-04") ] },
{ $eq: [ "$$item.col5", 29 ] }
] }
}
}
}
},
{
$project: {
aggCol1: { $size: "$c12" },
aggCol2: { $size: "$c3" }
}
}
])

Parsing JSON in Postgres

I have the following JSON that I'd like to parse inside a postgresql function.
{
"people": [
{
"person_name": "Person#1",
"jobs": [
{
"job_title": "Job#1"
},
{
"job_name": "Job#2"
}
]
}
]
}
I need to know how to pull out the person_name, and then loop thru the jobs and pull out the job_title. This is as far as I've been able to get.
select ('{"people":[{"person_name":"Person#1","jobs":[{"job_title":"Job#1"},
{"job_name":"Job#2"}]}]}')::json -> 'people';
https://www.db-fiddle.com/f/vcgya7WtVdvj8q5ck5TqgX/0
Assuming that job_name in your post should be job_title. I expanded your test data to:
{
"people": [{
"person_name": "Person#1",
"jobs": [{
"job_title": "Job#11"
},
{
"job_title": "Job#12"
}]
},
{
"person_name": "Person#2",
"jobs": [{
"job_title": "Job#21"
},
{
"job_title": "Job#22"
},
{
"job_title": "Job#23"
}]
}]
}
Query:
SELECT
person -> 'person_name' as person_name, -- B
json_array_elements(person -> 'jobs') -> 'job_title' as job_title -- C
FROM (
SELECT
json_array_elements(json_data -> 'people') as person -- A
FROM (
SELECT (
'{"people":[ '
|| '{"person_name":"Person#1","jobs":[{"job_title":"Job#11"}, {"job_title":"Job#12"}]}, '
|| '{"person_name":"Person#2","jobs":[{"job_title":"Job#21"}, {"job_title":"Job#22"}, {"job_title":"Job#23"}]} '
|| ']}'
)::json as json_data
)s
)s
A Getting person array; json_array_elements expands all array elements into one row per element
B Getting person_name from array elements
C Expanding the job array elements into one row per element and getting the job_title
Result:
person_name job_title
----------- ---------
"Person#1" "Job#11"
"Person#1" "Job#12"
"Person#2" "Job#21"
"Person#2" "Job#22"
"Person#2" "Job#23"

Excecute a query from MySql to Mongodb

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.

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