Retrieve all items pertaining to a specific week in the calendar

I'm trying to obtain a list of week ranges for all data in my MongoDB. When a week range is clicked, only the records for that specific week range should be displayed. By clicking on the week range, the ID of the week (let's say 42, representing the 42nd week of the year 2015) should be used to retrieve the results.

Query: How do I search for records based on a week number and year? Will it work as expected?

SCHEMA:

var orderSchema = mongoose.Schema({
        date: Date, //ISO date
        request: {
            headers : {
            ...

First Step: Retrieve all week IDs for all Objects:

    var query = Order.aggregate(
        [
            {
                $project:
                {
                    week:
                    {
                        $week: '$date'
                    }
                }
            },
            {
                $group:
                {
                    _id: null,
                    distinctDate:
                    {
                        $addToSet:
                        {
                            week: '$week'
                        }
                    }
                }
            }
        ]
    );

Result:

distinctDate: Array[35]
    0: Object
       week: 40
    1: Object
       week: 37
       ...

Convert these IDs to week ranges using MomentJS and display:

    data.forEach(function(v, k) {
        $scope.weekRanges.push(getWeekRange(v.week));
    });

    function getWeekRange(weekNum) {

        var monday = moment().day("Monday").isoWeek(weekNum).format('MM-DD-YYYY');
        var sunday = moment().day("Sunday").isoWeek(weekNum).format('MM-DD-YYYY');
        ...

Output:

Week 
10-12-2015 to 10-18-2015 //week ID 42
10-05-2015 to 10-11-2015 //week ID 41
09-28-2015 to 10-04-2015 ...
...

Second Step: Select a week range and retrieve Objects Per Week ID:

var year = 2015;
var weekID = weekParamID; //42

    if (!Order) {
        Order = mongoose.model('Order', orderSchema());
    }

    var query = Order.aggregate(
        {
            $project:
            {
                cust_ID : '$request.headers.custID',
                cost : '$response.body.pricing.cost',
                year :
                {
                    $year:  '$date'
                },
                month :
                {
                    $month: '$date'
                },
                week:
                {
                    $week: '$date'
                },
                day:
                {
                    $dayOfMonth: '$date'
                }
            }
        },
        {
            $match:
            {
                year : year, //2015
                week : weekID //42
            }
        }
    );

Clicking on the Week Range 10-12-2015 to 10-18-2015 (week ID 42) returns results outside of the selected range, showing dates like 10-19-2015:

10-19-2015      Order info  
10-18-2015      Order info
10-19-2015      Order info

Using MongoDB command line:

db.mycollection.aggregate({ $project: { week: { $week: '$date' }, day: { $dayOfMonth: '$date' } }  }, { $match: { week: 42 } }

Results:

{ "_id" : "1bd482f6759b", "week" : 42, "day" : 19 } //shouldn't exceed week range
{ "_id" : "b3d38759", "week" : 42, "day" : 19 }

EDIT: Update

A difference is noted between MongoDB ISO weeks (starting on Sunday) and Moment JS ISO weeks (starting on Monday).

This post on Stack Overflow recommends adjusting the dates in the query to ensure the Mongo date begins on a Monday:

{ 
$project: 
  {
    week: { $week: [ "$datetime" ] },
    dayOfWeek:{$dayOfWeek:["$datetime"]}}
  },
{
$project:
 {
  week:{$cond:[{$eq:["$dayOfWeek",1]},{$subtract:["$week",1]},'$week']}
 }
}

I've integrated this adjustment into my query, but unfortunately, it's not fetching the two specified fields that I need:

            cust_ID : '$request.headers.custID',
            cost : '$response.body.pricing.cost'

Query:

 db.mycollection.aggregate(
        {
            $project:
            {
                cust_ID : '$request.headers.custID',
                cost : '$response.body.pricing.cost',
                week:
                {
                    $week: ['$date']
                },
                dayOfWeek:
                {
                    $dayOfWeek: ['$date']
                }
            }
        },
        {
            $project:
            {
                week: {
                    $cond: [
                        {
                            $eq: [
                                "$dayOfWeek", 1
                            ]
                        },
                        {
                            $subtract: [
                                "$week", 1
                            ]
                        }, '$week'
                    ]
                }
            }
        },
        {
            $match:
            {
                week : 42
            }
        }
    );

Results:

{ "_id" : "387e2", "week" : 42 }
{ "_id" : "ef269f6341", "week" : 42 }
{ "_id" : "17482f6759b", "week" : 42 }
{ "_id" : "7123d38759", "week" : 42 }
{ "_id" : "ff89b1fb", "week" : 42 }

The specified fieldsets from $project are missing in the results.

Answer №1

When using the MongoDB $week operator, weeks are considered to begin on Sundays. For more information, you can refer to the documentation:

According to MongoDB, weeks start on Sundays, with week 1 starting on the first Sunday of the year. This behavior aligns with the strftime standard library function's "%U" operator.

On the other hand, Moment.JS's isoWeekday() follows the ISO week system where weeks begin on Mondays. Additionally, it defines week 1 as the first week to include a Thursday.

This discrepancy may be the reason for the inconsistency you are experiencing.

For instance, if a document is saved in MongoDB on a Monday:

db.test.save({ "date" : new ISODate("2015-10-19T10:10:10Z") })

and then the aggregation query is executed, resulting in week 42.

However, running the following code:

console.log(moment().day("Monday").isoWeek(42))

It displays a date different from the one saved in MongoDB, despite being the Monday of the reported week by MongoDB.

To address this issue, it depends on which definition of a week you require.

If the MongoDB $week definition suffices, you can easily find or devise an alternative implementation to convert the week number to the corresponding date. One option is a library that adds strftime support to Moment.js:

https://github.com/benjaminoakes/moment-strftime

Alternatively, if you prefer the ISO format, the solution is more complex. You would need to consider the difference in week start days and the discrepancy in week numbers at the start of the year. In 2015, it seems adding 1 week to the strftime week to align with the ISO week, while also considering the week start day, may be necessary, but this approach may not be universally applicable.

Answer №2

As of MongoDB version 3.4, the $isoWeek aggregation operator is now available for use.

This operator returns the week number in ISO 8601 format, ranging from 1 to 53. Week numbers begin at 1 with the week (Monday through Sunday) that includes the year's first Thursday.

For more information on this, refer to the MongoDB documentation.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having Trouble Concatenating Two Parameters in a JavaScript Function

I am attempting to retrieve 2 numbers as arguments for the function saveQuestion, however, I'm encountering an issue. $("#questionRow") .append('<input type="submit" class="btn btn-default" id="saveQuestion' + addSectionCount + & ...

The error message "AWS Lambda Node 18: fetch is not defined, please resolve or include global fetch" indicates that

Seeking assistance with calling the Pagespeed Insights API from an AWS Lambda using Node 18. Struggling to make fetch() function properly. Cloudwatch logs indicate the message "inside the try about to fetch," but then nothing else appears. The Lambda con ...

Angular - Implementing an Object Mapping Feature

Looking to dynamically generate parameter objects in Angular with a structure like this: [ password: {type: 'String', required: true, value: 'apassword'}, someRandomParam: {type: 'Integer', required: false, value:3} ] ...

When using a wildcard router in Node.js/Express.js, the static router may not be recognized

While using this specific route along with my other routes, I encounter an issue with serving static files: var public_dir = path.join(__dirname, 'public'); app.use('/public', express.static(public_dir)); However, when I add the follo ...

Utilizing the Spread Operator in combination with a function call within the props of the Tab component in Material UI

I came across this code snippet in Material UI: <Tab label="Item One" {...a11yProps(1)} />. It uses the spread operator (...) with a function call within the props. However, when I tried to use it separately like: console.log(...a11yProps(3 ...

Choosing a box will cause a dashed rectangle to appear when the mouse is selected

Whenever I try to select an option in my select box, a dotted rectangle appears. How do I remove this feature? https://i.sstatic.net/BzsL2.png I have noticed that many others are also facing the same issue. I tried updating my CSS with some properties ba ...

Challenges with CORS in AngularJS and Spring Security

I am currently in the process of setting up a module that combines Angular with Spring Security for user login and registration purposes. Everything seems to be working fine when I register a new user. However, I am encountering an error when the final ste ...

Prevent onlick actions until JavaScript function has completed

I run a dynamic quiz website using PHP, JavaScript, and MySQL. The quiz consists of multiple choice questions with answer options displayed on four buttons. <input type = "button" value="$alt1" onClick="changeQuestion('alternative1'); this.st ...

Issue with Pymongo: Unable to filter collection by epoch date

I am facing an issue with filtering a Mongodb collection based on a date field in the document stored in unix epoch format. myquery = {"created_at": {"$gt": 1623384000}} docs = mycollection.find(myquery) Expectedly, this should return ...

How can one achieve the equivalent of Flask Safe when making an ajax call?

Having trouble replicating equivalent functions in my Ajax call as I can in regular Javascript on my main HTML page. Using Python/Flask at the back-end. Any similar methods to use the {{ variable | safe }} syntax in AJAX for similar results? My code snipp ...

When the JSON array is converted into a string, it appears as undefined

Below is a snippet of my service.spec.ts file: service.spec.ts it('should mock the http requests', inject([Service, MockBackend], (service, mockBackend) => { let result:any; mockBackend.connections.subscribe((connection) => { ...

Generate HTML on the fly using Node variables

Utilizing Node.js with Express as the server, I have implemented a feature where users can upload .CSV files containing data. This data is then parsed and stored in a main array made up of arrays, with each line representing one array element. Currently, I ...

Displaying 'N/A' in the chart if the data is missing

I have a chart that displays data, but when data does not exist it shows "undefined%". https://i.sstatic.net/Fm3Tl.png Is there a way to remove the "undefined%" and simply display nothing on the graph if no data exists? Here is the code snippet: import { ...

problem with making ajax requests during the server-side processing of DataTables

Currently tackling server-side processing with datatables, but encountering an ajax error that I'll detail shortly. First things first, here's my code: Table <table id="call_analysis_basic_table" class="display" cellspacing="0" width="100%"& ...

The functionality of the slick slider seems to be malfunctioning

I've been trying to integrate the slick slider into my website, but it just won't work. I've double-checked everything multiple times, but I can't seem to find the issue. It's driving me crazy! If anyone can help me identify the pr ...

Numerous routers available for enhancing functionality in an Ember application

Can an Ember app have multiple router.js files? By default, one router.js file will look like this: import Ember from 'ember'; import config from '../../config/environment'; var Router = Ember.Router.extend({ location: config.locat ...

Having issues with closing a div tag using $.after() function

This issue can be better understood with an example: http://jsbin.com/lavonexuse The challenge here is to insert a full-width row after a specific column (identified by the class .insertion-point) when "Insert Row" is clicked. The problem I'm facing ...

Utilizing ReactStrap: a guide to retrieving the id of the chosen dropDownItem

In my code, I have a dropdownList component with various DropdownItems: <Dropdown isOpen={this.state.dropdownOpen[3]} toggle={() => { this.toggle(3); }} > <DropdownToggle className="my-dropdown" car ...

Setting a JavaScript variable to null

Using Jquery, I have a variable that is assigned a value on button click. After the code executes successfully, I need to reset the variable to null. $("#btnAdd").click(function () { var myDataVariable= {}; myDataVariable.dataOne="SomeDa ...

Using Regular Expressions in Express routing

Does anyone have experience serving a file with a dynamic hash in its name on a specific route? The file is named like workbox-someHash.js and the hash changes every time the app is deployed. I attempted to serve it using the following code snippets: &qu ...