2
\$\begingroup\$

Simple code for getting documents that have a creationDate between two values in mongodb.

If the user provides only one of the values the code should still work and get the documents that have either a creationDate less than or bigger than the given value.

I'm mainly looking for more readability and simplicity.

interface mongoDateFilter {
 $gte?: Date;
 $lte?: Date;
}
export const getReportsForContent = async (
 contentId: ObjectId,
 beginDate: Date | undefined,
 endDate: Date | undefined,
): Promise<Report[]> => {
 const reportsCollection = await getCollection('reports');
 const creationDateMongoFilter: mongoDateFilter = {};
 if (beginDate) {
 creationDateMongoFilter['$gte'] = beginDate;
 }
 if (endDate) {
 creationDateMongoFilter['$lte'] = endDate;
 }
 let reportsForContent: Report[] = [];
 if (beginDate || endDate) {
 reportsForContent = await reportsCollection.find({ contentId, creationDate: creationDateMongoFilter }).toArray();
 } else {
 reportsForContent = await reportsCollection.find({ contentId }).toArray();
 }
 return reportsForContent;
};
```
CertainPerformance
8,7331 gold badge14 silver badges26 bronze badges
asked Dec 8, 2020 at 18:14
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Prefer dot notation over bracket notation when syntax permits it - it's a bit easier to read and write. ESLint rule: dot-notation.

Construct objects all in one go rather than mutating them afterwards, if you can - it's easier to write (especially in TypeScript, since you don't have to denote the type ahead of time) and can be easier to understand at a glance when unnecessary mutation is avoided.

Don't assign expressions that won't be used - with

let reportsForContent: Report[] = [];

regardless of the situation, reportsForContent will be reassigned to something else afterwards, so you can leave off the = [] part.

Or, even better:

Return the value retrieved instead of reassigning a variable and then returning the variable. This:

 if (beginDate || endDate) {
 reportsForContent = await reportsCollection.find({ contentId, creationDate: creationDateMongoFilter }).toArray();
 } else {
 reportsForContent = await reportsCollection.find({ contentId }).toArray();
 }

can be

 if (beginDate || endDate) {
 return reportsCollection.find({ contentId, creationDate: creationDateMongoFilter }).toArray();
 } else {
 return reportsCollection.find({ contentId }).toArray();
 }

Or, even better, handle the case where no date is set at the very beginning, and only construct the creationDateMongoFilter later, if it's needed.

In all:

export const getReportsForContent = async (
 contentId: ObjectId,
 beginDate: Date | undefined,
 endDate: Date | undefined,
): Promise<Report[]> => {
 const reportsCollection = await getCollection('reports');
 if (!beginDate && !endDate) {
 return reportsCollection.find({ contentId }).toArray();
 }
 const creationDateMongoFilter = {
 (...beginDate && { $gte: beginDate }),
 (...endDate && { $lte: endDate }),
 };
 return reportsCollection.find({ contentId, creationDate: creationDateMongoFilter }).toArray();
};

No need for the mongoDateFilter interface anymore.

answered Dec 8, 2020 at 18:45
\$\endgroup\$
2
  • \$\begingroup\$ Sending undefined to one of $gte or $lte while the other one is a defined and a date, will not result in the same behavior as supplying only one of $gte or $lte that's why I had those if statements and conditionally filled the creationDateMongoFilter object \$\endgroup\$ Commented Dec 9, 2020 at 22:53
  • 1
    \$\begingroup\$ Oh, that's unfortunate, that's a surprisingly strict interpretation Mongo has. Tweak is simple enough, you can conditionally add properties to the object during its definition, see stackoverflow.com/q/11704267 \$\endgroup\$ Commented Dec 10, 2020 at 0:27

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.