Explorar o código

further enhancements

Enzo hai 1 ano
pai
achega
5823ad0c5b
Modificáronse 2 ficheiros con 92 adicións e 44 borrados
  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.
     private filterFromObs(...conditions: Conditions[]) {
-        let enquiry = conditions[0]
-        let key = Object.keys(enquiry)[0]
+        let searchObj = Object.assign({}, ...conditions)
         this.dataFromStorage.subscribe({
             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)
                     } else {
                         // console.log(`${element.header.messageName} does not match search criteria`)
-                    }
+                    } 
                 } else {
-                    if (this.hasKeyAndValue(element, ...conditions)) {
+                    if (this.filterByKeyValue(element, ...conditions)) {
                         this.filteredResult.next(element)
                     } else {
                         // 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
-    private hasKeyAndValue(data, ...conditions): boolean {
+    private filterByKeyValue(data, ...conditions): boolean {
         // Merge all conditions into searchObj
         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') {
             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. 
         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 {
         // 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));
         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[],
     msgPayload?: string,
     messageID?: string,
-    regex?: string
+    regex?: string,
+    dateRange?: DateRange
+}
+export interface DateRange {
+    startDate?: string | Date,
+    endDate?: string | Date
 }
-
 export interface Storage {
     type: 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 { queryService } from "../services/query.service"
 import { Conditions, Storage } from "../services/query.service"
@@ -5,26 +9,50 @@ import { _, isObject } from 'lodash'
 
 let query = new queryService()
 
+//For now just local file storage. More will be preapred in the design phase later.
 let storageAddress: Storage = {
     type: "File",
     address: "payload.json"
 }
 
-let conditions: Conditions[] = [
+// Array inquiry: should return mutiple data
+let conditions1: Conditions[] = [
     { 'msgTag': ['free'] }
 ]
+
+// Basic inquiry, but with multi search: should return one data
 let conditions2: Conditions[] = [
     { "msgId": "4f710c4b-a258-4c7e-a4b6-6095bb7028e9" },
     { "msgLogDateTime": "2023-01-14T21:50:19.917Z" },
 ]
 
+// Value only argument! : should return one data
 let conditions3: Conditions[] = [
     { "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