Mongo $filter with date comparison - mongodb

I have the following aggregation which has a date comparison where I only want to grab documents that have the $$item.date less than the current time.
[
{ $match : { "_id" : "57b4c5f0291ebb13110b888e" } },
{ $project : {
"fulfillments" : {
$filter : {
"input" : "$fulfillments",
"as" : "item",
"cond" : { "$gte" : ["$$item.date","new Date()"]}
}
}
}
},
...
...
]
The important part that I have a question about above is the following:
"cond" : { "$gte" : ["$$item.date","new Date()"]}
This doesn't seem to be working as I can change the new Date() to 1 or 0 or pretty much any value and it still returns all documents. I need it to only return documents that have the date greater than or equal to the current date.
For example, given the following document
{
"_id": "57b4c5f0291ebb13110b888e",
"fulfillments": [
{
"_id": "582deb33bb117300010a2ae5",
"date": new Date("2016-11-23T17:00:00-0700"),
},
{
"_id": "582deb33bdf17300010a2ae5",
"date": new Date("2017-11-23T17:00:00-0700"),
}
}
Only the following fulfillment should be returned because it is 2017-11-23
{
"_id": "582deb33bdf17300010a2ae5",
"date": new Date("2017-11-23T17:00:00-0700"),
}
Update
There is question if I am giving an accurate document strucutre, so I included a screenshot below to validate this.

If you just want the current time on the machine just remove the " from the query, see below for my example
> db.test.find().pretty()
{
"_id" : "57b4c5f0291ebb13110b888e",
"fulfillments" : [
{
"_id" : "582deb33bb117300010a2ae5",
"date" : ISODate("2016-11-24T00:00:00Z")
},
{
"_id" : "582deb33bdf17300010a2ae5",
"date" : ISODate("2017-11-24T00:00:00Z")
}
]
}
>
> db.test.aggregate([
... { $match : { "_id" : "57b4c5f0291ebb13110b888e" } },
... { $project : {
... "fulfillments" : {
... $filter : {
... "input" : "$fulfillments",
... "as" : "item",
... "cond" : { "$gte" : ["$$item.date",new Date()]}
... }
... }
... }
... }
... ]).pretty()
{
"_id" : "57b4c5f0291ebb13110b888e",
"fulfillments" : [
{
"_id" : "582deb33bdf17300010a2ae5",
"date" : ISODate("2017-11-24T00:00:00Z")
}
]
}
>

Related

How to search mongodb

I have two JSONs in a collection in mongodb and would like to write a bson.M filter to fetch the first JSON below.
I tried with the filter below to get the first JSON but got no result.
When the first JSON is in the collection, I get result when i use the filter
but when i have both JSONs, I do not get a result. Need help.
filter := bson.M{"type": "FPF", "status": "REGISTERED","fpfInfo.fpfInfoList.ssai.st": 1, "fpfInfo.fpfInfoList.infoList.dn": "sim"}
{
"_id" : "47f6ad68-d431-4b69-9899-f33d828f8f9c",
"type" : "FPF",
"status" : "REGISTERED",
"fpfInfo" : {
"fpfInfoList" : [
{
"ssai" : {
"st" : 1
},
"infoList" : [
{
"dn" : "sim"
}
]
}
]
}
},
{
"_id" : "347c8ed2-d9d1-4f1a-9672-7e8a232d2bf8",
"type" : "FPF",
"status" : "REGISTERED",
"fpfInfo" : {
"fpfInfoList" : [
{
"ssai" : {
"st" : 1,
"ds" : "000004"
},
"infoList" : [
{
"dn" : "sim"
}
]
}
]
}
}
db.collection.aggregate([
{
"$unwind": "$fpfInfo.fpfInfoList"
},
{
"$match": {
"fpfInfo.fpfInfoList.ssai.ds": {
"$exists": false
},
"fpfInfo.fpfInfoList.infoList.dn": "sim",
"fpfInfo.fpfInfoList.ssai.st": 1
}
}
])
Playground

How to get elements from an array based on condition in MongoDB?

I am the beginner in MongoDB & Here is my sample doc given below :
{
"plan_id" : "100",
"schedule_plan_list" : [
{
"date" : "01-05-2020",
"time" : "9:00AM -10:00AM"
},
{
"date" : "02-05-2020",
"time" : "10:00AM -11:00AM"
},
{
"date" : "03-05-2020",
"time" : "9:00AM -10:00AM"
},
{
"date" : "04-05-2020",
"time" : "9:30AM -10:30AM"
},
{
"date" : "05-05-2020",
"time" : "9:00AM -10:00AM"
},
{
"date" : "06-05-2020",
"time" : "9:00AM -10:00AM"
},
{
"date" : "07-05-2020",
"time" : "9:30AM -10:30AM"
},
{
"date" : "08-05-2020",
"time" : "4:00PM -5:00PM"
}
]
}
I want to get next 5 elements ** based on given date is **"02-05-2020"
My given query fetch only match "02-05-2020" but I want "02-05-2020","03-05-2020",.."06-05-2020"
db.getCollection('schedule_plans').find({"plan_id" : "100"},{_id:0,"schedule_plan_list": { "$elemMatch": { "date" : "02-05-2020"}}})
so anyone help me to solve this
You can try below aggregation query :
db.collection.aggregate([
{ $match: { "plan_id": "100" } },
/** You can re-create `schedule_plan_list` field with condition applied & slice the new array to keep required no.of elements in array */
{
$project: {
_id: 0,
"schedule_plan_list": {
$slice: [
{
$filter: { input: "$schedule_plan_list", cond: { $gte: [ "$$this.date", "02-05-2020" ] } }
},
5
]
}
}
})
Test : mongoplayground
Ref : aggregation

Filter result after an unwind

I've got an aggregation with an unwind :
{
$unwind: { "path":"$contributions", preserveNullAndEmptyArrays:true}
},
Output :
contributions" : {
"_id" : ObjectId("5b4e0636d3befc00155ffb8e"),
"creationDate" : ISODate("2018-07-17T15:07:34.172+0000"),
"validationDate" : ISODate("2018-07-17T15:07:42.008+0000"),
},
contributions" : {
"_id" : ObjectId("5b4e0636d3befc00155ffb8e"),
"rejectionDate" : ISODate("2018-07-17T15:07:34.172+0000"),
"validationDate" : ISODate("2018-07-17T15:07:42.008+0000"),
},
Now I want to filter this result to show only result that doesn't have a rejectionDate. So in this example, it should show only one result.
I try to add a filter :
$filter: {
input: `$contributions`, as: 'item',
cond: { $and: [
{ $not: '$$item.rejectionDate' },
...dateRangeFilterHelper('$$item.contributionDate', period)
] }
}
But it doesn't work like that.
instead of $not you can use $exists operator. you might get the desired output. Also if you can post the sample dataset and desired output then it will help to write the complete query.
The following query can get us the expected output:
db.collection.aggregate([
{
$addFields:{
"contributions":{
$filter:{
"input":"$contributions",
"as":"contribution",
"cond":{
$eq:["$$contribution.rejectionDate", undefined]
}
}
}
}
}
]).pretty()
Data set:
{
"_id" : ObjectId("5d7275c4eb1b7fdde7ea09e8"),
"contributions" : [
{
"_id" : ObjectId("5b4e0636d3befc00155ffb8e"),
"creationDate" : ISODate("2018-07-17T15:07:34.172Z"),
"validationDate" : ISODate("2018-07-17T15:07:42.008Z")
},
{
"_id" : ObjectId("5b4e0636d3befc00155ffb8e"),
"rejectionDate" : ISODate("2018-07-17T15:07:34.172Z"),
"validationDate" : ISODate("2018-07-17T15:07:42.008Z")
}
]
}
Output:
{
"_id" : ObjectId("5d7275c4eb1b7fdde7ea09e8"),
"contributions" : [
{
"_id" : ObjectId("5b4e0636d3befc00155ffb8e"),
"creationDate" : ISODate("2018-07-17T15:07:34.172Z"),
"validationDate" : ISODate("2018-07-17T15:07:42.008Z")
}
]
}

Mongo Aggregation $filter on ISO date value

I have the following document
{
"_id": "57b4c5f0291ebb13110b888e",
"first": "John",
"last": "Smith",
"email": "John.Smith#gmail.com",
"fulfillments": [
{
"_id": "57b683e531a5a21679b78e6d",
"created_by_name": "John Smith",
"created_by_id": "57b4c5f0291ebb23110b888e",
"fulfilled_by_name": "John Smith",
"fulfilled_by_id": "57b4c5f0291ebb13110b888e",
"date": new Date("2016-08-23T13:58:15-0700")
}
]
}
For which I have a mongo query that I want to just return the list of fulfillments that have not already occured. This means that the date property on the fulfillment embedded document is greater than the current time.
db.users.aggregate([
{ $match : { "_id" : "57b4c5f0291ebb13110b888e" } },
{ $project : {
"fulfillments" : {
$filter : {
"input" : "$fulfillments",
"as" : "item",
"cond" : ...SOMETHING HERE TO FILTER ON 'date'
}
}
}
},
{ $unwind : "$fulfillments" },
{ $project : {
"created_by_name" : "$fulfillments.created_by_name",
"created_by_id" : "$fulfillments.created_by_id",
"fulfilled_by_name" : "$fulfillments.fulfilled_by_name",
"fulfilled_by_id" : "$fulfillments.fulfilled_by_id",
"date" : "$fulfillments.date"
}
}
])
I can't figure out what the proper way is to filter on only fulfillments that the date has not already occured.
The following should give you the desired result
...
$project : {
"fulfillments" : {
$filter : {
"input" : "$fulfillments",
"as" : "item",
"cond" : { $gt: [ "$$item.date", new Date() ] }
}
}
}
...

mongodb aggregation find min value and other fields in nested array

Is it possible to find in a nested array the max date and show its price then show the parent field like the actual price.
The result I want it to show like this :
{
"_id" : ObjectId("5547e45c97d8b2c816c994c8"),
"actualPrice":19500,
"lastModifDate" :ISODate("2015-05-04T22:53:50.583Z"),
"price":"16000"
}
The data :
db.adds.findOne()
{
"_id" : ObjectId("5547e45c97d8b2c816c994c8"),
"addTitle" : "Clio pack luxe",
"actualPrice" : 19500,
"fistModificationDate" : ISODate("2015-05-03T22:00:00Z"),
"addID" : "1746540",
"history" : [
{
"price" : 18000,
"modifDate" : ISODate("2015-05-04T22:01:47.272Z"),
"_id" : ObjectId("5547ec4bfeb20b0414e8e51b")
},
{
"price" : 16000,
"modifDate" : ISODate("2015-05-04T22:53:50.583Z"),
"_id" : ObjectId("5547f87e83a1dae00bc033fa")
},
{
"price" : 19000,
"modifDate" : ISODate("2015-04-04T22:53:50.583Z"),
"_id" : ObjectId("5547f87e83a1dae00bc033fe")
}
],
"__v" : 1
}
my query
db.adds.aggregate(
[
{ $match:{addID:"1746540"}},
{ $unwind:"$history"},
{ $group:{
_id:0,
lastModifDate:{$max:"$historique.modifDate"}
}
}
])
I dont know how to include other fields I used $project but I get errors
thanks for helping
You could try the following aggregation pipeline which does not need to make use of the $group operator stage as the $project operator takes care of the fields projection:
db.adds.aggregate([
{
"$match": {"addID": "1746540"}
},
{
"$unwind": "$history"
},
{
"$project": {
"actualPrice": 1,
"lastModifDate": "$history.modifDate",
"price": "$history.price"
}
},
{
"$sort": { "lastModifDate": -1 }
},
{
"$limit": 1
}
])
Output
/* 1 */
{
"result" : [
{
"_id" : ObjectId("5547e45c97d8b2c816c994c8"),
"actualPrice" : 19500,
"lastModifDate" : ISODate("2015-05-04T22:53:50.583Z"),
"price" : 16000
}
],
"ok" : 1
}