Mongo query to return latest entry - mongodb

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.

Related

Find element from document

i've passed a mysql database to mongoDB for a project. My db is about a pharmacy. I have a collection of factures, where which has the list of medicines sold. I'm trying to find the medicine which was sold the most.
{
"_id" : ObjectId("5c3c71f2760c4f47c701fe13"),
"cliente" : {
"tlmv" : "910987654",
"nome" : "Josefina Vivida da Paz",
"nif" : "122133144",
"pontos" : NumberLong(0),
"id" : NumberLong(2),
"pass" : "1eab06cab995dfeb32b6b7c709b8a6c62cabacfe",
"email" : "josefina#hotmail.pt"
},
"data_f" : ISODate("2018-06-03T00:00:01Z"),
"data_s" : ISODate("2018-06-02T23:55:59Z"),
"desconto" : 0,
"funcionario" : {
"tlmv" : "934567123",
"nome" : "Pedro Jorge Rito Lima",
"ordenado" : 800.32,
"iban" : "PT 50 2751 3262 76598707612",
"pass" : "3cfa1c281281ffe4f5db2ccfbe7a17f8a9479808",
"niss" : "14385639201",
"id" : NumberLong(2),
"cedula" : "54321"
},
"id" : NumberLong(15),
"id_c" : NumberLong(2),
"id_func" : NumberLong(2),
"medicamentos" : [
{
"categoria" : "Analg�sico",
"receita" : "N",
"des" : "Ben-U-Ron 500",
"qt" : 20,
"formato" : "granulado",
"qt_v" : NumberLong(1),
"pos" : "A12",
"lab" : "Laborat�rio do Rio Ave",
"preco_l" : 2.51,
"un" : "un",
"preco" : 2.51,
"preco_v" : 2.51,
"id" : NumberLong(1),
"stock" : NumberLong(21)
},
{
"categoria" : "Estatina",
"receita" : "S",
"des" : "Sinvastatina",
"qt" : 30,
"formato" : "comprimido",
"qt_v" : NumberLong(1),
"pos" : "K23",
"lab" : "Mylan",
"preco_l" : 16.45,
"un" : "un",
"preco" : 16.45,
"preco_v" : 16.45,
"id" : NumberLong(6),
"stock" : NumberLong(25)
}
],
"pontos_r" : NumberLong(10),
"pontos_u" : NumberLong(0),
"total" : 18.96
}
So my objective is to count every medicine -"medicamento"- sorted by different descriptions-"des". Similiar to Count on mysql. Any ideas how? The code above is abount 1 facture.
You need $unwind to get a medicine per document and then $group with $sum to get count per medicine, try:
db.collection.aggregate([
{
$unwind: "$medicamentos"
},
{
$group: {
_id: "$medicamentos.des",
count: { $sum: 1 }
}
}
])

MongoDB between date range query - nested property

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

How to optimise MongoDB search with indexing?

These documents are in my MongoDB collection:
{
"_id" : ObjectId("57f5e1b5c7739d9805edfe85"),
"date" : ISODate("2016-10-01T00:00:00.000Z"),
"query" : "test1",
"page" : "page1/runway/ready-to-wear/ss17/2016/10/christian-dior/",
"clicks" : 17.0,
"impressions" : 161.0,
"ctr" : 0.10559006211180125,
"position" : 8.503105590062113
}
{
"_id" : ObjectId("57f5e1b5c7739d9805edfe86"),
"date" : ISODate("2016-10-01T00:00:00.000Z"),
"query" : "test1",
"page" : "page2/runway/ready-to-wear/ss17/2016/10/christian-dior/",
"clicks" : 17.0,
"impressions" : 161.0,
"ctr" : 0.10559006211180125,
"position" : 8.503105590062113
}
{
"_id" : ObjectId("57f5e1b5c7739d9805edfe87"),
"date" : ISODate("2016-10-01T00:00:00.000Z"),
"query" : "test2",
"page" : "page3/runway/ready-to-wear/ss17/2016/10/christian-dior/",
"clicks" : 17.0,
"impressions" : 161.0,
"ctr" : 0.10559006211180125,
"position" : 8.503105590062113
}
I need to filter and get some documents like these:
{
"_id" : ObjectId("57f5e1b5c7739d9805edfe85"),
"date" : ISODate("2016-10-01T00:00:00.000Z"),
"query" : "test1",
"page" : "page1/runway/ready-to-wear/ss17/2016/10/christian-dior/",
"clicks" : 17.0,
"impressions" : 161.0,
"ctr" : 0.10559006211180125,
"position" : 8.503105590062113
}
{
"_id" : ObjectId("57f5e1b5c7739d9805edfe86"),
"date" : ISODate("2016-10-01T00:00:00.000Z"),
"query" : "test1",
"page" : "page2/runway/ready-to-wear/ss17/2016/10/christian-dior/",
"clicks" : 17.0,
"impressions" : 161.0,
"ctr" : 0.10559006211180125,
"position" : 8.503105590062113
}
I created an index using query field and ran db.query using aggregate() method like this:
{
"aggregate" : "Mycollection Name" ,
"pipeline" : [
{ "$match" : { "$text" : { "$search" : "\"test1\""}}},
{ "$match" : { "date" : { "$gte" : { "$date" : "2016-10- 01T00:00:00.000Z"} ,"$lte" : { "$date" : "2016-10-01T00:00:00.000Z"}}}},
{ "$group" : { "_id" : "$page" , "clicks" : { "$sum" : "$clicks"} , "impressions" : { "$sum" : "$impressions"} , "ctr" : { "$avg" : "$ctr"} , "position" : { "$avg" : "$position"}}} ,
{ "$sort" : { "clicks" : -1}}
]
}
This query is working but it is not return exactly search.
How can I optimize this query?

MongoDB : geospatial index not getting added

I have a mongo collection where each document has a 'loc' array as follows:
> db.trucks.findOne()
{
"_id" : ObjectId("52afe2a9e8de3f311ec675ee"),
"objectid" : "427856",
"fooditems" : "Cupcakes",
"facilitytype" : "Truck",
"loc" : [
37.7901490737255,
-122.398658184604
],
"priorpermit" : "0",
"location" : {
"latitude" : "37.7901490874965",
"needs_recoding" : false,
"longitude" : "-122.398658184594"
},
"lot" : "055",
"cnn" : "101000",
"status" : "REQUESTED",
"schedule" : "http://bsm.sfdpw.org/PermitsTracker/reports/report.aspx?title=schedule&report=rptSchedule&params=permit=13MFF-0068&ExportPDF=1&Filename=13MFF-0068_schedule.pdf",
"locationdescription" : "01ST ST: STEVENSON ST to JESSIE ST (21 - 56)",
"latitude" : "37.7901490737255",
"blocklot" : "3708055",
"address" : "50 01ST ST",
"received" : "Mar 14 2013 3:34PM",
"applicant" : "Cupkates Bakery, LLC",
"longitude" : "-122.398658184604",
"expirationdate" : "2013-03-15T00:00:00",
"permit" : "13MFF-0068",
"y" : "2115738.283",
"x" : "6013063.33",
"block" : "3708"
}
When I try to index on 'loc', it doesn't get added:
> db.trucks.ensureIndex( { loc : "2d" } )
> db.trucks.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "food.trucks",
"name" : "_id_"
}
]
What am I doing wrong?
Shouldn't be db.trucks.ensureIndex( { loc : "2d" } )? You are creating indexes on some other collection.

MongoDB query to break ties and remove duplicates

I have documents which have a Version, URL, and DateAdded field (among others but these are the relevant ones).
I'd like to find all documents where the Version is "5.5" and the DateAdded is less than or equal to January 1, 2013. That's pretty straightforward, but I also want the following behavior:
If two or more documents have the same URL, only return the one with the most recent DateAdded (provided, again, that is is less than or equal to January 1, 2013). It would be great if all of this could be expressed in a single query (but my main concern is performance).
I've been doing this last bit of filtering in my client code (outside of MongoDB) but this ends up being inefficient, not to mention inelegant.
I've also tried using Mongo's MapReduce functionality to accomplish the same thing but this is extremely slow, as it appears to copy much of my collection to another collection.
Is there a performant solution?
This should do the trick.
Example data:
db.foo.insert({ "_id" : ObjectId("528bd5bded29286a62959513"), "Version" : "5.3", "URL" : "foo.bar.com/asdfwoaef", "DateAdded" : ISODate("2012-10-05T00:00:00Z") })
db.foo.insert({ "_id" : ObjectId("528bd5e8ed29286a62959514"), "Version" : "5.6", "URL" : "foo.bar.com/asdfwoaef", "DateAdded" : ISODate("2012-12-05T00:00:00Z") })
db.foo.insert({ "_id" : ObjectId("528bd621ed29286a62959515"), "Version" : "5.5", "URL" : "foo.bar.com/aafoobbb", "DateAdded" : ISODate("2012-11-04T00:00:00Z") })
db.foo.insert({ "_id" : ObjectId("528bd629ed29286a62959516"), "Version" : "5.5", "URL" : "foo.bar.com/aafoobbb", "DateAdded" : ISODate("2012-11-05T00:00:00Z") })
db.foo.insert({ "_id" : ObjectId("528bd642ed29286a62959517"), "Version" : "5.5", "URL" : "foo.bar.com/aafoobbb", "DateAdded" : ISODate("2013-01-02T00:00:00Z") })
db.foo.insert({ "_id" : ObjectId("528bd744ed29286a62959518"), "Version" : "5.5", "URL" : "foo.bar.com/ccbarcc", "DateAdded" : ISODate("2013-01-02T00:00:00Z") })
db.foo.insert({ "_id" : ObjectId("528bd780ed29286a62959519"), "Version" : "5.5", "URL" : "foo.bar.com/ccbarcc", "DateAdded" : ISODate("2012-04-05T00:00:00Z") })
Pipeline:
pipeline = [
{
"$match" : {
"Version" : "5.5",
"DateAdded" : {
"$lt" : ISODate("2013-01-01T00:00:00Z")
}
}
},
{
"$sort" : {
"URL" : 1,
"DateAdded" : -1
}
},
{
"$group" : {
"_id" : "$URL",
"doc" : {
"$first" : {
"id" : "$_id",
"DateAdded" : "$DateAdded"
}
}
}
}
]
db.foo.aggregate(pipeline)
And here is the result:
{
"result" : [
{
"_id" : "foo.bar.com/ccbarcc",
"doc" : {
"id" : ObjectId("528bd780ed29286a62959519"),
"DateAdded" : ISODate("2012-04-05T00:00:00Z")
}
},
{
"_id" : "foo.bar.com/aafoobbb",
"doc" : {
"id" : ObjectId("528bd629ed29286a62959516"),
"DateAdded" : ISODate("2012-11-05T00:00:00Z")
}
}
],
"ok" : 1
}