Skip to content

Commit 783c928

Browse files
committed
feat(call): enhance filter processing to support ISO date strings
- Added functionality to convert ISO date strings and ISODate notation to Date objects within the filter processing logic. - Updated documentation in templates and tools schemas to reflect support for date strings in ISO format. - Improved handling of nested objects and arrays in the filter to ensure consistent date conversion. This enhancement improves the flexibility of date handling in MongoDB queries. resolves #27
1 parent 591816e commit 783c928

File tree

3 files changed

+80
-16
lines changed

3 files changed

+80
-16
lines changed

src/schemas/call.ts

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,45 @@ function processObjectIdInFilter(
241241
): Filter<Document> {
242242
// If objectIdMode is "none", don't convert any strings to ObjectIds
243243
if (objectIdMode === "none") {
244-
return filter as Filter<Document>;
244+
// Create a new filter object to handle dates
245+
const result: Record<string, unknown> = {};
246+
247+
for (const [key, value] of Object.entries(filter)) {
248+
if (typeof value === "string" && isISODateString(value)) {
249+
// Convert ISO date string to Date object
250+
result[key] = new Date(value);
251+
} else if (typeof value === "string" && value.startsWith("ISODate(") && value.endsWith(")")) {
252+
// Handle ISODate("2025-01-01T00:00:00Z") format
253+
const dateString = value.substring(8, value.length - 2);
254+
if (isISODateString(dateString)) {
255+
result[key] = new Date(dateString);
256+
} else {
257+
result[key] = value;
258+
}
259+
} else if (typeof value === "object" && value !== null) {
260+
if (Array.isArray(value)) {
261+
// For arrays, apply date conversion to each item
262+
result[key] = value.map((item) => {
263+
if (typeof item === "string" && isISODateString(item)) {
264+
return new Date(item);
265+
} else if (typeof item === "string" && item.startsWith("ISODate(") && item.endsWith(")")) {
266+
const dateString = item.substring(8, item.length - 2);
267+
return isISODateString(dateString) ? new Date(dateString) : item;
268+
}
269+
return item;
270+
});
271+
} else {
272+
// Process nested objects
273+
result[key] = processObjectIdInFilter(
274+
value as Record<string, unknown>,
275+
"none"
276+
);
277+
}
278+
} else {
279+
result[key] = value;
280+
}
281+
}
282+
return result as Filter<Document>;
245283
}
246284

247285
const result: Record<string, unknown> = {};
@@ -259,21 +297,32 @@ function processObjectIdInFilter(
259297
} else {
260298
result[key] = value;
261299
}
300+
} else if (typeof value === "string" && isISODateString(value)) {
301+
// Convert ISO date string to Date object
302+
result[key] = new Date(value);
303+
} else if (typeof value === "string" && value.startsWith("ISODate(") && value.endsWith(")")) {
304+
// Handle ISODate("2025-01-01T00:00:00Z") format
305+
const dateString = value.substring(8, value.length - 2);
306+
if (isISODateString(dateString)) {
307+
result[key] = new Date(dateString);
308+
} else {
309+
result[key] = value;
310+
}
262311
} else if (typeof value === "object" && value !== null) {
263312
if (Array.isArray(value)) {
264313
// For arrays, apply the same logic to each item
265-
if (
266-
objectIdMode === "force" ||
267-
(objectIdMode === "auto" && isObjectIdField(key))
268-
) {
269-
result[key] = value.map((item) =>
270-
typeof item === "string" && isObjectIdString(item)
271-
? new ObjectId(item)
272-
: item,
273-
);
274-
} else {
275-
result[key] = value;
276-
}
314+
result[key] = value.map((item) => {
315+
if (typeof item === "string" && isObjectIdString(item) &&
316+
(objectIdMode === "force" || (objectIdMode === "auto" && isObjectIdField(key)))) {
317+
return new ObjectId(item);
318+
} else if (typeof item === "string" && isISODateString(item)) {
319+
return new Date(item);
320+
} else if (typeof item === "string" && item.startsWith("ISODate(") && item.endsWith(")")) {
321+
const dateString = item.substring(8, item.length - 2);
322+
return isISODateString(dateString) ? new Date(dateString) : item;
323+
}
324+
return item;
325+
});
277326
} else {
278327
// Process nested objects
279328
result[key] = processObjectIdInFilter(
@@ -295,6 +344,12 @@ function isObjectIdString(str: string): boolean {
295344
return /^[0-9a-fA-F]{24}$/.test(str);
296345
}
297346

347+
// Helper function to check if a string is in ISO date format
348+
function isISODateString(str: string): boolean {
349+
// Check if string matches ISO 8601 format
350+
return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,3})?Z$/.test(str);
351+
}
352+
298353
function formatResponse(data: unknown): {
299354
content: [{ type: string; text: string }];
300355
} {

src/schemas/templates.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ Example queries:
3939
3. Find documents with existing email:
4040
{ "email": { "$exists": true } }
4141
42+
4. Find documents with dates:
43+
// Using ISO date string format
44+
{ "createdAt": { "$gt": "2023-01-01T00:00:00Z" } }
45+
// Using ISODate syntax
46+
{ "createdAt": { "$gt": ISODate("2023-01-01T00:00:00Z") } }
47+
4248
Use these patterns to construct MongoDB queries.`,
4349
},
4450
],

src/schemas/tools.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ export async function handleListToolsRequest({
2525
type: "string",
2626
description: "Name of the collection to query",
2727
},
28-
filter: { type: "object", description: "MongoDB query filter" },
28+
filter: {
29+
type: "object",
30+
description: "MongoDB query filter. Supports date strings in ISO format ('2025-01-01T00:00:00Z') and ISODate('2025-01-01T00:00:00Z') notation"
31+
},
2932
projection: {
3033
type: "object",
3134
description: "Fields to include/exclude",
@@ -63,7 +66,7 @@ export async function handleListToolsRequest({
6366
},
6467
pipeline: {
6568
type: "array",
66-
description: "Aggregation pipeline stages",
69+
description: "Aggregation pipeline stages. Supports date strings in ISO format ('2025-01-01T00:00:00Z') and ISODate('2025-01-01T00:00:00Z') notation",
6770
items: {
6871
type: "object",
6972
},
@@ -96,7 +99,7 @@ export async function handleListToolsRequest({
9699
},
97100
filter: {
98101
type: "object",
99-
description: "Filter to select documents to update",
102+
description: "Filter to select documents to update. Supports date strings in ISO format ('2025-01-01T00:00:00Z') and ISODate('2025-01-01T00:00:00Z') notation",
100103
},
101104
update: {
102105
type: "object",

0 commit comments

Comments
 (0)