From 18fe01d2f942b2486cdc69de70dcfa70c3363ca2 Mon Sep 17 00:00:00 2001
From: "d.buechler" <d.buechler@adito.de>
Date: Thu, 7 Nov 2019 12:23:56 +0100
Subject: [PATCH] Pattern gets now filled and used to search Refactorings and
 Bugfixes

---
 .../onActionProcess.js                        |   7 +-
 process/DuplicateScanner_lib/process.js       | 407 ++++++------------
 2 files changed, 124 insertions(+), 290 deletions(-)

diff --git a/entity/DuplicateScanner_entity/entityfields/runactiongroup/children/rebuildpersonduplicatescache/onActionProcess.js b/entity/DuplicateScanner_entity/entityfields/runactiongroup/children/rebuildpersonduplicatescache/onActionProcess.js
index 29ce7c3af2..5c808d0603 100644
--- a/entity/DuplicateScanner_entity/entityfields/runactiongroup/children/rebuildpersonduplicatescache/onActionProcess.js
+++ b/entity/DuplicateScanner_entity/entityfields/runactiongroup/children/rebuildpersonduplicatescache/onActionProcess.js
@@ -7,15 +7,14 @@ var targetEntity = "Person_entity";
 var recordBlockSize = DuplicateScannerUtils.GetBlockSize();
 logging.log("recordBlockSize -> " + recordBlockSize);
 
-let duplicateFieldsConfig = DuplicateScannerUtils.LoadIndexFieldsConfiguration(filterName, targetEntity);
-let resultFields = DuplicateScannerUtils.LoadResultFields(filterName, targetEntity);
+//let duplicateFieldsConfig = DuplicateScannerUtils.LoadIndexFieldsConfiguration(filterName, targetEntity);
+//let resultFields = DuplicateScannerUtils.LoadResultFields(filterName, targetEntity);
 
 logging.log(filterName + ": Delete duplicates -> ");
 DuplicateScannerUtils.DeleteDuplicateClustersByTargetEntity(targetEntity);
 
 logging.log(filterName + ": Recalculate duplicates -> ");
-DuplicateScannerUtils.RebuildDuplicatesCache(filterName, targetEntity, recordBlockSize,
-duplicateFieldsConfig, resultFields, null);
+DuplicateScannerUtils.RebuildDuplicatesCache(filterName, targetEntity, recordBlockSize, null);
 
 logging.log(filterName + ": Refresh unrelated duplicates -> ");
 DuplicateScannerUtils.RefreshUnrelatedDuplicateRelations(targetEntity);
diff --git a/process/DuplicateScanner_lib/process.js b/process/DuplicateScanner_lib/process.js
index a90a8d0a62..3759c2a2ad 100644
--- a/process/DuplicateScanner_lib/process.js
+++ b/process/DuplicateScanner_lib/process.js
@@ -297,49 +297,32 @@ DuplicateScannerUtils.RebuildDuplicatesCache = function(pFilterName, pTargetEnti
     pRecordsBlockSize, pFormatValuesConsumeWebserviceCallback)
 {
     let useExternalWebservice = _DuplicateScannerUtils._isUseExternalWebservice(pFilterName, pTargetEntity);
-    let alreadyIdentifiedIds = [];
-
-    let duplicateFieldsConfig = DuplicateScannerUtils.LoadIndexFieldsConfiguration(filterName, targetEntity);
     let resultFields = DuplicateScannerUtils.LoadResultFields(filterName, targetEntity);
 
-    //load all entity fields used in the prefilter
-    let filterFieldConfigs = _DuplicateScannerUtils._getFieldConfigsFromFilterFields(pFilterName, pTargetEntity);
-    //logging.log("filterFieldConfigs -> " + filterFieldConfigs);
-
-    let entityFieldsToLoad = _DuplicateScannerUtils._getEntityFieldNamesFromFieldsConfig(duplicateFieldsConfig);
-
-    //logging.log("entityFieldsToLoad initial-> " + entityFieldsToLoad);
-
-    //If the fields from the prefilter aren't in the entity fields to load, add them manually
-    if(filterFieldConfigs.length > 0)
-    {
-        let INDEX_FILTER_FIELD_NAME = 0;
-        for (let i = 0; i < filterFieldConfigs.length; i++)
-        {
-            let filterFieldConfig = filterFieldConfigs[i];
-            let filterFieldName = filterFieldConfig[INDEX_FILTER_FIELD_NAME];
-            //logging.log("filterFieldConfig -> " +filterFieldConfig );
-            if(entityFieldsToLoad.indexOf(filterFieldName) < 0)
-            {
-                //logging.log("Noch nicht vorhanden, hinzufügen -> ");
-                duplicateFieldsConfig.push(filterFieldConfig);
-                entityFieldsToLoad.push(filterFieldName);
-            }
-        }
-    }
+    let indexPattern = _DuplicateScannerUtils._loadIndexPattern(pFilterName, pTargetEntity);
+    let entityFields = _DuplicateScannerUtils._loadEntityFieldsFromPattern(indexPattern);
+    let entityIdField = _DuplicateScannerUtils._loadEntityIdField(pFilterName, pTargetEntity);
+    
+    logging.log("indexPattern -> " +indexPattern );
+    
+    logging.log("entityIdField -> " + entityIdField);
+    
+    //Add the id field to ensure that it's on the first position
+    entityFields = [entityIdField].concat(entityFields);
     
-    //logging.log("entityFieldsToLoad vollsätndig-> " + entityFieldsToLoad);
-    //logging.log("duplicateFieldsConfig vollsätndig-> " + duplicateFieldsConfig);
+    logging.log("entityFields -> " + entityFields);
     
-    let targetRecords = DuplicateScannerUtils.LoadEntityRecords(pTargetEntity, entityFieldsToLoad, 0, pRecordsBlockSize);
+    let alreadyIdentifiedIds = [];
+
+    let targetRecords = DuplicateScannerUtils.LoadEntityRecords(pTargetEntity, entityFields, 0, pRecordsBlockSize);
     //logging.log("Initialer Block geladen targetRecords-> " + JSON.stringify(targetRecords));
 
     let currentRecordIndex = pRecordsBlockSize;
     while(targetRecords.length > 0)
     {
-        foundDuplicateIds = DuplicateScannerUtils.ScanRecords(pFilterName, pTargetEntity, targetRecords,
-            duplicateFieldsConfig, resultFields, useExternalWebservice,
-            pFormatValuesConsumeWebserviceCallback, alreadyIdentifiedIds);
+        foundDuplicateIds = DuplicateScannerUtils.ScanRecords(pTargetEntity, targetRecords,
+            entityFields, resultFields, useExternalWebservice,
+            pFormatValuesConsumeWebserviceCallback, alreadyIdentifiedIds, indexPattern);
         //logging.log("gefundene ids zum ignorieren foundDuplicateIds -> " + foundDuplicateIds);
         alreadyIdentifiedIds = alreadyIdentifiedIds.concat(foundDuplicateIds);
         //logging.log("Gesamte ignorierListe -> " + alreadyIdentifiedIds);
@@ -359,8 +342,8 @@ DuplicateScannerUtils.RebuildDuplicatesCache = function(pFilterName, pTargetEnti
     }
 }
 
-DuplicateScannerUtils.ScanRecords = function(pFilterName, pTargetEntity, pTargetRecordsData,
-    pDuplicateFieldsConfig, pResultFields, pUseExternalWebservice, pFormatValuesConsumeWebserviceCallback, pAlreadyIdentifiedIds)
+DuplicateScannerUtils.ScanRecords = function(pTargetEntity, pTargetRecordsData,
+    pEntityFields, pResultFields, pUseExternalWebservice, pFormatValuesConsumeWebserviceCallback, pAlreadyIdentifiedIds, pIndexPattern)
 {
     //logging.log("in ScanRecords -> ");
     let foundDuplicateIds = [];
@@ -380,14 +363,14 @@ DuplicateScannerUtils.ScanRecords = function(pFilterName, pTargetEntity, pTarget
         //        logging.log("Neuer Record -> " + pTargetRecordsData[b]);
 
         //logging.log("pTargetRecordsData[b] -> " + JSON.stringify(pTargetRecordsData[b]));
-        let entityFieldValuesRay = DuplicateScannerUtils.BuildEntityFieldNameValueRays(pDuplicateFieldsConfig, pTargetRecordsData[b]);
-        //logging.log("Werte des Datensatzes entityFieldValuesRay -> " + JSON.stringify(entityFieldValuesRay));
+        let entityFieldValuesRay = DuplicateScannerUtils.BuildEntityFieldNameValueRays(pEntityFields, pTargetRecordsData[b]);
+        logging.log("Werte des Datensatzes entityFieldValuesRay -> " + JSON.stringify(entityFieldValuesRay));
 
         //The first field in this Array must always be the configured id field. This is ensured using onValidation-logic
         let idField = entityFieldValuesRay[0][0];
         let idValue = entityFieldValuesRay[0][1];
-        //        logging.log("idField -> " + idField);
-        //        logging.log("idValue -> " + idValue);
+                logging.log("idField -> " + idField);
+                logging.log("idValue -> " + idValue);
         //logging.log("pTargetRecordsData[b][idField] -> " + pTargetRecordsData[b][idField]);
         //If the current Id has already been identified, continue
         if(pAlreadyIdentifiedIds.indexOf(pTargetRecordsData[b][idField]) > -1)
@@ -396,22 +379,22 @@ DuplicateScannerUtils.ScanRecords = function(pFilterName, pTargetEntity, pTarget
             continue;
         }
 
-        let foundDuplicates = _DuplicateScannerUtils._scanForDuplicates(pFilterName, pTargetEntity,
-            entityFieldValuesRay, pResultFields, idField, idValue, pFormatValuesConsumeWebserviceCallback, pUseExternalWebservice)
+        let foundDuplicates = _DuplicateScannerUtils._scanForDuplicates(pTargetEntity,
+            entityFieldValuesRay, pResultFields, idField, idValue, pFormatValuesConsumeWebserviceCallback, pUseExternalWebservice, pIndexPattern)
 
         if(foundDuplicates == null || foundDuplicates.length == 0)
         {
-            //logging.log("Keine Datensätze gefunden  continue;-> ");
+            logging.log("Keine Datensätze gefunden  continue;-> ");
             continue;
         }
-        //logging.log("foundDuplicates.length nach _scanForDuplicates -> " + foundDuplicates.length);
+        logging.log("foundDuplicates.length nach _scanForDuplicates -> " + foundDuplicates.length);
 
         //Insert all found duplicate ids into an cache array because those ids don't have to be checked again lateron.
 
         for (let i = 0; i < foundDuplicates.length; i++)
         {
             let localId = foundDuplicates[i][indexsearch.FIELD_ID];
-            //logging.log("foundDuplicates[i] -> " + foundDuplicates[i]);
+            logging.log("foundDuplicates[i] -> " + foundDuplicates[i]);
             foundDuplicateIds.push(localId);
         }
 
@@ -419,14 +402,14 @@ DuplicateScannerUtils.ScanRecords = function(pFilterName, pTargetEntity, pTarget
 
         //The duplicates list contains only the found duplicates to the original id, therefore it get's added manually
         foundDuplicateIds.push(pTargetRecordsData[b][idField]);
-        //logging.log("foundDuplicates -> " + JSON.stringify(foundDuplicates));
-        //logging.log("foundDuplicateIds -> " + JSON.stringify(foundDuplicateIds));
+        logging.log("foundDuplicates -> " + JSON.stringify(foundDuplicates));
+        logging.log("foundDuplicateIds -> " + JSON.stringify(foundDuplicateIds));
 
         let insertQueriesRay = _DuplicateScannerUtils._createInsertDuplicatesClusterQuery(foundDuplicateIds, pTargetEntity)
         duplicatesToInsertQueries = duplicatesToInsertQueries.concat(insertQueriesRay);
         foundDuplicateIds = [];
     }
-    //logging.log("duplicatesToInsertQueries -> " + JSON.stringify(duplicatesToInsertQueries));
+    logging.log("duplicatesToInsertQueries -> " + JSON.stringify(duplicatesToInsertQueries));
     db.inserts(duplicatesToInsertQueries, db.getCurrentAlias(), 10 * datetime.ONE_MINUTE);
     return foundDuplicateIds;
 }
@@ -628,41 +611,24 @@ DuplicateScannerUtils.ScanForDuplicates = function(pFilterName, pTargetEntity, p
 {
     let useExternalWebservice = _DuplicateScannerUtils._isUseExternalWebservice(pFilterName, pTargetEntity);
     let resultFields = DuplicateScannerUtils.LoadResultFields(pFilterName, pTargetEntity);
-
-    let duplicateFieldsConfig = DuplicateScannerUtils.LoadIndexFieldsConfiguration(pFilterName, pTargetEntity);
-    //logging.log("duplicateFieldsConfig -> " + duplicateFieldsConfig);
-    let entityFieldsToLoad = _DuplicateScannerUtils._getEntityFieldNamesFromFieldsConfig(duplicateFieldsConfig);
-    //logging.log("entityFieldsToLoad " + entityFieldsToLoad)
-    //If the fields from the prefilter aren't in the entity fields to load, add them manually
-    let filterFieldConfigs = _DuplicateScannerUtils._getFieldConfigsFromFilterFields(pFilterName, pTargetEntity);
-    //logging.log("filterFieldConfigs " + filterFieldConfigs)
-
-    if(filterFieldConfigs.length > 0)
-    {
-        let INDEX_FILTER_FIELD_NAME = 0;
-        for (let i = 0; i < filterFieldConfigs.length; i++)
-        {
-            let filterFieldConfig = filterFieldConfigs[i];
-            let filterFieldName = filterFieldConfig[INDEX_FILTER_FIELD_NAME];
-            //logging.log("filterFieldName" + filterFieldName)
-            //logging.log("filterFieldConfig -> " +filterFieldConfig );
-            if(entityFieldsToLoad.indexOf(filterFieldName) < 0)
-            {
-                //logging.log("Noch nicht vorhanden, hinzufügen -> ");
-                duplicateFieldsConfig.push(filterFieldConfig);
-            }
-        }
-    }
-
-    let entityFieldValuesRay = DuplicateScannerUtils.BuildEntityFieldNameValueRays(duplicateFieldsConfig, pValuesToCheck);
-    //The first field in this Array must always be the configured id field.
+    
+    let indexPattern = _DuplicateScannerUtils._loadIndexPattern(pFilterName, pTargetEntity);
+    let entityFields = _DuplicateScannerUtils._loadEntityFieldsFromPattern(indexPattern);
+    let entityIdField = _DuplicateScannerUtils._loadEntityIdField(pFilterName, pTargetEntity);
+    
+    //Add the id field to ensure that it's on the first position
+    entityFields = [entityIdField].concat(entityFields);
+    
+    let entityFieldValuesRay = DuplicateScannerUtils.BuildEntityFieldNameValueRays(entityFields, pValuesToCheck);
+   
+   //The first field in this Array must always be the configured id field.
     logging.log("ray " + entityFieldValuesRay.toSource())
     let idField = entityFieldValuesRay[0][0];
     let idValue = entityFieldValuesRay[0][1];
 
-    return _DuplicateScannerUtils._scanForDuplicates(pFilterName, pTargetEntity,
+    return _DuplicateScannerUtils._scanForDuplicates(pTargetEntity,
         entityFieldValuesRay, resultFields, idField, idValue,
-        pFormatValuesConsumeWebserviceCallback, useExternalWebservice)
+        pFormatValuesConsumeWebserviceCallback, useExternalWebservice, indexPattern)
 }
 
 /*
@@ -818,7 +784,6 @@ DuplicateScannerUtils.MergeOrganisation = function(pSourceContactId, pTargetCont
 DuplicateScannerUtils.BuildEntityFieldNameValueRays = function(pDuplicateFieldsConfig, pTargetRecordData)
 {
     let INDEX_CONFIG_ENTITY_FIELD = 0;
-    let INDEX_CONFIG_USE_FOR_SEARCH = 2;
     let entityFieldValuesRay = [];
     /*
     * Based on the parameterized filter field names and the values loaded via the query,
@@ -829,8 +794,13 @@ DuplicateScannerUtils.BuildEntityFieldNameValueRays = function(pDuplicateFieldsC
     {
         //        logging.log("pDuplicateFieldsConfig[a][1] -> " + pDuplicateFieldsConfig[a][INDEX_CONFIG_ENTITY_FIELD]);
         //        logging.log(" pTargetRecordData[a] -> " + pTargetRecordData[a]);
-        let entityField = pDuplicateFieldsConfig[a][INDEX_CONFIG_ENTITY_FIELD];
-        entityFieldValuesRay.push([entityField, pTargetRecordData[entityField], pDuplicateFieldsConfig[a][INDEX_CONFIG_USE_FOR_SEARCH]])
+        let entityField = pDuplicateFieldsConfig[a];
+        let entityFieldValue = pTargetRecordData[entityField];
+        
+        if(entityFieldValue == null)
+            entityFieldValue = "";
+        entityFieldValue = entityFieldValue.trim();
+        entityFieldValuesRay.push([entityField, entityFieldValue]);
     }
     return entityFieldValuesRay.length > 0 ? entityFieldValuesRay : [["", ""]];
 }
@@ -856,85 +826,85 @@ _DuplicateScannerUtils._buildUpdateResetStandardCommunications = function(pSourc
     return [["COMMUNICATION", ["ISSTANDARD"], null, ["0"], "CONTACT_ID = '" + pSourceContactId + "'"]];
 }
 
-_DuplicateScannerUtils._getEntityFieldNamesFromFieldsConfig = function(pDuplicateFieldsConfig)
+/*
+ * Gets the Pattern for the scanner
+ * A pattern usually contains placeholders in the style of "{entityFieldName]"
+ * 
+ * @param {String} pScannerName Name of the filter to use
+ * @param {String} pTargetEntity The target entity which has been assigned to the filters configuration
+ * @returns {String} Scan pattern as string
+ */
+_DuplicateScannerUtils._loadIndexPattern = function(pScannerName, pTargetEntity)
 {
-    let entityFieldsToLoad = [];
-    for (field in pDuplicateFieldsConfig)
-    {
-        entityFieldsToLoad.push(pDuplicateFieldsConfig[field][0]);
-    }
-    return entityFieldsToLoad;
+    let scanPatternQuery = SqlCondition.begin()
+    .and("DUPLICATESCANNER.ENTITY_TO_SCAN_NAME = '" + pTargetEntity + "'")
+    .and("DUPLICATESCANNER.FILTER_NAME = '" + pScannerName + "'")
+    .buildSql("select SCAN_PATTERN from DUPLICATESCANNER");
+
+    return db.cell(scanPatternQuery);
 }
-_DuplicateScannerUtils._getFieldConfigsFromFilterFields = function(pFilterName, pTargetEntity)
+
+_DuplicateScannerUtils._loadEntityFieldsFromPattern = function(indexPattern)
 {
-    let resultFields = [];
-    let filterFields = [];
-    let filters = DuplicateScannerUtils.loadFilters(pFilterName, pTargetEntity)
+    return indexPattern.match(/[^{}]+(?=\})/g);
+}
 
-    for (let i = 0; i < filters.length; i++)
-    {
-        let filter = JSON.parse(filters[i][0]).filter;
-        let fields = JditoFilterUtils.getFilterFields(filter.childs);
-        filterFields = filterFields.concat(fields);
-    }
-    for (let i = 0; i < filterFields.length; i++)
+_DuplicateScannerUtils._replacePlaceholderForValuesInPattern = function(pIndexPattern, pEntityFieldValueRays)
+{
+    let INDEX_ENTITY_FIELD_NAME = 0;
+    let INDEX_ENTITY_FIELD_VALUE = 1;
+
+    let placeholder = "";
+    let fieldValue = "";
+    for (let i = 0; i < pEntityFieldValueRays.length; i++) 
     {
-        let filterField = filterFields[i];
-        resultFields.push([filterField, 0, 0]);
+        placeholder = "{" + pEntityFieldValueRays[i][INDEX_ENTITY_FIELD_NAME] + "}";
+        fieldValue = pEntityFieldValueRays[i][INDEX_ENTITY_FIELD_VALUE];
+        
+        logging.log("placeholder -> " + placeholder);
+        logging.log("fieldValue -> " + fieldValue);
+        pIndexPattern = pIndexPattern.replace(placeholder, fieldValue);
     }
-    return resultFields;
+    return pIndexPattern;
+}
+
+_DuplicateScannerUtils._loadEntityIdField = function(pFilterName, pTargetEntity)
+{
+    let loadEntityIdFieldQuery = SqlCondition.begin()
+    .andPrepare("DUPLICATESCANNER.FILTER_NAME", pFilterName)
+    .andPrepare("DUPLICATESCANNER.ENTITY_TO_SCAN_NAME", pTargetEntity)
+    .buildSql("select ID_FIELD_NAME from DUPLICATESCANNER", "1=2");
+
+    return db.cell(loadEntityIdFieldQuery);
 }
 
 /*
  * @see DuplicateScannerUtils.ScanForDuplicates for the documentation
  */
-_DuplicateScannerUtils._scanForDuplicates = function(pFilterName, pTargetEntity, pFilterFieldValueRays,
-pResultFields, pRecordIdFieldToIgnore, pRecordIdValueToIgnore, pFormatValuesConsumeWebserviceCallback, pUseExternalWebservice)
+_DuplicateScannerUtils._scanForDuplicates = function(pTargetEntity, pEntityFieldNameValueRays,
+pResultFields, pRecordIdFieldToIgnore, pRecordIdValueToIgnore, pFormatValuesConsumeWebserviceCallback, pUseExternalWebservice, pIndexPattern)
 {
-    let possibleDuplicates = [];
-    let ignoredRecordFilter = _DuplicateScannerUtils._getIgnoreRecordFilter(pRecordIdFieldToIgnore, pRecordIdValueToIgnore, pTargetEntity);
-    let configuredFilters = _DuplicateScannerUtils._loadFilters(pFilterName, pTargetEntity);
-
-
-    //logging.log("Found filters -> " + configuredFilters);
-
-    let preFilter = null;
-    
-    //Only run the prefilter if filters have been configured. If not, run the indexsearch based on the field configuration
-    if(configuredFilters != null && configuredFilters.length > 0)
-    {
-        //To ensure the record which the current search is based on isnt found as result, the other configured filters get appended to
-        //the filter of said records to ignore
-        configuredFilters = [ignoredRecordFilter].concat(configuredFilters);
-
-        preFilter =_DuplicateScannerUtils._applyPreFilter(pTargetEntity, configuredFilters, pFilterFieldValueRays);
-
-        //logging.log("preFilter welcher Elemente im erlaubten bereich ausgibt -> " + preFilter);
-        
-        //The scan can be executed even without any prefilters. If a prefilter has been configured but doesn't match the 
-        //threshold criteria no search shall be run.
-        if(preFilter == null)
-            return null;
-    }
-    
-    //No prefilter and no filterfields => No indexsearch
-    if(preFilter == null && pFilterFieldValueRays.length < 1)
+    //No filterfields/indexpattern => No indexsearch
+    if(pEntityFieldNameValueRays.length < 1 || pIndexPattern == null || pIndexPattern == "")
         return null;
-
-    //If at this point the prefilter is null but a search has to be executed, add the ignorefilter manually that the search doesn't find the base record as duplicate to itself.
-    //This is the case if no prefilter but indexfields are configured.
-    if(preFilter == null)
-        preFilter = ignoredRecordFilter;
     
-    possibleDuplicates = _DuplicateScannerUtils._callIndexSearch(pTargetEntity, preFilter, pFilterFieldValueRays, pResultFields, 100);
-    //logging.log("possibleDuplicates -> " + JSON.stringify(possibleDuplicates));
+    let possibleDuplicates = [];
+    let ignoreSourceRecordPattern = _DuplicateScannerUtils._getIgnoreSourceRecordPattern(pRecordIdFieldToIgnore, pRecordIdValueToIgnore);
+   logging.log("ignoreSourceRecordPattern -> " + ignoreSourceRecordPattern);
+    let indexPatternWithValues = _DuplicateScannerUtils._replacePlaceholderForValuesInPattern(pIndexPattern, pEntityFieldNameValueRays);
+    logging.log("indexPatternWithValues -> " + indexPatternWithValues);
+    indexPatternWithValues = ignoreSourceRecordPattern + indexPatternWithValues + ")";
+    logging.log("indexPatternWithValues -> " + indexPatternWithValues);
+    possibleDuplicates = _DuplicateScannerUtils._callIndexSearch(pTargetEntity, indexPatternWithValues, pResultFields, 100);
+    
+    logging.log("possibleDuplicates -> " + JSON.stringify(possibleDuplicates));
     
     if(possibleDuplicates == null)
         return null;
 
     possibleDuplicates = possibleDuplicates[indexsearch.HITS];
     
-    if(pUseExternalWebservice && possibleDuplicates.length > 0 && pFormatValuesConsumeWebserviceCallback != null)
+    if(pUseExternalWebservice && pFormatValuesConsumeWebserviceCallback != null)
         possibleDuplicates = pFormatValuesConsumeWebserviceCallback.apply(this, [possibleDuplicates]);
 
 //    //logging.log("pTargetEntity -> " + pTargetEntity);
@@ -965,161 +935,29 @@ _DuplicateScannerUtils._isUseExternalWebservice = function(pFilterName, pTargetE
     return (isUseWebservice == 0) ? false : true;
 }
 
-/*
- * Applies... the configured prefilters. The pre filter is used to narrow the records to be searched by the duplicate scan service
- * The filters get applied sequentially one after another.
- * If the number of results equal or lower as the configured threshold and greater than zero, the current filter combination gets returned.
- * If no more filters are available and the number of results still exceed the threshold, null gets returned.
- * If the number of results reach zero  while aplying filters, null gets returned
- * The reason is, that if a huge count of records were to be used, the time to search for duplicates would be substantially longer.
- * If the prefilters to not have the desired effect it is advised to modify the configured filter conditions
- *
- *  @param {String} pTargetEntity Entity which has been configured
- *  @param {String[[]]} pFilterCountCharactersToUseRay Array of Arrays containing the configuration of the filters.
- * The structure is as follows: [INDEX_FILTER_CONDITION, INDEX_COUNT_CHARS_TO_USE, INDEX_MAX_RESULTS_THRESHOLD]
- *  @param {String[[]]} pFilterFieldValueRays Array of Arrays containing the name of a used field and its value.
- * Use "DuplicateScannerUtils.BuildEntityFieldNameValueRays". The fieldnames and values have to be in the same order
- *  @returns {String} Null if the records count wasnt inside the threshold, the used combined filter to achieve a successfull prefiltering
- */
-_DuplicateScannerUtils._applyPreFilter = function(pTargetEntity, pFilterCountCharactersToUseRay, pFilterFieldValueRays)
-{
-//    logging.log("#pFilterFieldValueRays#" + JSON.stringify(pFilterFieldValueRays))
-    var combinedFilter = {};
-
-    for (i = 0; i < pFilterCountCharactersToUseRay.length; i++) 
-    {
-        var filter = pFilterCountCharactersToUseRay[i][INDEX_FILTER_CONDITION];
-//        logging.log("#1#filter>>" + filter)
-        let countCharsOfValueToUse = pFilterCountCharactersToUseRay[i][INDEX_COUNT_CHARS_TO_USE];
-        let maxResultsThreshold = pFilterCountCharactersToUseRay[i][INDEX_MAX_RESULTS_THRESHOLD];
-        
-        if(filter == null || filter == "")
-            continue;
-
-        filter = JSON.parse(filter);
-
-        let filterValuesObject = {};
-        for (a = 0; a < pFilterFieldValueRays.length; a++)
-        {
-            filterValuesObject[pFilterFieldValueRays[a][0]] = pFilterFieldValueRays[a][1];
-        }
-
-        //logging.log("filterValuesObject zum füllen des jsons -> " + JSON.stringify(filterValuesObject));
-        /*
-         * Insert the values into the current filter. Has to be here so that only the new filter
-         * and therefore the combinedFilter incrementally gets filled and not always everything multiple times.
-         */
-        //logging.log("1 ###### filter zum befüllen mit werten-> " + JSON.stringify(filter));
-        filter.filter.childs = _DuplicateScannerUtils._insertValuesInFilterTemplate(filter.filter.childs, filterValuesObject, countCharsOfValueToUse);
-        //logging.log("2 ###### gefüllter filter prefilter index-> " + JSON.stringify(filter));
-
-        if(i == 0)
-            combinedFilter = filter.filter;
-        else
-        {
-            //logging.log("3 ###### aktueller combinedFilter -> " + JSON.stringify(combinedFilter));
-            //logging.log("4 ###### gefüllter filter -> " + JSON.stringify(filter));
-            //Extend the current combined filter with the next filter condition to further refine the results
-            //It seems to always contain one child element at the root
-            //combinedFilter.childs.push(filter.filter.childs);
-            let newCombinedFilterChilds = combinedFilter.childs.concat(filter.filter.childs);
-            combinedFilter.childs = newCombinedFilterChilds;
-        }
-
-        //logging.log("5 ###### combinedFilter + gefüllter filter vor indexsuche-> " + JSON.stringify(combinedFilter));
-
-        filter.filter = combinedFilter;
-        //logging.log("6 ###### completeFilter -> " + JSON.stringify(filter));
-
-        //Workaround to load the smallest possible resultset because only the TOTALHITS are relevant at this time
-        //Only load "indexsearch.FIELD_ID" and a resultSet size of 1
-        let searchResult = _DuplicateScannerUtils._callIndexSearch(pTargetEntity, JSON.stringify(filter), [],
-            [], 1);//todo use again after this has been fixed!! insert the local id after fix
-        //logging.log("searchResults hits length -> " + searchResult[indexsearch.HITS].length);
-
-        //        if(searchResult[indexsearch.TOTALHITS] < 80)//todo entfernen?!
-        //        {
-        //            for (let i = 0; i < searchResult[indexsearch.HITS].length; i++)
-        //            {
-        //                logging.log("Treffer Nr -> " + i);
-        //                //searchResults hits 0 -> {#ADITO_SEARCH_ID=1868bd3a-05af-4b7f-a633-e3aec50ac45c, _index_group_=Person, #ADITO_SEARCH_TYPE=Person, firstname_value=Peter, _local_id_=1868bd3a-05af-4b7f-a633-e3aec50ac45c}
-        //                let localId = searchResult[indexsearch.HITS][i]["_local_id_"];
-        //                let firstname = searchResult[indexsearch.HITS][i]["firstname_value"];
-        //                let indexGroup = searchResult[indexsearch.HITS][i]["_index_group_"];
-        //                logging.log("localId -> " + localId);
-        //                logging.log("firstname -> " + firstname);
-        //                logging.log("indexGroup -> " + indexGroup);
-        //            }
-        //        }
-
-        let totalHits = searchResult[indexsearch.TOTALHITS]
-
-        //logging.log("totalHits -> " + totalHits);
-
-        if(totalHits > maxResultsThreshold)
-        {
-            //logging.log("zu viele rows gefundenn nächsten Filter anwenden -> totalHits:" + totalHits + " maxResultsThreshold:" + maxResultsThreshold);
-            //Found more rows than allowed by the threshold, run next filter to narrow the results
-            continue;
-        }
-        else if(totalHits <= 0)
-        {
-            return null;
-        }
-        else
-        {
-            //we're in the treshold, return the valid filter. The filter gets used lateron.
-            return JSON.stringify(filter);
-        }
-    }
-    //logging.log("zu viele rows und keine filter mehr -> ");
-    return null;
-}
-
 /*
  * Runs the indexsearch based on the given parameters.
- * If the "pEntityFieldValueRays" is empty, only the prefilters get applied as pattern.
- * if not, the prefilters will be applies as pattern and the contents of "pEntityFieldValueRays" get applies as filter.
- *
+ * If the "pEntityFieldValueRays" is empty, no search will be executed.
+ * 
  * @param {String} pTargetEntity Entity which has been configured
- * @param {String} pPreFilterJson The prefilters
- * @param {String[[]]} pEntityFieldValueRays Array of Arrays containing the name of a used field and its value.
- * Use "DuplicateScannerUtils.BuildEntityFieldNameValueRays". The fieldnames and values have to be in the same order. NotNull!->Empty Array
+ * @param {String} pIndexPatternWithValues The pattern used to search. Has to contain the values already.
  * @param {String} pResultFields The result field config. Use "DuplicateScannerUtils.LoadResultFields"
  * @param {String} pResultSetRows todo
- * @returns {[["key", "value"]]} Array of Key-Value-Pairs based on the configured pResultFields
+ * @returns {[["key", "value"]] || null} Array of Key-Value-Pairs based on the configured pResultFields, if no pattern exists null
  */
-_DuplicateScannerUtils._callIndexSearch = function(pTargetEntity, pPreFilterJson, pEntityFieldValueRays, pResultFields, pResultSetRows)
+_DuplicateScannerUtils._callIndexSearch = function(pTargetEntity, pIndexPatternWithValues, pResultFields, pResultSetRows)
 {
-    let indexPattern = null;
-    let filterPattern = null;
-    
-    //The pPreFilterJson is never null because it always contains at least the default ignore record filter
-    indexPattern = indexsearch.buildQueryFromSearchCondition(pPreFilterJson);
-
-    indexPattern = indexPattern.replace(null, "");//todo remove if api has been fixed
-
-    let filterPatternConfig = _DuplicateScannerUtils._buildFilterPatternConfig(pEntityFieldValueRays, pTargetEntity);
-
-    if(filterPatternConfig != null)
-        filterPattern = indexsearch.buildPatternString(filterPatternConfig);
-
     //The indexPattern can't be null because it is required to run the search.
-    if(indexPattern == null)
+    if(pIndexPatternWithValues == null || pIndexPatternWithValues == "")
         return null;
     
     let indexQuery = indexsearch.createIndexQuery()
-                                .setPattern(indexPattern)
+                                .setPattern(pIndexPatternWithValues)
                                 .setEntities([pTargetEntity])
                                 //.addSearchFields("Person_entity.FIRSTNAME", "Person_entity.LASTNAME", "Person_entity.CONTACTID")
                                 //.setRows(pResultSetRows);
     indexQuery = _DuplicateScannerUtils._setResultFields(indexQuery, pResultFields);
 
-    if(filterPattern != null)
-        indexQuery = indexQuery.addFilter(filterPattern);
-    
-    logging.log("indexQuery: PATTERN + FILTERS -> " + indexQuery.getPattern() + " " + indexQuery.getFilters());
-
     return indexsearch.searchIndex(indexQuery);
 }
 
@@ -1332,18 +1170,15 @@ _DuplicateScannerUtils._buildDeleteCachedUnrelatedDuplicateQuery = function(pSou
 }
 
 /*
- * Creates a filter JSON which excludes the field and it's value using the operator "NOT_EQUAL"
+ * Creates a pattern which excludes the field and it's value
  *
  * @param {String} pRecordIdFieldToIgnore Field to be ignored
  * @param {String} pRecordIdValueToIgnore The fields value
- * @param {String} pTargetEntity Entity which has been configured
- * @returns {String[]} Array where 0 = filter, 1 = null(INDEX_COUNT_CHARS_TO_USE), 2 = null(INDEX_MAX_RESULTS_THRESHOLD)
+ * @returns {String} Pattern which excludes the gived field in combination with the value
  */
-_DuplicateScannerUtils._getIgnoreRecordFilter = function(pRecordIdFieldToIgnore, pRecordIdValueToIgnore, pTargetEntity)
+_DuplicateScannerUtils._getIgnoreSourceRecordPattern = function(pRecordIdFieldToIgnore, pRecordIdValueToIgnore)
 {
-    let ignoreFilterJson = JSON.stringify({"entity":pTargetEntity,"filter":{"type":"group","operator":"AND","childs":[{"type":"row","name":pRecordIdFieldToIgnore,"operator":"NOT_EQUAL","value":pRecordIdValueToIgnore,"key":"","contenttype":"TEXT"}]}});
-
-    return [ignoreFilterJson, null, null];
+    return "(+(-" + pRecordIdFieldToIgnore.toLowerCase() + "_value:(" + pRecordIdValueToIgnore + ")) ";
 }
 
 _DuplicateScannerUtils._buildUpdateContactIdStatements = function(pTableInfos, pSourceContactId, pTargetContactId)
-- 
GitLab