I have to implement a subscription where users can choose to subscribe his products which will get delivered to him on each alternate from the date he subscribed or with a Two Day Gap from the subscribed date.
//Sample Data
[
{
"subscribed_on": ISODate("2017-01-01T08:15:39.736Z"),
"_id" : 1,
"customer" : "jon doe",
"type": "alternate"
},
{
"subscribed_on": ISODate("2017-01-02T08:15:39.736Z"),
"_id" : 1,
"customer" : "Doe John",
"type": "Two Day Gap"
},
{
subscribed_on: ISODate("2017-01-02T08:15:39.736Z"),
"_id" : 1,
"customer" : "Foo Name",
"type": "alternate"
}
]
Now for each day I have to query to find the list of the customers which have the delivery for today's date.
How can I aggregate so that I can calculate if the current date is the alternate date or lies in two-day gap?
To simplify the query for alternate I can check if the current date is even or odd and will query the date opposite it. Like if the current date is 1st Jan which is odd I can query to find the date which is even for alternate subscription query. Is this correct efficient way for finding alternate date?
What will be the current way to find the subscription for Two Day Gap type?
Related
I'm using vue.js v2. From my api I get an object with some date fields in ISO format but vue.js is not correctly displaying those value in an input tag.
<input type="date" class="form-control" v-model="lastPortalInvoiceDate">
Value found via the vue debug extension in Edge
"2022-02-06T23:00:00Z"
Value returned in JSON from api
{
"data": {
"portalInvoiceNumberPrefix": "I-{{BY}}-",
"portalInvoiceFilePrefix": "ABC",
"lastPortalInvoiceNumber": 1,
"lastPortalInvoiceDate": "2022-02-06T23:00:00Z",
"nextBookYearSwitchDate": "2022-02-10T23:00:00Z",
"id": 1,
"value": 1
},
"tenantId": 1,
"responseType": "ok",
"responseMessages": [
"Successfully read PortalInvoiceConfig"
]
}
Select a date with datepicker and see the changes in your data. You will see the output in format 'yyyy-mm-dd'.
You must format your date. For this, you can split your time string to parse date only.
yourDateStr = yourDateStr.split('T')[0]; //if your date is "2022-02-06T23:00:00Z" format
Parsing with new Date(yourDateStr) will cause you trouble setting the right time zone. So, if you want a simple solution you could do just parse the date.
Pretty self-explanatory.
I searched multiple mongo aggregation documentation documents, and built the query the best I could.
Worth to point out I have almost none aggregation experience, and this is onde of the most complex aggregates I have done so far.
let currentYear = new Date();
currentYear.setFullYear(currentYear.getFullYear());
currentYear.setMonth(0);
currentYear.setDate(1);
await Order.aggregate([
{ $match: {
order_ordered_on:{
$gte: currentYear
},
order_status: 'Delivered'
}},
{ $group : {
_id: {month: {$month : '$order_ordered_on'}},
total: {$sum: '$order_total'},
}},
{ $sort : {
_id : 1
}},
{$project: {
_id:1,
total: 1
}}
]).exec((err, result) =>{
if (err) throw err;
let amount = result.map(a => a.total);
res.json({
amount
});
})
To explain my thought process, First I set a date for current year, january first until current time.
Then I match it with the order_ordered_on which has the date which Im working of, and the also match to select only the orders which have the Delivered status.
I group by _id to divide it in months and sum the total amount by months aswell.
Sort it in ascending order do order the array and project the resulting data.
After that I map the result to an array, which is my goal(each position in the array corresponds to a months profit).
The problem is that the total value being returned is absurd and it doesnt match what is expected. Since I dont have much experience, I could not find where Im making the aggregation mistake.
Any help is appreciated.
To make myself clearer, Im currently using a single Order model, and the order_ordered_on, order_status and order_total fields.
The main goal of this aggregate is to split the current year profit in monthly profits, from january 1st until now, and then plot it in a graph through front-end development. The data contains Orders from 2017 until current day. The format the front-end needs to receive is that of an ordered array with the profit values.
I know that it's possible to query by timestamp as seen in previous question, However, what if the date is in the following format:
{
"lambeosaurus": {
"date" : "2012-20-03",
"length" : 12.5,
"weight": 5000
},
"stegosaurus": {
"date" : "2015-25-13",
"length" : 9,
"weight" : 2500
}
}
How would I go about and query this by date?
You've stored your dates as strings. When Firebase order strings it uses lexicographic ordering. In that order, "2012-20-03" comes before "2012-25-01".
This is the reason why the question you linked to (and the Firebase documentation) usually store dates as timestamps. Those have all the information about the date, in a single number that is guaranteed to be ordered correctly.
Alternatively, you can store the date as a string. But in that case you have to make sure the date is in a format that will lexicographically order correctly too. For your sample that would be: "2012-01-25" and "2012-03-20".
So in this case your only option is to change the data structure to either what was in the original question (and documentation) or to a string format that orders in the order you want.
Convert it to timestamp :
new Date('2012-20-03'.split('-').reverse().join('/')).getTime()
In general :
function toTimeStamp(dateString){
return new Date(dateString.split('-').reverse().join('/')).getTime()
}
As you can see here, on the X-Axis the dates are equidistant inspite of the date's varying in range.
[Right click->Open in a new tab if you can't see the pic]
But the X-axis distance is equivalent for both.
I want the X-axis to show value 0, when there's no value for a particular date..
Possible Solutions:
Is there any inbuilt parameter that am missing within AMcharts itself for this?
The other solution i had in mind was to input value 0 for date's having no corresponding data. [But this will lag the front
end]
The date format issue where:
For a date, 2014-11-12 10:15, the "dataDateFormat": "YYYY-MM-DD
JJ:NN" doesn't seem to work.
Tried to do it in milliseconds as well, didn't work.
Here's my fiddle
"dataProvider": [{
"date": "1343364300000",
"value": 1
},{
"date": "1343364900000",
"value": 5
},{
"date": "1343365500000",
"value": 10
},{
"date": "1343366100000",
"value": 15
},{
"date": "1343366100000",
"value": 8
},{
"date": "1343369520000",
"value": 24
},]
This is the chart am using for this.
http://www.amcharts.com/demos/date-based-data/#
For first point I think if you need to display 0 on empty data the only way is to implement your zero fill function on server side or JS.
I ran with same issue months ago and had to implement on my server side because there isn't any built in function in the library to do that.
Second point. Your date formatter is running ok, the problem is you have pan and zoom activated together. Then you are not able to zoom and see formatted dates because categoryAxis.parseDates groups them in Months. I would suggest you disable chartCursor.pan and put a min period on category axis of mm or ss.
Here's your modified fiddle.
I have set of docs in my couchdb here I mentioned one sample doc:
{
"_id": "26",
"_rev": "1-53ac67e9ec4b4ce8ffa9cd609e107aaf",
"customer_name": "Vadilal",
"type": "trip",
"duration": "10 hours 27 mins",
"end_time": "Jan 1, 2014 10:11:00 PM",
"start_time": "Jan 11, 2014 8:46:00 AM",
}
If I pass timestamp(key) from the URL, if it is in between start_time and end_time then i want to get the docs.
Example:
suppose url would be like this
.../trip/_design/trip/_view/trip?key="Jan 10, 2014 8:46:00 AM"
Here I am passing timestamp as Jan 10, 2014 8:46:00 AM so it comes in between start_time and end_time of above mentioned doc, in this case I need fetch the remaining information.
Kindly help to figure out this problem, it would be great help to me.
I have written function like below :
function(doc){
if(doc.type=="trip"){
var startTime=new Date(doc.start_time);
var endTime=new Date(doc.end_time);
emit([startTime.getTime(),endTime.getTime()], doc);
}
And calling URL as below :
../trip/_design/trip/_view/trip?startkey=[1390086890000]&endkey=[1390086890000,{}]
is above one correct according to my requirement???
That is unfortunately not possible. There are two problems with you requirement.
Views are arranged by a key
You could write a view like this to index documents by the start key or the end key respectively.
function(doc){
emit(doc.start_time, doc_id); // amend with end key to index by end key.
}
you can use three parameters in your query:
key - matches an exact key
startkey - matches all documents that are greater or equal to the start key
endkey - matches all documents that are greater or equal to the end key
The sorting problem
Depending on the type your index keys will be sorted either alphabetically or as integers.
So if your view trip is using a start key like this:
.../trip/_design/trip/_view/trip?start_key="Jan 10, 2014 8:46:00 AM"
You could return all values greater or equal to the string "Jan 10, 2014..." which would be true for "Jan 11, 2014" or "Jan 31, 2014" but there would be false positives for "July 22, 2011" or false negatives for "Feb 01, 2014" as F < J.
To solve this issue you will have to convert the start date to something that can be sorted in time order eg:
parse the date to date time and then convert to epoch like How to get time in milliseconds since the unix epoch in Javascript?
convert the date to yyyyMMddHHmmss formate like 20140110084600
Both of these will sort correctly.
Can you solve your problem
Yes, but with a little client side code. Here's the recipe:
create two views trip/by_start_date and trip/by_end_date which return the start and end date as keys respectively. In a way that is sorted as per the second section above.
Get two sets of documents.
Set 1 should return all documents that start before your date: ..._view/by_start_date?endkey=[your_date]
set 2 should return all documents that end after your date: ..._view/by_end_date?startkey=[your_date]
You then have two sets of document ids and the result you were after will be those documents that are in both these sets.
Further optimization
In the above solution you might just get too many values returned to handle. You can further cut it down using CouchDB's ability to key on more than one value. Key by both start and end date like this:
function(doc){
var start_time = some_conversion_function(doc.start_time);
var end_time = some_conversion_function(doc.end_time);
emit([start_time, end_time], doc_id);
}
If you have any more details on the maximum difference between start time and end time you can use this to further reduce the documents in each set. The below example will return the documents that start no later than X days before date and no later than date and end no later than X days after date.
..._view/by_start_date?startkey=[date-X,]&endkey=[date, date+X]
You can apply a similar logic to the by_end_date view.