How to write query for date in mongolab? - mongodb

i have stored data like this
"C_Newsletter": {
"date": {
"$date": "2015-10-20T09:52:26.498Z"
}
},
For this how can i write query for date search in mongolab.here i want to search
2015-10-20 .where ever 2015-10-20 matches i need to show
i am new to mongo lab some one help me out for this.i have written like this
{
"C_Newsletter": {
"date": {
"$date": "2015-10-20T09:52:26.498Z"
}
}
}
but its showing only one data .becoz of exact time and date.my expectation i want to get entire 2015-10-20 data

Create a date range query using the $gt and $lte operators where you search for dates between a particular range i.e. end of previous day to end of day in question, something like the following:
{
"C_Newsletter": {
"date": {
"$gt": { "$date": "2015-10-19T23:59:59.999Z" },
"$lte": { "$date": "2015-10-20T23:59:59.999Z" }
}
}
}

Related

MongoDB convert BsonTimestamp to Date

Is there an (efficient) way of converting a MongoDB document field with of type BsonTimestamp to a Date field. Do I have to create a temporary field to store the Date. Do I have to write a custom JS migartion script and loop over every item for this?
from this:
"ts": {
"$timestamp": {
"t": 1620986905,
"i": 1
}
}
to this:
"ts": {
"$date": {
"$numberLong": "1620986905626"
}
}

Mongodb get document that has max value for each subdocument

I have some data looking like this:
{'Type':'A',
'Attributes':[
{'Date':'2021-10-02', 'Value':5},
{'Date':'2021-09-30', 'Value':1},
{'Date':'2021-09-25', 'Value':13}
]
},
{'Type':'B',
'Attributes':[
{'Date':'2021-10-01', 'Value':36},
{'Date':'2021-09-15', 'Value':14},
{'Date':'2021-09-10', 'Value':18}
]
}
I would like to query for each document the document with the newest date. With the data above the desired result would be:
{'Type':'A', 'Date':'2021-10-02', 'Value':5}
{'Type':'B', 'Date':'2021-10-01', 'Value':36}
I managed to find some queries to find over all sub document only the global max. But I did not find the max for each document.
Thanks a lot for your help
Storing date as string is generally considered as bad pratice. Suggest that you change your date field into date type. Fortunately for your case, you are using ISO date format so some effort could be saved.
You can do this in aggregation pipeline:
use $max to find out the max date
use $filter to filter the Attributes array to contains only the latest element
$unwind the array
$project to your expected output
Here is the Mongo playground for your reference.
This keeps 1 member from Attributes only, the one with the max date.
If you want to keep multiple ones use the #ray solution that keeps all members that have the max-date.
*mongoplayground can lose the order, of fields in a document,
if you see wrong result, test it on your driver, its bug of mongoplayground tool
Query1 (local-way)
Test code here
aggregate([
{
"$project": {
"maxDateValue": {
"$max": {
"$map": {
"input": "$Attributes",
"in": { "Date": "$$this.Date", "Value": "$$this.Value" },
}
}
},
"Type": 1
}
},
{
"$project": {
"Date": "$maxDateValue.Date",
"Value": "$maxDateValue.Value"
}
}
])
Query2 (unwind-way)
Test code here
aggregate([
{
"$unwind": { "path": "$Attributes" }
},
{
"$group": {
"_id": "$Type",
"maxDate": {
"$max": {
"Date": "$Attributes.Date",
"Value": "$Attributes.Value"
}
}
}
},
{
"$project": {
"_id": 0,
"Type": "$_id",
"Date": "$maxDate.Date",
"Value": "$maxDate.Value"
}
}
])

$matching with field added with $dateToString doesn't work

In my MongoDB collection I have documents that contain a nested string field, containing a month and year, e.g. '04/2021'. Sample document:
{
"_id": {
"$oid": "608ba45cec43c5b24cda034b"
},
"status": "pass",
"stage": 5,
"priority": 0,
"payload": {
"company_id": "8800",
"company_name": "<MY COMPANY>",
"target_period": "04/2021"
},
"retry_count": 0,
"build_number": "101",
"job_name": "P123",
"createdAt": {
"$date": "2021-04-30T06:31:56.000Z"
},
"updatedAt": {
"$date": "2021-05-10T03:55:44.686Z"
}
}
I am trying to write an aggregation pipeline that will dynamically return documents where said field points to the past month. For example, ran this month (May 2021) I would get documents labeled with '04/2021'. From this post I found the oneliner for getting the comparison string: new Date(new Date().getFullYear(), new Date().getMonth(), 1). (I understand that by the virtue of getMonth returning a zero-based index of month, getting the previous month works by accident and has to be solved somehow.)
This pipeline does not work:
[
{
$addFields: {
previous_month: {
$dateToString: {
'date': new Date(new Date().getFullYear(), new Date().getMonth(), 1),
'format': '%m/%G'
}
}
}
},
{
$match: {
"payload.target_period": "$previous_month"
}
}
]
With MongoDB Compass I can see that the field previous_month is populated just fine by the $addFields stage (above sample document gets value 04/2021), but the $match stage returns 0 documents. I'm running MongoDB version 4.2.12.
You should use $expr operator while trying to self reference another ket in a document inside
$match stage.
[
{
$addFields: {
previous_month: {
$dateToString: {
'date': new Date(new Date().getFullYear(), new Date().getMonth(), 1),
'format': '%m/%G'
}
}
}
},
{
$match: {
$expr: {
$eq: [ "$payload.target_period", "$previous_month" ],
},
}
}
]
Instead of doing whole process in query, I think you can prepare input date in your client language, (js, nodejs) easily,
have prepared a function zeroFill it will return number with concat 0 if its less than 10,
get previous month date and pick previous month
concat both month and year
function zeroFill(i) { return (i < 10 ? '0' : '') + i; }
var date = new Date();
date.setMonth(date.getMonth() - 1);
let searchDate = zeroFill(date.getMonth() + 1) + "/" + date.getFullYear();
console.log(searchDate); // mm/yyyy
Your query would be just:
[{ $match: { "payload.target_period": searchDate } }]
Playground
I would suggest moment.js library, it is much simpler to use:
{ $match: { "payload.target_period": moment().startOf("months").subtract(1, "months").format("MM/YYYY") } }

mongodb aggregate get current date

I'm using metabase and I have native mongodb query. I want to filter documents created yesterday. The problem is that I only have json. Is there any way to compute yesterday?
my json is:
[...
{
"$match": {
"createdAt": { "$ne": "$yesterday" },
}
},
...]
Unfortunately Metabase does not allow to use Date() to get now Date. also you should notice that dateFromString is available in version 3.6 of mongoDB and newer but another problem here is i think dateFromString does not work well with now Date in aggregate and mongoDB return an error that you should pass a string to convert to Date in dateFromString!
so i suggest to you to get yesterday Date in metabase write code something like this :
[{
"$project": {
"user": 1,
"createdAt": 1,
"yesterday": {
"$subtract": [ISODate(), 86400000]
}
}
},
{
"$project": {
"user": 1,
"yesterday": 1,
"createdAt": 1,
"dateComp": { "$cmp": ["$yesterday", "$createdAt"] }
}
},
{
"$match": {
"dateComp": -1
}}]
In Metabase, you can actually use dates relative to today, such as yesterday, by using Date(). This is a workaround currently implemented in the mongo driver for metabase. This workaround internally handles the date as a String, so we have to parse it before trying to use yesterday as a Date.
[
{
"$project": {
"_id": 1,
"todayHandledAsString": Date(),
"todayHandledAsDate": {"$dateFromString": {
"dateString": Date()
}}
}
},
{
"$project": {
"_id": 1,
"todayHandledAsString": 1,
"todayHandledAsDate": 1,
"yesterday": {
"$subtract": ["$todayHandledAsDate", 86400000]
}
}
}
]
Unfortunately, Metabase also disallows operations or comments, so we have to use a hardcoded value of 86400000 instead of 24 * 60 * 60 * 1000, which is a single day in millis.
pay_status is a field of current table. After map them,then you can choose.
[
{$match:{{pay_status}}},
{$match:{{pay_time}}},
{$project:{...}}
]

Searching date in mongodb

In mongodb collection i have field called event_startdate Which is in following format
event_startdate:2018-10-14 16:00:00.000 (type:date)
i am storing date and time together is this field and want to serach event which is happening today and using query given bellow
var date= moment().format('YYYY-MM-D')
Event.find({ event_startdate:date}).exec()
Since time also attached to event_startdate i am unable to fetch today's detail.
is there a way to find this?
var date= moment().format('YYYY-MM-D') would give you a string which then you are trying to compare to an ISO date in mongo.
Try something among these lines:
db.getCollection('COLNAME').aggregate([
{
"$match": {
"$expr": {
$eq: [
"2018-10-10", // <--- You string date goes here
{
"$dateToString": {
"date": "$date",
"format": "%Y-%m-%d"
}
}
]
}
}
}
])
This is using the $expr pipeline operator with dateToString.
You can also do using find.
db.getCollection('loginDetail').find({
"$expr": {
$eq:
[ "2018-09-21", { "$dateToString": { "date": "$eventDate", "format": "%Y-%m-%d"
}
}
]
}
})