How to group users data on mongo db - mysql

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

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

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

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

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.