I am using MongoDB 3.2.
Having trouble with this query ...
(Apologies in advance for the SQL-like syntax, I'm just learning Mongo coming from SQL)
I need to find the COUNT of documents where
"audit_event_type_id" : 1
shop2.date" BETWEEN "2014-10-01" AND "2015-09-01"
Grouping it by
shop2.facility_name
MONTH(shop2.date)
YEAR(shop2.date)
ORDER BY
count DESC
Is there a way to convert a string to date in the query? I know I am storing shop2.date as a string when it should be ISODate. If not, let's assume that it's an ISODate.
Here is a document sample :
{
"_id" : ObjectId("56b38f31967a337c432119cb"),
"audit_event_id" : 12382306,
"audit_event_type_id" : 2,
"group_id" : 3333489,
"applicant_id" : 3428508,
"service_credit_id" : 3804844,
"page_hit_id" : 43870954,
"shop1" : {
"facility_id" : 28,
"facility_name" : "Fake1",
"date" : "2014-08-13",
"time" : "07:00",
"expedite" : false,
"collect_biometrics" : false,
"block_id" : 364814,
"appointment_category" : "Renewal"
},
"shop2" : {
"facility_id" : 29,
"facility_name" : "Fake2",
"date" : "2014-08-07",
"time" : "07:00",
"expedite" : false,
"block_id" : 373614,
"appointment_category" : "Biometrics"
},
"created_at" : "2014-07-30 00:44:36",
"updated_at" : "2014-07-30 00:44:36",
"user_id" : 3242890,
"payment_id" : null,
"mission_id" : 24,
"affected_user_id" : null
}
Any help would be appreciated. Thanks!!
Update
I've updated all shop1.date & shop2.date to ISODate. Here is the new document sample :
{
"_id" : ObjectId("56b38f31967a337c432119cb"),
"audit_event_id" : 12382306,
"audit_event_type_id" : 2,
"group_id" : 3333489,
"applicant_id" : 3428508,
"service_credit_id" : 3804844,
"page_hit_id" : 43870954,
"shop1" : {
"facility_id" : 28,
"facility_name" : "Fake1",
"date" : ISODate("2014-08-13T00:00:00Z"),
"time" : "07:00",
"expedite" : false,
"collect_biometrics" : false,
"block_id" : 364814,
"appointment_category" : "Renewal"
},
"shop2" : {
"facility_id" : 29,
"facility_name" : "Fake2",
"date" : ISODate("2014-08-07T00:00:00Z"),
"time" : "07:00",
"expedite" : false,
"block_id" : 373614,
"appointment_category" : "Biometrics"
},
"created_at" : "2014-07-30 00:44:36",
"updated_at" : "2014-07-30 00:44:36",
"user_id" : 3242890,
"payment_id" : null,
"mission_id" : 24,
"affected_user_id" : null
}
You can use the aggregation framework in mongodb for this:
db.Collection.aggregate([
{ $match: {
audit_event_type_id: 1,
"shop2.date": { $gte: ISODate("2014-10-01T00:00:00.000Z"), $lt: ISODate("2015-09-01T00:00:00.000Z") } }
},
{ $group : {
_id : { "shop2.facility_name": "$shop2.facility_name", month: { $month: "$shop2.date" }, year: { $year: "$shop2.date" } },
count: { $sum: 1 } }
},
{ $sort : { count: -1 } }
])
Related
This was my query on MySQL:
select date, AVG(retail_and_recreation_percent_change_from_baseline),
AVG(grocery_and_pharmacy_percent_change_from_baseline),
AVG(workplaces_percent_change_from_baseline)
from global_mobility_report
where date >=
(select date
from owid_covid_data
where location like "Indonesia"
and CAST(total_cases as signed) > 20000
order by date
limit 1)
and country_region like "Indonesia"
group by date
order by date
I wanted to do something similar on MongoDB but I had to take 2 steps:
Step 1: Find the date
db.ovid2.aggregate([
{$match:{"location":"Indonesia"}},
{$match:{"total_cases":{$gt:20000}}},
{$sort:{date:1}},
{$project:{_id:0, date:1}}
{$limit:1}
])
output: ISODate("2020-05-22T00:00:00.000+08:00")
Step 2: Manually input the date and continue with the rest of the query
db.mobility.aggregate([
{$match:{"country_region":"Indonesia"}},
{$match:{"date":{$gte:ISODate("2020-05-22T00:00:00.000+08:00")}}},
{$group:{_id:"$date",
AvgRandR:{$avg:"$retail_and_recreation_percent_change_from_baseline"},
AvgGandP:{$avg:"$grocery_and_pharmacy_percent_change_from_baseline"},
AvgW:{$avg:"$workplaces_percent_change_from_baseline"}}},
{$sort:{_id:1}}
])
Is there an easier way to go about doing this? I realize this is not optimal especially if the question changes and Step 1 returns multiple outputs (say over 100). This means I would have to type a 100 different values into step 2?
Here are some sample documents:
collection: mobility
{
"_id" : ObjectId("5f49fd6a3acddb5eec4427bb"),
"country_region_code" : "ID",
"country_region" : "Indonesia",
"sub_region_1" : "",
"sub_region_2" : "",
"metro_area" : "",
"iso_3166_2_code" : "",
"census_fips_code" : "",
"date" : ISODate("2020-02-15T08:00:00.000+08:00"),
"retail_and_recreation_percent_change_from_baseline" : -2,
"grocery_and_pharmacy_percent_change_from_baseline" : -2,
"parks_percent_change_from_baseline" : -8,
"transit_stations_percent_change_from_baseline" : 1,
"workplaces_percent_change_from_baseline" : 5,
"residential_percent_change_from_baseline" : 1
},
{
"_id" : ObjectId("5f49fd6a3acddb5eec44281f"),
"country_region_code" : "ID",
"country_region" : "Indonesia",
"sub_region_1" : "",
"sub_region_2" : "",
"metro_area" : "",
"iso_3166_2_code" : "",
"census_fips_code" : "",
"date" : ISODate("2020-05-25T08:00:00.000+08:00"),
"retail_and_recreation_percent_change_from_baseline" : -40,
"grocery_and_pharmacy_percent_change_from_baseline" : -17,
"parks_percent_change_from_baseline" : -16,
"transit_stations_percent_change_from_baseline" : -59,
"workplaces_percent_change_from_baseline" : -70,
"residential_percent_change_from_baseline" : 19
},
{
"_id" : ObjectId("5f49fd6a3acddb5eec4428db"),
"country_region_code" : "ID",
"country_region" : "Indonesia",
"sub_region_1" : "Aceh",
"sub_region_2" : "",
"metro_area" : "",
"iso_3166_2_code" : "ID-AC",
"census_fips_code" : "",
"date" : ISODate("2020-05-22T08:00:00.000+08:00"),
"retail_and_recreation_percent_change_from_baseline" : -4,
"grocery_and_pharmacy_percent_change_from_baseline" : 33,
"parks_percent_change_from_baseline" : -10,
"transit_stations_percent_change_from_baseline" : -33,
"workplaces_percent_change_from_baseline" : -31,
"residential_percent_change_from_baseline" : 9
}
collection: ovid2
{
"_id" : ObjectId("5f4a06e23acddb5eec55a4aa"),
"iso_code" : "IDN",
"continent" : "Asia",
"location" : "Indonesia",
"date" : ISODate("2020-05-22T00:00:00.000+08:00"),
"total_cases" : 20162,
"new_cases" : 973,
"new_cases_smoothed" : 593.714,
"total_deaths" : 1278,
"new_deaths" : 36,
"new_deaths_smoothed" : 33.571,
"total_cases_per_million" : 73.712,
"new_cases_per_million" : 3.557,
"new_cases_smoothed_per_million" : 2.171,
"total_deaths_per_million" : 4.672,
"new_deaths_per_million" : 0.132,
"new_deaths_smoothed_per_million" : 0.123,
"new_tests" : 0,
"total_tests" : 168969,
"total_tests_per_thousand" : 0.618,
"new_tests_per_thousand" : 0,
"new_tests_smoothed" : 5273,
"new_tests_smoothed_per_thousand" : 0.019,
"tests_per_case" : 8.881,
"positive_rate" : 0.113,
"tests_units" : NaN,
"stringency_index" : 71.76,
"population" : 273523621,
"population_density" : 145.725,
"median_age" : 29.3,
"aged_65_older" : 5.319,
"aged_70_older" : 3.053,
"gdp_per_capita" : 11188.744,
"extreme_poverty" : 5.7,
"cardiovasc_death_rate" : 342.864,
"diabetes_prevalence" : 6.32,
"female_smokers" : 2.8,
"male_smokers" : 76.1,
"handwashing_facilities" : 64.204,
"hospital_beds_per_thousand" : 1.04,
"life_expectancy" : 71.72
},
{
"_id" : ObjectId("5f4a06e23acddb5eec55a420"),
"iso_code" : "IDN",
"continent" : "Asia",
"location" : "Indonesia",
"date" : ISODate("2020-01-05T00:00:00.000+08:00"),
"total_cases" : 0,
"new_cases" : 0,
"new_cases_smoothed" : 0,
"total_deaths" : 0,
"new_deaths" : 0,
"new_deaths_smoothed" : 0,
"total_cases_per_million" : 0,
"new_cases_per_million" : 0,
"new_cases_smoothed_per_million" : 0,
"total_deaths_per_million" : 0,
"new_deaths_per_million" : 0,
"new_deaths_smoothed_per_million" : 0,
"new_tests" : 0,
"total_tests" : 0,
"total_tests_per_thousand" : 0,
"new_tests_per_thousand" : 0,
"new_tests_smoothed" : 0,
"new_tests_smoothed_per_thousand" : 0,
"tests_per_case" : 0,
"positive_rate" : 0,
"tests_units" : 0,
"stringency_index" : 5.56,
"population" : 273523621,
"population_density" : 145.725,
"median_age" : 29.3,
"aged_65_older" : 5.319,
"aged_70_older" : 3.053,
"gdp_per_capita" : 11188.744,
"extreme_poverty" : 5.7,
"cardiovasc_death_rate" : 342.864,
"diabetes_prevalence" : 6.32,
"female_smokers" : 2.8,
"male_smokers" : 76.1,
"handwashing_facilities" : 64.204,
"hospital_beds_per_thousand" : 1.04,
"life_expectancy" : 71.72
},
{
"_id" : ObjectId("5f4a06e63acddb5eec55fbf3"),
"iso_code" : "ZWE",
"continent" : "Africa",
"location" : "Zimbabwe",
"date" : ISODate("2020-03-21T00:00:00.000+08:00"),
"total_cases" : 1,
"new_cases" : 1,
"new_cases_smoothed" : 0,
"total_deaths" : 0,
"new_deaths" : 0,
"new_deaths_smoothed" : 0,
"total_cases_per_million" : 0.067,
"new_cases_per_million" : 0.067,
"new_cases_smoothed_per_million" : 0,
"total_deaths_per_million" : 0,
"new_deaths_per_million" : 0,
"new_deaths_smoothed_per_million" : 0,
"new_tests" : 0,
"total_tests" : 0,
"total_tests_per_thousand" : 0,
"new_tests_per_thousand" : 0,
"new_tests_smoothed" : 0,
"new_tests_smoothed_per_thousand" : 0,
"tests_per_case" : 0,
"positive_rate" : 0,
"tests_units" : 0,
"stringency_index" : 27.78,
"population" : 14862927,
"population_density" : 42.729,
"median_age" : 19.6,
"aged_65_older" : 2.822,
"aged_70_older" : 1.882,
"gdp_per_capita" : 1899.775,
"extreme_poverty" : 21.4,
"cardiovasc_death_rate" : 307.846,
"diabetes_prevalence" : 1.82,
"female_smokers" : 1.6,
"male_smokers" : 30.7,
"handwashing_facilities" : 36.791,
"hospital_beds_per_thousand" : 1.7,
"life_expectancy" : 61.49
}
You can try,
$match your required conditions
$lookup with owid_covid_data collection using aggregation pipeline and get result in owid_covid_data field,
$match your required conditions
$project to required fields
$sort by date ascending order
$limit number 1 document to return
$match date condition
$unwind deconstruct owid_covid_data array, this will remove empty result document
$group by date and average fields
$sort by date ascending order
db.global_mobility_report.aggregate([
{ $match: { country_region: "Indonesia" } },
{
$lookup: {
from: "owid_covid_data",
let: { date: "$date" },
pipeline: [
{
$match: {
location: "Indonesia",
total_cases: { $gt: 20000 }
}
},
{ $project: { _id: 0, date: 1 } },
{ $sort: { date: 1 } },
{ $limit: 1 },
{ $match: { $expr: { $gte: ["$$date", "$date"] } } }
],
as: "owid_covid_data"
}
},
{ $unwind: "$owid_covid_data" },
{
$group: {
_id: "$date",
AvgRandR: { $avg: "$retail_and_recreation_percent_change_from_baseline" },
AvgGandP: { $avg: "$grocery_and_pharmacy_percent_change_from_baseline" },
AvgW: { $avg: "$workplaces_percent_change_from_baseline" }
}
},
{ $sort: { _id: 1 } }
])
Playground
I am getting confused with a simple MongoDB query that I can't figure it out where the problem is. I have a collection like this:
{
"_id" : NumberLong(1939026454),
"username" : "5144269288",
"_type" : 1,
"group_id" : 416,
"user_id" : NumberLong(426661),
"credit_used" : 0.0,
"retry_count" : 1,
"successful" : true,
"type_details" : {
"in_bytes" : 0,
"sub_service_qos" : "",
"sub_service_name" : "rating-group-103",
"out_bytes" : 0,
"sub_service_charging" : "FreeIPTV",
"remote_ip" : ""
},
"logout_time" : ISODate("2017-11-06T07:16:09.000Z"),
"before_credit" : 4560.2962,
"ras_id" : 18,
"caller_id" : "",
"isp_id" : 0,
"duration" : NumberLong(14500),
"details" : {
"connect_info" : "rate-group=103",
"sub_service" : "rating-group-103",
"diameter_request_type" : "initial"
},
"unique_id_value" : "918098048;falcon;Dehghan01000000001415716f9a113697;529;falcon-02b4e8a7__103",
"charge_rule_details" : [
{
"start_in_bytes" : 0,
"charge_rule_id" : 3682,
"start_out_bytes" : 0,
"stop_time" : ISODate("2017-11-06T07:16:09.000Z"),
"stop_out_bytes" : 0,
"start_time" : ISODate("2017-11-06T03:14:29.000Z"),
"charge_rule_desc" : "rating-group-103",
"stop_in_bytes" : 0
}
],
"unique_id" : "acct_session_id",
"login_time" : ISODate("2017-11-06T03:14:29.000Z")
}
I need to filter documents that login_time is between two given dates and type_details.sub_service_name is some string.
I tried this:
db.getCollection('connection_log_partial_data').find({
"type_details" : {"sub_service_name": "rating-group-103"},
"login_time": {
"$gt": ISODate("2016-11-06T03:14:29.000Z"),
"$lt": ISODate("2017-11-06T03:14:29.000Z")
}
});
but it fetches 0 records. Any suggestions?
your query should be something like:
db.getCollection('connection_log_partial_data').find({
"type_details.sub_service_name" : "rating-group-103",
"login_time": {
"$gte": ISODate("2016-11-06T03:14:29.000Z"),
"$lte": ISODate("2017-11-06T03:14:29.000Z")
}
});
How to write query to return object between dates? Query should search nested property. I use $gte and $lte but it doesn't seem to work as I expected. I want to return 'task' object which has got history.startTime between two dates.
db.tasks.find({'history.startTime' : { '$gte': ISODate("2017-02-04T00:00:00.000Z"), '$lt': ISODate("2017-02-05T23:00:00.000Z")} }).pretty()
{
"_id" : ObjectId("588f53c5d00baa2558fd56ae"),
"desc" : "test3",
"category" : "Category1",
"project" : "Project1",
"_creator" : "582afb3800c1bc1f203edf39",
"history" : [
{
"startTime" : ISODate("2017-02-06T11:49:42.570Z"),
"stopTime" : ISODate("2017-02-06T11:49:45.725Z"),
"_id" : ObjectId("589862d9449b4629f8dbaba7"),
"dt" : 3.155
},
{
"startTime" : ISODate("2017-02-06T08:53:53.086Z"),
"stopTime" : ISODate("2017-02-06T11:47:58.098Z"),
"_id" : ObjectId("5898626e449b4629f8dbaba6"),
"dt" : 10445.012
},
{
"startTime" : ISODate("2017-01-30T15:30:46.287Z"),
"stopTime" : ISODate("2017-01-30T15:32:52.979Z"),
"_id" : ObjectId("588f5c2cd00baa2558fd56b0"),
"dt" : 126.692
},
{
"startTime" : ISODate("2017-01-30T13:55:09.738Z"),
"stopTime" : ISODate("2017-01-30T14:55:13.974Z"),
"_id" : ObjectId("588f53d1d00baa2558fd56af"),
"dt" : 3604.236
}
],
"isCompleted" : false,
"isPerforming" : false,
"duration" : 14179.095000000001,
"updated" : ISODate("2017-02-06T11:49:45.725Z"),
"creationDate" : ISODate("2017-01-30T14:55:01.045Z"),
"__v" : 4
}
It is an array. Your query won't work. You have to use $elemMatch.
db.tasks.find({
'history': {
$elemMatch: {
startTime: {
$gte: ISODate("2017-02-04T00:00:00.000Z"),
$lte: ISODate("2017-02-05T23:00:00.000Z")
}
}
}
});
Hi I have below mongodb collection
{
"_id" : ObjectId("53ce993639203f573671d3f5"),
"user_id" : NumberLong(51),
"buses" : [
{
"slot_id" : NumberLong(50),
"status" : NumberLong(3),
"bus_id" : NumberLong(8)
},
{
"slot_id" : NumberLong(67),
"status" : NumberLong(3),
"bus_id" : NumberLong(12)
}
]
}
i want to pull sub array where bus_id=8.
Final result i want to be like this
{
"_id" : ObjectId("53ce993639203f573671d3f5"),
"user_id" : NumberLong(51),
"buses" : [
{
"slot_id" : NumberLong(67),
"status" : NumberLong(3),
"bus_id" : NumberLong(12)
}
]
}
When i tried with below query
db.collectionname.update({},{$pull: {buses: {bus_id:8}}},{multi: true})
I got below error in console,
Cannot apply $pull/$pullAll modifier to non-array
Can any one please suggest me how to achieve this,and also need php mongodb query also.
Thanks in Advance
Worked fine for me for your sample document:
> db.bus.findOne()
{
"_id" : ObjectId("53ce993639203f573671d3f5"),
"user_id" : NumberLong(51),
"buses" : [
{
"slot_id" : NumberLong(50),
"status" : NumberLong(3),
"bus_id" : NumberLong(8)
},
{
"slot_id" : NumberLong(67),
"status" : NumberLong(3),
"bus_id" : NumberLong(12)
}
]
}
> db.bus.update({}, { "$pull" : { "buses" : { "bus_id" : 8 } } }, { "multi" : true })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.bus.findOne()
{
"_id" : ObjectId("53ce993639203f573671d3f5"),
"user_id" : NumberLong(51),
"buses" : [
{
"slot_id" : NumberLong(67),
"status" : NumberLong(3),
"bus_id" : NumberLong(12)
}
]
}
The cause of the problem is that some buses element is not an array. What does the query
> db.bus.find({ "buses.0" : { "$exists" : 0}, "buses" : { "$ne" : [] } })
return? This query finds documents where there is no 0th element of the array and the array is not empty, so it should return documents where buses is not an array.
I have document sales
db.sale.findOne({_id : ObjectId("52ea4dd29dbc7923107ddb97")})
{
"_id" : ObjectId("52ea4dd29dbc7923107ddb97"),
"firm" : ObjectId("52e56c009dbc794999ea5c3d"),
"patient" : {
"last" : "",
"first" : ""
},
"doc" : "",
"hospital" : "",
"discount" : 0,
"dd" : "",
"mode" : "cash",
"invoice" : "300114-undefined-1",
"items" : [
{
"bat" : "BJFE",
"narco" : 0,
"name" : "GDRNCCD",
"mrp" : 1,
"free" : 0,
"qty" : 1,
"item_discount" : 0,
"wpr" : 1,
"exp" : "1425168000000"
},
{
"bat" : "",
"narco" : 0,
"name" : "GDRN vbhjdsfb",
"mrp" : 1,
"free" : 0,
"qty" : 1,
"item_discount" : 0,
"wpr" : 0,
"exp" : "[object Object]"
},
{
"bat" : "",
"narco" : 0,
"name" : "GDRN vbhjdsfb",
"mrp" : 1,
"free" : 0,
"qty" : 1,
"item_discount" : 0,
"wpr" : 0,
"exp" : "[object Object]"
}
],
"date" : ISODate("2014-01-30T00:00:00Z"),
"mob" : "",
"email" : ""
}
How can I Aggregate total numbers if items in one field and sum up mrp *qty of all the items into one field.
I have read the mognodb aggregation but it only aggregates among group of matched documents not inside a single document. Is it possile?
{
"_id" : ObjectId("52ea4dd29dbc7923107ddb97"),
"firm" : ObjectId("52e56c009dbc794999ea5c3d"),
'total_items' : items.length,
"total" : mrp*qty of all items,
}
db.sales.aggregate(
{$unwind: "$items"},
{$project: {_id: 1,firm:1, total: {$multiply: ["$items.mrp", "$items.qty"]}}},
{$group: {_id: {"id":"$_id", firm:"$firm"}, count: {$sum:1} , total : {$sum:"$total"}}}
)
With a slight change : _id contains id and firm, you will need an extra projection to match your desired document, but I don't think it's important.
Plus, you can easily change to group by farm only
Thanks to Orid,I tried this,
db.sale.aggregate(
{ $match :{ firm :ObjectId("52e56c009dbc794999ea5c3d") } },
{$project : {day : {$dayOfMonth : '$date'},items :1,patient :1,invoice :1}},
{$match : {day: {$gte : new Date().getDate()}}},
{$unwind : "$items"},
{$project: {_id: 1,patient:1,invoice :1, total: {$multiply: ["$items.mrp", "$items.qty"]}}},
{$group: {_id: {"id":"$_id", invoice:"$invoice",patient :"$patient"}, count: {$sum:1} , total : {$sum:"$total"}}})
Result
{
"result" : [
{
"_id" : {
"id" : ObjectId("52eab6129dbc7923107ddbaf"),
"invoice" : "310114-undefined-1",
"patient" : {
"last" : "",
"first" : ""
}
},
"count" : 2,
"total" : 25
},
{
"_id" : {
"id" : ObjectId("52eab6129dbc7923107ddbb0"),
"invoice" : "310114-undefined-1",
"patient" : {
"last" : "",
"first" : ""
}
},
"count" : 1,
"total" : 1
},
{
"_id" : {
"id" : ObjectId("52eab6129dbc7923107ddbae"),
"invoice" : "310114-undefined-1",
"patient" : {
"last" : "",
"first" : ""
}
},
"count" : 2,
"total" : 5
}
],
"ok" : 1
}