Browse Source

further enhancements

Enzo 1 year ago
parent
commit
5823ad0c5b
2 changed files with 92 additions and 44 deletions
  1. 58 38
      services/query.service.ts
  2. 34 6
      test/test1.ts

+ 58 - 38
services/query.service.ts

@@ -30,18 +30,17 @@ export class queryService {
 
 
     // Search and Filter: Pure Observables. To be moved out to become a separate service again.
     // Search and Filter: Pure Observables. To be moved out to become a separate service again.
     private filterFromObs(...conditions: Conditions[]) {
     private filterFromObs(...conditions: Conditions[]) {
-        let enquiry = conditions[0]
-        let key = Object.keys(enquiry)[0]
+        let searchObj = Object.assign({}, ...conditions)
         this.dataFromStorage.subscribe({
         this.dataFromStorage.subscribe({
             next: element => {
             next: element => {
-                if (key == "regex") {
-                    if (this.filterViaRegex(element, enquiry)) {
+                if (Object.keys(conditions).length == 1 && searchObj.hasOwnProperty('regex')) {
+                    if (this.filterViaRegex(element, searchObj.regex)) {
                         this.filteredResult.next(element)
                         this.filteredResult.next(element)
                     } else {
                     } else {
                         // console.log(`${element.header.messageName} does not match search criteria`)
                         // console.log(`${element.header.messageName} does not match search criteria`)
-                    }
+                    } 
                 } else {
                 } else {
-                    if (this.hasKeyAndValue(element, ...conditions)) {
+                    if (this.filterByKeyValue(element, ...conditions)) {
                         this.filteredResult.next(element)
                         this.filteredResult.next(element)
                     } else {
                     } else {
                         // console.log(`${element.header.messageName} does not match search criteria`)
                         // console.log(`${element.header.messageName} does not match search criteria`)
@@ -70,41 +69,51 @@ export class queryService {
     }
     }
 
 
     // Logic 2: Success: More superior version than Logic 1 since it can perform flat searches like {messageID : 1234} without specifying its nested properties
     // Logic 2: Success: More superior version than Logic 1 since it can perform flat searches like {messageID : 1234} without specifying its nested properties
-    private hasKeyAndValue(data, ...conditions): boolean {
+    private filterByKeyValue(data, ...conditions): boolean {
         // Merge all conditions into searchObj
         // Merge all conditions into searchObj
         let searchObj = Object.assign({}, ...conditions)
         let searchObj = Object.assign({}, ...conditions)
+        let dateCheck = true
+        if (searchObj.hasOwnProperty("dateRange")) {
+            dateCheck = this.filterByDateRange(data, searchObj.dateRange)
+            // Must delete, otherwise the function below will attempt to match date range with the date property and it will inevitably returns false
+            delete searchObj.dateRange
+        } 
         if (typeof data !== 'object' || typeof searchObj !== 'object') {
         if (typeof data !== 'object' || typeof searchObj !== 'object') {
             return false;
             return false;
         }
         }
 
 
-        let matchKeys = Object.keys(searchObj);
-        let isMatchingObject = (object) => {
-            return matchKeys.every((key) => {
-                let lodashPath = key.replace(/\[(\w+)\]/g, '.$1').replace(/^\./, '');
-                let objectValue = _.get(object, lodashPath);
-                let searchValue = searchObj[key];
-
-                if (Array.isArray(searchValue) && key === 'msgTag') {
-                    // Check if any of the search values are included in the object value
-                    return searchValue.some((value) => {
-                        return Array.isArray(objectValue) ? objectValue.includes(value) : objectValue === value;
-                    });
-                } else if (typeof searchValue === 'object' && typeof objectValue === 'object') {
-                    return isMatchingObject(objectValue);
-                } else {
-                    return objectValue === searchValue;
+        if(dateCheck == true){
+            let matchKeys = Object.keys(searchObj);
+            let isMatchingObject = (object) => {
+                return matchKeys.every((key) => {
+                    let lodashPath = key.replace(/\[(\w+)\]/g, '.$1').replace(/^\./, '');
+                    let objectValue = _.get(object, lodashPath);
+                    let searchValue = searchObj[key];
+    
+                    if (Array.isArray(searchValue) && key === 'msgTag') {
+                        // Check if any of the search values are included in the object value
+                        return searchValue.some((value) => {
+                            return Array.isArray(objectValue) ? objectValue.includes(value) : objectValue === value;
+                        });
+                    } else if (typeof searchValue === 'object' && typeof objectValue === 'object') {
+                        return isMatchingObject(objectValue);
+                    } else {
+                        return objectValue === searchValue;
+                    }
+                });
+            };
+    
+            let isObjectMatching = (object) => {
+                if (typeof object !== 'object') {
+                    return false;
                 }
                 }
-            });
-        };
-
-        let isObjectMatching = (object) => {
-            if (typeof object !== 'object') {
-                return false;
-            }
-            return isMatchingObject(object) || Object.values(object).some(isObjectMatching);
-        };
-
-        return isObjectMatching(data);
+                return isMatchingObject(object) || Object.values(object).some(isObjectMatching);
+            };
+    
+            return isObjectMatching(data);
+        } else {
+            return false
+        }
 
 
         /* This function first merges all the ...conditions objects into a single searchObj object using the Object.assign() method. 
         /* This function first merges all the ...conditions objects into a single searchObj object using the Object.assign() method. 
         It then checks whether both data and searchObj are of type object. If either one is not an object, the function returns false.
         It then checks whether both data and searchObj are of type object. If either one is not an object, the function returns false.
@@ -124,11 +133,18 @@ export class queryService {
 
 
     private filterViaRegex(element: any, inquiry: any): boolean {
     private filterViaRegex(element: any, inquiry: any): boolean {
         // create a new regular expression to use regex.test
         // create a new regular expression to use regex.test
-        const regex = new RegExp(inquiry.regex);
+        const regex = new RegExp(inquiry);
         const hasMatchingSubstring = regex.test(JSON.stringify(element));
         const hasMatchingSubstring = regex.test(JSON.stringify(element));
         return hasMatchingSubstring;
         return hasMatchingSubstring;
     }
     }
-    
+
+    private filterByDateRange(data: any, dateRange: DateRange): boolean {
+        const start = new Date(dateRange.startDate);
+        const end = new Date(dateRange.endDate);
+        const target = new Date(data.header.dateCreated);
+        return target >= start && target <= end;
+    }
+
 }
 }
 
 
 
 
@@ -143,9 +159,13 @@ export interface Conditions {
     msgTag?: string[],
     msgTag?: string[],
     msgPayload?: string,
     msgPayload?: string,
     messageID?: string,
     messageID?: string,
-    regex?: string
+    regex?: string,
+    dateRange?: DateRange
+}
+export interface DateRange {
+    startDate?: string | Date,
+    endDate?: string | Date
 }
 }
-
 export interface Storage {
 export interface Storage {
     type: string,
     type: string,
     address: string
     address: string

+ 34 - 6
test/test1.ts

@@ -1,3 +1,7 @@
+/* the key is to do it in one line. Client just pass 2 arguments, one is the location of the data, which could be file, sql or mongodb, and also
+pass in the conditions of their search enquiries. We will aslo have to cater to different file storage location to determine how to prep the
+data to be filtered
+ */
 import { Observable } from "rxjs"
 import { Observable } from "rxjs"
 import { queryService } from "../services/query.service"
 import { queryService } from "../services/query.service"
 import { Conditions, Storage } from "../services/query.service"
 import { Conditions, Storage } from "../services/query.service"
@@ -5,26 +9,50 @@ import { _, isObject } from 'lodash'
 
 
 let query = new queryService()
 let query = new queryService()
 
 
+//For now just local file storage. More will be preapred in the design phase later.
 let storageAddress: Storage = {
 let storageAddress: Storage = {
     type: "File",
     type: "File",
     address: "payload.json"
     address: "payload.json"
 }
 }
 
 
-let conditions: Conditions[] = [
+// Array inquiry: should return mutiple data
+let conditions1: Conditions[] = [
     { 'msgTag': ['free'] }
     { 'msgTag': ['free'] }
 ]
 ]
+
+// Basic inquiry, but with multi search: should return one data
 let conditions2: Conditions[] = [
 let conditions2: Conditions[] = [
     { "msgId": "4f710c4b-a258-4c7e-a4b6-6095bb7028e9" },
     { "msgId": "4f710c4b-a258-4c7e-a4b6-6095bb7028e9" },
     { "msgLogDateTime": "2023-01-14T21:50:19.917Z" },
     { "msgLogDateTime": "2023-01-14T21:50:19.917Z" },
 ]
 ]
 
 
+// Value only argument! : should return one data
 let conditions3: Conditions[] = [
 let conditions3: Conditions[] = [
     { "regex": "cum incidunt maxime voluptatibus" }
     { "regex": "cum incidunt maxime voluptatibus" }
 ]
 ]
-query.query(storageAddress, ...conditions3).subscribe((element) => { console.log(`${element.header.messageName} is matched`) })
 
 
-// query.query(storageAddress, ...conditions2).subscribe((element) => { console.log(`${element.header.messageName} is matched`) })
+// Date Range inquiry: Should return multiple data
+let conditions4: Conditions[] = [
+    {
+        "dateRange": {
+            "startDate": "2023-04-09T21:00:00.000Z",
+            'endDate': "2023-04-10T00:00:00.000Z"
+        }
+    }
+]
+
+// Multi conditions except for regex search: Should return at least 1 data
+let conditions5: Conditions[] = [
+    {
+        "dateRange": {
+            "startDate": "2023-04-09T21:00:00.000Z",
+            'endDate': "2023-04-10T00:00:00.000Z"
+        }
+    },
+    { 'msgTag': ['basic'] },
+    { "msgId": "4f710c4b-a258-4c7e-a4b6-6095bb7028e9" },
+    { "msgLogDateTime": "2023-01-14T21:50:19.917Z" }
+]
+query.query(storageAddress, ...conditions4).subscribe((element) => { console.log(`${element.header.messageName} is matched`) })
+
 
 
-// the key is to do it in one line. Client just pass 2 arguments, one is the location of the data, which could be file, sql or mongodb, and also
-// pass in the conditions of their search enquiries. We will aslo have to cater to different file storage location to determine how to prep the
-// data to be filtered