Below Query, we are using for fetching the data, how to convert this to as left join Query.
so if id column does not exist in a user_content table the value of count would be 0.
db.contents.aggregate([
{ "$lookup" : {
"from" : "user_content" ,
"localField" : "_id" ,
"foreignField" : "contentId" ,
"as" : "user_content"}
} ,
{ "$unwind" : {
"path" : "$user_content" ,
"preserveNullAndEmptyArrays" : true}
} ,
{ "$match" : { "user_content.liked" : true}} ,
{ "$group" : {
"_id" : "$_id" ,
"popularity" : {
"$first" : "$popularity"} ,
"user_content" : { "$push" : "$user_content"}
}
} ,
{ "$project" : {
"popularity" : 1 ,
"count" : { "$size" : [ "$user_content"]}}
} ,
{ "$skip" : 0} ,
{ "$limit" : 1000000}
]);
Related
I have next data:
table1
[
{
"_id" : ObjectId("5ef3611fc3e39a4891c479d9"),
"bid" : ObjectId("db08c671b5174f49886ca8de"),
},
{
"_id" : ObjectId("5ef30da4c3e39a4891c479d8"),
"bid" : ObjectId("db08c671b5174f49886ca8de"),
}
]
table2:
[
{
"_id" : ObjectId("5ef3626fc3e39a4891c479da"),
"t1_id" : ObjectId("5ef30da4c3e39a4891c479d8"),
"bid" : ObjectId("db08c671b5174f49886ca8de")
}
]
I have next SQL query with two conditions on join
SELECT table1.* FROM table1
LEFT JOIN table2 t2 ON(t2.bid=table1.bid AND t2.t1_id=table1._id)
and try to adapt it to mongoDB.
I came with next query
db.getCollection("table1").aggregate(
[
{
"$project" : {
"_id" : NumberInt(0),
"leads" : "$$ROOT"
}
},
{
"$lookup" : {
"from" : "table2",
"as" : "t2",
"let" : {
"bid" : "$bid",
"t1_id" : "$t1_id"
},
"pipeline" : [
{
"$match" : {
"$expr" : {
"$and" : [
{ "$eq" : [ "$table1._id","$$t1_id"]},
{ "$eq" : [ "$table1.bid","$$bid"]}
]
}
}
}
]
}
},
{
"$unwind" : {
"path" : "$ps",
"preserveNullAndEmptyArrays" : true
}
}
],
);
I got next result
{
"table1" : {
"_id" : ObjectId("5ef30da4c3e39a4891c479d8"),
"bid" : ObjectId("db08c671b5174f49886ca8de"),
},
"t2" : [
{
"_id" : ObjectId("5ef3626fc3e39a4891c479da"),
"t1_id" : ObjectId("5ef30da4c3e39a4891c479d8"),
"bid" : ObjectId("db08c671b5174f49886ca8de")
}
]
},
{
"table1" : {
"_id" : ObjectId("5ef3611fc3e39a4891c479d9"),
"bid" : ObjectId("db08c671b5174f49886ca8de"),
},
"t2" : [
{
"_id" : ObjectId("5ef3626fc3e39a4891c479da"),
"t1_id" : ObjectId("5ef30da4c3e39a4891c479d8"),
"bid" : ObjectId("db08c671b5174f49886ca8de")
}
]
}
And I can`t understand, why second record from table1 matched with t2, though t2.t1_id != table1._id.
Can you help me find a reason of such results and fix mongo query?
let parameter of $lookup takes an expression from the "local" table (t1), which I assume $t1_id doesn't exist
as parameter corresponds to the output result field of the lookup, not an alias.
In the pipeline, expressions starting with $$ are variables declared in the let parameter. expressions starting with $ are expressions from the "foreign" table (t2)
So, to directly translate the $lookup pipeline stage from your SQL statement, it should be
{
"$lookup" : {
"from" : "table2",
"as" : "t2",
"let" : {
"bid" : "$bid",
"t1_id" : "$_id" // should be $_id, as from the SQL you want table1._id, not table1.t1_id
},
"pipeline" : [
{
"$match" : {
"$expr" : {
"$and" : [
{ "$eq" : [ "$t1_id", "$$t1_id"] }, // $t1_id is from t2, $$t1_id is from variable in let parameter
{ "$eq" : [ "$bid", "$$bid"] } // $bid is from t2, $$bid is from variable in let parameter
]
}
}
}
]
}
}
I'm trying to add a condition in my aggregation to get only elements that contain a specific id (like counters.id=1209 in example below ).
My aggregation:
db.getCollection('counters').aggregate([ { "$match" :
{ "module" : "iecc" , "machine" : "COM01" , "colx" : 42 , "idcpt" : { "$in"
: [ 1209 , 1210 , 1217 , 1211 , 1212 , 1213 , 1214 , 1207 , 1208 , 1225 , 1215
, 1216]}}} ,
{ "$group" : { "_id" : "$coly" , "counters" : { "$push" : { "id" : "$idcpt"
, "value" : "$val" , "Tcrea" : "$tcreation"}}}} ,
{ "$sort" : { "counters.1209" : -1 ,"counters.Tcrea" : -1 }}
]
)
actual result:
{
"_id" : 1,
"counters" : [
{
"id" : 1207,
"value" : NumberLong(1),
"Tcrea" : NumberLong(0)
},
{
"id" : 1209,
"value" : "004130",
"Tcrea" : NumberLong(1525962174)
}
]
}
{
"_id" : 2,
"counters" : [
{
"id" : 1207,
"value" : NumberLong(1),
"Tcrea" : NumberLong(0)
}
]
}
The expected result is to get only the first element id=1.
I'm trying "$project" with "$exists" but it don't work :(
{ "$project" : { counters.id : { "$exists" : true, "$in" : 1209}
} }
What's going wrong?
All ideas will be welcome !!
I have following collection -
[{
"customerId" : "54a32e9f1e14fa5476d654db",
"hostId" : "192.168.20.20",
"runtimeMilliSeconds" : 1422007201815
}
{
"customerId" : "54a32e9f1e14fa5476d654db",
"hostId" : "192.168.20.20",
"runtimeMilliSeconds" : 1422008101736
}
{
"customerId" : "54a32e9f1e14fa5476d654db",
"hostId" : "192.168.20.21",
"runtimeMilliSeconds" : 1422009002239
}
{
"customerId" : "54a32e9f1e14fa5476d654db",
"hostId" : "192.168.20.21",
"runtimeMilliSeconds" : 1422009901379
}
{
"customerId" : "54a32e9f1e14fa5476d654db",
"hostId" : "192.168.20.22",
"runtimeMilliSeconds" : 1422010801685
}
{
"customerId" : "54a32e9f1e14fa5476d654db",
"hostId" : "192.168.20.22",
"runtimeMilliSeconds" : 1422010801585
}]
I also have list of hostIds as : [ "192.168.20.20" , "192.168.20.21" , "192.168.20.22"]
I want to match hostId list with collection and find latest (greatest) runtimeMilliSeconds only to get following output -
[{"hostId":"192.168.20.20", "runtime": 1422007201815},
{"hostId":"192.168.20.21", "runtime": 1422009002239},
{"hostId":"192.168.20.22", "runtime": 1422010801685}]
I have tried out following with mongo aggregation -
{ "$match" : { "hostId" : { "$in" : [ "192.168.20.20" , "192.168.20.21" , "192.168.20.22"]} ,
"customerId" : "54a32e9f1e14fa5476d654db"}},
{ "$sort" : { "runtimeMilliSeconds" : -1}},
{ "$group" : { "_id" : { "hostId" : "$hostId" ,
"runtime" : "$runtimeMilliSeconds"}}},
{ "$project" : { "hostId" : "$_id.hostId" ,
"runtimeMilliSeconds" : "$_id.runtime" , "_id" : 0}}
But it gives me all values in collection.
How do I get above mentioned output using mongo??
Use $first operator
db.test.aggregate(
[
{ "$match" : { "hostId" : { "$in" : [ "192.168.20.20" , "192.168.20.21" , "192.168.20.22"]} , "customerId" : "54a32e9f1e14fa5476d654db"}},
{ "$sort" : { "runtimeMilliSeconds" : -1}},
{ "$group" : { "_id" : { "hostId" : "$hostId" } , "runtime" : { $first : "$runtimeMilliSeconds" }}},
{ "$project" : { "hostId" : "$_id.hostId" , "runtimeMilliSeconds" : "$runtime" , "_id" : 0}}
]
)
output will be:
{
"result" : [
{
"hostId" : "192.168.20.20",
"runtimeMilliSeconds" : 1422008101736
},
{
"hostId" : "192.168.20.21",
"runtimeMilliSeconds" : 1422009901379
},
{
"hostId" : "192.168.20.22",
"runtimeMilliSeconds" : 1422010801685
}
],
"ok" : 1
}
The most efficient way to do that would be to use the $max operator (no $sort stage needed):
[
{"$match" : {
"hostId" : { "$in" : [ "192.168.20.20" , "192.168.20.21" , "192.168.20.22"]},
"customerId" : "54a32e9f1e14fa5476d654db"
}},
{ "$group" : {
"_id" : "$hostId",
"runtime" : {"$max" : "$runtimeMilliSeconds"}
}},
{"$project" : {
"hostId" : "$_id" ,
"runtime" : 1,
"_id" : 0
}}
]
Hi I think you are close to your answer but following some changes will meet your output
{
"$match": {
"hostId": {
"$in": [
"192.168.20.20",
"192.168.20.21",
"192.168.20.22"
]
},
"customerId": "54a32e9f1e14fa5476d654db"
}
},
{
"$group": {
"_id": {
"hostId": "$hostId",
"runtime": "$runtimeMilliSeconds"
}
}
},
{
"$sort": {
"_id.runtime": -1
}
}{
"$group": {
"_id": "$_id.hostId",
"runtime": {
"$first": "$_id.runtime"
}
}
}
I have a query
[ { "$match" : { "vm_id" : "218276"}},{ "$group" : { "_id" : { "$dayOfMonth" : "$ts"} , "public_tx_total" : { "$sum" : "$interface_public_tx_bytes"} , "public_rx_total" : { "$sum" : "$interface_public_rx_bytes"} , "private_tx_total" : { "$sum" : "$interface_private_tx_bytes"} , "private_rx_total" : { "$sum" : "$interface_private_rx_bytes"} , "count" : { "$sum" : 1}}},{ "$sort" : { "_id" : 1}} ]
where I want to add a key that takes $ts and pulls the year out of and add it to the results
year: {$year: "$ts"}
I 'm not sure where to place the snippet without causing an error.
You can do it by adding the following command into the group query.
"year" : {$first : { $year:"$ts"}}
Your query will look like :
[
{"$match":{"vm_id":"218276"}},
{"$group":{"_id":{"$dayOfMonth":"$ts"},
"year":{$first:{$year:"$ts"}},
"public_tx_total":{"$sum":"$interface_public_tx_bytes"},
"public_rx_total":{"$sum":"$interface_public_rx_bytes"},
"private_tx_total":{"$sum":"$interface_private_tx_bytes"},
"private_rx_total":{"$sum":"$interface_private_rx_bytes"},
"count":{"$sum":1}}},
{"$sort":{"_id":1}}
]
I have a collection which has a field of array kind. I want to sort on the basis of a field of sub-array but Mongo is not sorting the data.
My collection is:
{
"_id" : ObjectId("51f1fcc08188d3117c6da351"),
"cust_id" : "abc123",
"ord_date" : ISODate("2012-10-03T18:30:00Z"),
"status" : "A",
"price" : 25,
"items" : [{
"sku" : "ggg",
"qty" : 7,
"price" : 2.5
}, {
"sku" : "ppp",
"qty" : 5,
"price" : 2.5
}]
}
My Query is:
db.orders.aggregate([
{ "$unwind" : "$items"} ,
{ "$match" : { }} ,
{ "$group" : { "items" : { "$addToSet" : { "sku" : "$items.sku"}} , "_id" : { }}} ,
{ "$sort" : { "items.sku" : 1}} ,
{ "$project" : { "_id" : 0 , "items" : 1}}
])
Result is:
"result" : [
{
"items" : [
{
"sku" : "ppp"
},
{
"sku" : "ggg"
}
]
}
],
"ok" : 1
}
Whereas "sku":"ggg" should come first when it is ascending.
You weant to do the sort BEFORE you regroup:
db.orders.aggregate([
{ "$unwind" : "$items"} ,
{ "$sort" : { "items.sku" : 1}},
{ "$match" : { }} ,
{ "$group" : { "items" : { "$push" : { "sku" : "$items.sku"}} , "_id" : null}} ,
{ "$project" : { "_id" : 0 , "items" : 1}}
])