MongoDB between date range query - nested property - mongodb

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

Related

Mongo query to return latest entry

Hi I have the following data structure in mongodb:
{
"_id" : "4087322f-1ad0-4595-935f-b41ef6d87306",
"lastModifiedDate" : ISODate("2016-11-22T20:48:05.904Z"),
"notes" : " I do not like him that much",
"peopleId" : "1121",
"status" : "asses"
}
I wish to query the data such that it will return the latest value for each peopleId which also matches a chosen status. I've been looking into $group however doing the equal status is causing some issue.
I have got as far as grouping the values by peopleId using:
.aggregate([
{$group : {_id : "$peopleId", "allData" : {$push : "$$ROOT"}}},
{$sort : { lastModifiedDate : -1}}
]).pretty()
To give give me these results:
{
"_id" : "1123",
"allData" : [
{
"_id" : "c9d6a6ce-104d-414a-8d89-512e556d7aba",
"lastModifiedDate" : ISODate("2016-11-22T20:55:35.662Z"),
"notes" : "He's in!",
"peopleId" : "1123",
"status" : "done"
},
{
"_id" : "14e522d8-6cae-42ee-ad52-d5cf3cae0c29",
"lastModifiedDate" : ISODate("2016-11-22T20:56:46.128Z"),
"notes" : "He's in!",
"peopleId" : "1123",
"status" : "asses"
}
]
}
{
"_id" : "1121",
"allData" : [
{
"_id" : "d2c3e5da-8696-4dcc-a5cd-1f2657f0192c",
"lastModifiedDate" : ISODate("2016-11-22T20:46:35.097Z"),
"notes" : " I do not like him",
"peopleId" : "1121",
"status" : "pending"
},
{
"_id" : "4087322f-1ad0-4595-935f-b41ef6d87306",
"lastModifiedDate" : ISODate("2016-11-22T20:48:05.904Z"),
"notes" : " I do not like him that much",
"peopleId" : "1121",
"status" : "asses"
},
{
"_id" : "be4fa5bd-da8c-4c1a-9010-6a86afd11dbc",
"lastModifiedDate" : ISODate("2016-11-22T20:49:27.268Z"),
"notes" : "He's in!\nTue Nov 22 12:49:27 PST 2016 He's TF OUT",
"peopleId" : "1121",
"status" : "done"
}
]
}
From this I need to extract the most recent entry based on lastModifiedDate and then check that is matches a given status.
Here are the solutions.
Solution 1:-
If you want all the fields in the collection in the output.
db.collection.aggregate([
{$match : {"status" : "asses"}},
{$sort : {peopleId : 1, lastModifiedDate : -1}},
{$group : {_id : "$peopleId", "allData" : {$push : "$$ROOT"}}},
{$project: {_id :0, allData : {$slice : ["$allData", 0, 1]}}}
]);
Output:-
{
"allData" : [
{
"_id" : ObjectId("5834c004ba41f1f22e600c7f"),
"lastModifiedDate" : ISODate("2016-11-24T20:48:05.904Z"),
"notes" : " I do not like him that much",
"peopleId" : "1",
"status" : "asses"
}
]
}
Solution 2:-
If you don't want all the fields from the collection in the output.
db.collection.aggregate([
{$match : {"status" : "asses"}},
{$sort : {peopleId : 1, lastModifiedDate : -1}},
{$group : {_id : "$peopleId", lastModDate : {$first : "$lastModifiedDate"}}}
])
Output:-
{
"_id" : "1",
"lastModDate" : ISODate("2016-11-24T20:48:05.904Z")
}
i created a collection with following docs
{ "_id" : "4087322f-1ad0-4595-935f-b41ef6d87306", "lastModifiedDate" : ISODate("2016-11-22T20:48:05.904Z"), "notes" : " I do not like him that much",
"peopleId" : "1121", "status" : "asses" }
{ "_id" : "4087322f-1ad0-4595-935f-b41ef6d87305", "lastModifiedDate" : ISODate("2016-10-22T20:48:05.904Z"), "notes" : " I do not like him that much",
"peopleId" : "1121", "status" : "asses" }
{ "_id" : "4087322f-1ad0-4595-935f-b41ef6d87304", "lastModifiedDate" : ISODate("2016-11-21T20:48:05.904Z"), "notes" : " I do not like him that much",
"peopleId" : "1121", "status" : "asses" }
and if i execute the following query
db.mel.find().sort({lastModifiedDate:-1}).limit(1)
it gives me
{ "_id" : "4087322f-1ad0-4595-935f-b41ef6d87306", "lastModifiedDate" : ISODate("2016-11-22T20:48:05.904Z"), "notes" : " I do not like him that much",
"peopleId" : "1121", "status" : "asses" }
which is latest as per the lastmodifeddate.

MongoDB Aggregation Count of Group By Inner Array

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

Mongo DB : remove document from collection

Here is one of my document of my collection "entities", I can't figure out how to remove it.
{
"_id" : {
"id" : "sensors:StreetLight2",
"type" : "sensors",
"servicePath" : "/egmmqttpath"
},
"attrNames" : [
"TimeInstant",
"PING_status"
],
"attrs" : {
"PING_status" : {
"value" : "delivered but no respond",
"type" : "string",
"md" : [
{
"name" : "TimeInstant",
"type" : "ISO8601",
"value" : "2015-11-20T09:02:53.114688"
}
],
"creDate" : 1448010161,
"modDate" : 1448010172
},
"TimeInstant" : {
"value" : "2015-11-20T09:02:53.114834",
"type" : "ISO8601",
"creDate" : 1448010122,
"modDate" : 1448010172
}
},
"creDate" : 1448010122,
"modDate" : 1448010172
}
Any ideas? how can I remove the above document? Thanks in advance.
From doc:
db.collection.remove()
Removes documents from a collection.
1) By _ID: Since _ID is unique.
db.entities.remove( {"_id" :
{
"id" : "sensors:StreetLight2",
"type" : "sensors",
"servicePath" : "/egmmqttpath"
}
})
I would pass the _id to remove it.
db.entities.remove({
"_id" : {
"id" : "sensors:StreetLight2",
"type" : "sensors",
"servicePath" : "/egmmqttpath"
}
})
remove document in mongodb
query = {"_id": <value of _id>}
db.entities.remove(query)
db.entities.remove(
"_id" : {
"id" : "sensors:StreetLight2",
"type" : "sensors",
"servicePath" : "/egmmqttpath""id" : "sensors:StreetLight2"
}
)
you can also take any key-value pair from documents for remove
you can refer these links for better understanding
https://docs.mongodb.org/manual/tutorial/remove-documents/
https://docs.mongodb.org/manual/reference/method/db.collection.remove/
In mongo shell you should use .remove():
db.entities.remove(
{
"_id" :
{
"id" : "sensors:StreetLight2",
"type" : "sensors",
"servicePath" : "/egmmqttpath"
}
})

Mongodb pull data from subarray

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.

Compound GeoSpatial Index in MongoDB is not working as intended

the collection nodesWays has the following indexes:
> db.nodesWays.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "h595.nodesWays"
},
{
"v" : 1,
"key" : {
"amenity" : 1,
"geo" : "2dsphere"
},
"name" : "amenity_1_geo_2dsphere",
"ns" : "h595.nodesWays",
"2dsphereIndexVersion" : 2
},
{
"v" : 1,
"key" : {
"geo" : "2dsphere"
},
"name" : "geo_2dsphere",
"ns" : "h595.nodesWays",
"2dsphereIndexVersion" : 2
}
]
Now the following two queries should return the same result, but they don't.
I want the nearest 10 restaurants to the specified point.
The first query is working how it should be, the second is not working like intended.
The only difference between these two queries is that the first one uses the geo_2dsphere-Index
and the second query the amenity_1_geo_2dsphere-Index.
> db.nodesWays.find(
{
geo:{
$nearSphere:{
$geometry:{
type: "Point", coordinates: [9.7399777,52.3715156]
}
}
}, "amenity":"restaurant",
name: {$exists: true}
}, {id:1, name:1}).hint( "geo_2dsphere" ).limit(10)
{ "_id" : ObjectId("53884860e552e471be2b7192"), "id" : "321256694", "name" : "Masa" }
{ "_id" : ObjectId("53884860e552e471be2b7495"), "id" : "323101271", "name" : "Bavarium" }
{ "_id" : ObjectId("53884862e552e471be2ba605"), "id" : "442496282", "name" : "Naxos" }
{ "_id" : ObjectId("53884860e552e471be2b7488"), "id" : "323101189", "name" : "Block House" }
{ "_id" : ObjectId("53884878e552e471be2d1a41"), "id" : "2453236451", "name" : "Maestro" }
{ "_id" : ObjectId("53884870e552e471be2c8aab"), "id" : "1992166428", "name" : "Weinstube Leonardo Ristorante" }
{ "_id" : ObjectId("53884869e552e471be2c168b"), "id" : "1440320284", "name" : "Altdeutsche küche" }
{ "_id" : ObjectId("53884861e552e471be2b88f7"), "id" : "353119010", "name" : "Mövenpick" }
{ "_id" : ObjectId("5388485de552e471be2b2c86"), "id" : "265546900", "name" : "Miles" }
{ "_id" : ObjectId("53884863e552e471be2bb5d3"), "id" : "532304135", "name" : "Globetrotter" }
> db.nodesWays.find(
{
geo:{
$nearSphere:{
$geometry:{
type: "Point", coordinates: [9.7399777,52.3715156]
}
}
}, "amenity":"restaurant",
name: {$exists: true}
}, {id:1, name:1}).hint( "amenity_1_geo_2dsphere" ).limit(10)
{ "_id" : ObjectId("53884875e552e471be2cf4a8"), "id" : "2110027373", "name" : "Schloßhof Salder" }
{ "_id" : ObjectId("5388485be552e471be2aff19"), "id" : "129985174", "name" : "Balkan Paradies" }
{ "_id" : ObjectId("5388485be552e471be2afeb4"), "id" : "129951134", "name" : "Asia Dragon" }
{ "_id" : ObjectId("53884863e552e471be2ba811"), "id" : "450130115", "name" : "Kings Palast" }
{ "_id" : ObjectId("53884863e552e471be2ba823"), "id" : "450130135", "name" : "Restaurant Montenegro" }
{ "_id" : ObjectId("53884877e552e471be2d053a"), "id" : "2298722569", "name" : "Pizzaria Da-Lucia" }
{ "_id" : ObjectId("53884869e552e471be2c152e"), "id" : "1420101752", "name" : "Napoli" }
{ "_id" : ObjectId("5388485be552e471be2b0028"), "id" : "136710095", "name" : "Europa" }
{ "_id" : ObjectId("53884862e552e471be2ba5bc"), "id" : "442136241", "name" : "Syrtaki" }
{ "_id" : ObjectId("53884863e552e471be2ba763"), "id" : "447972565", "name" : "Pamukkale" }
My goal with the second index is to:
select all restaurants
then use the nearSphere-Operator to sort them in regards to the distance from the specified point
Auf Wiedersehen
I think you should try to put the geolocation first in the index.