diff --git a/src/app/components/search/search.html b/src/app/components/search/search.html index dbdf54be..b4abd50e 100644 --- a/src/app/components/search/search.html +++ b/src/app/components/search/search.html @@ -33,7 +33,7 @@

-
diff --git a/src/app/main/index.js b/src/app/main/index.js index 484dcb1b..89398621 100644 --- a/src/app/main/index.js +++ b/src/app/main/index.js @@ -145,75 +145,6 @@ angular } }); - $scope.$watch('search.query', function(q) { - $scope.search.results = assignSearchRelevance(projectService.search(q)); - }); - - function assignSearchRelevance(results){ - if($scope.search.query === "") - return results; - let criteriaArr = { - "name": 10, - "tags": 5, - "description": 3, - "raw_code": 2, - "columns": 1 - }; - _.each(results, function(result){ - result.overallWeight = 0; - _.each(Object.keys(criteriaArr), function(criteria){ - if(result.model[criteria] != undefined){ - let count = 0; - let body = result.model[criteria]; - let query = ($scope.search.query).toLowerCase(); - if(criteria === "columns"){ - _.each(body, function(column){ - // there a spark bug where columns are missign from the catalog. That - // needs to be fixed outside of docs but this if != null check will - // allow docs to continue to function now and also when the bug is - // fixed. - // relevant issue: https://github.com/dbt-labs/dbt-spark/issues/295 - if (column.name) { - let columnName = column.name.toLowerCase(); - let index = 0; - while(index != -1){ - index = columnName.indexOf(query, index); - if (index != -1) { - count++; index++; - } - } - } - }); - } - else if(criteria === "tags"){ - _.each(body, function(tag){ - let tagName = tag.toLowerCase(); - let index = 0; - while(index != -1){ - index = tagName.indexOf(query, index); - if (index != -1) { - count++; index++; - } - } - }); - } - else{ - body = body.toLowerCase(); - let index = 0; - while(index != -1){ - index = body.indexOf(query, index); - if(index != -1){ - count++; index++; - } - } - } - result.overallWeight += (count * criteriaArr[criteria]); - } - }); - }); - return results; - } - /* INITIALIZE THE APPLICATION: 1. Set the selected model (if there is one) via the url diff --git a/src/app/services/proejct_service_utils.test.js b/src/app/services/proejct_service_utils.test.js new file mode 100644 index 00000000..80e9a9c6 --- /dev/null +++ b/src/app/services/proejct_service_utils.test.js @@ -0,0 +1,42 @@ +const proj_utils = require('./project_service_utils') + +describe('Project Service Tests', () => { + describe('assignSearchRelevance', () => { + let results; + + beforeEach(() => { + results = [ + { model: { name: 'dm_test', tags: ["dm", "test", "test model"], columns: {"id": {"name": "id"}}, raw_code: "SELECT test from test" }, overallWeight: 0, overallNameWeight: 0 }, + { model: { name: 'ft_test_person', tags: ["test", "ft", "person"], columns: {"id": {"name": "id"}}, raw_code: "SELECT test, test from test" }, overallWeight: 0, overallNameWeight: 0 }, + { model: { name: 'test_event', tags: ["test", "event"], columns: {"test": {"name": "test"}} , raw_code: "SELECT id from abc" }, overallWeight: 0, overallNameWeight: 0 }, + { model: { name: 'test_log', tags: ["test", "log"], overallWeight: 0, overallNameWeight: 0 }}, + { model: { name: 'test', tags: [], columns: {} }, overallWeight: 0, overallNameWeight: 0 }, + { model: { name: 'n/a', tags: [], columns: {} }, overallWeight: 0, overallNameWeight: 0 }, + ]; + }); + + it('should prioritize exact name matches', () => { + proj_utils.assignSearchRelevance(results, 'test'); + expect(results[0].model.name).toBe('test'); + expect(results[0].overallNameWeight).toBe(100); + expect(results[0].overallWeight).toBe(100); + + expect(results[1].model.name).toBe('test_event'); + expect(results[1].overallNameWeight).toBe(50); + expect(results[1].overallWeight).toBe(56); + + expect(results[2].model.name).toBe('test_log'); + expect(results[2].overallNameWeight).toBe(50); + expect(results[2].overallWeight).toBe(55); + + expect(results[3].model.name).toBe('dm_test'); + expect(results[3].overallNameWeight).toBe(30); + expect(results[3].overallWeight).toBe(44); + + expect(results[4].model.name).toBe('ft_test_person'); + expect(results[4].overallNameWeight).toBe(10); + expect(results[4].overallWeight).toBe(21); + }); + + }); +}); diff --git a/src/app/services/project_service.js b/src/app/services/project_service.js index 7e157ae4..876aa900 100644 --- a/src/app/services/project_service.js +++ b/src/app/services/project_service.js @@ -3,6 +3,7 @@ const angular = require('angular'); const $ = require('jquery'); const _ = require('lodash'); const { getQuoteChar } = require('./compat'); +const { assignSearchRelevance } = require('./project_service_utils'); import merge from 'deepmerge'; @@ -357,7 +358,7 @@ angular } service.search = function(q) { - if (q.length == 0) { + if (q.length === 0) { return _.map(service.project.searchable, function(model) { return { model: model, @@ -376,7 +377,7 @@ angular }); } }); - return res; + return assignSearchRelevance(res, q); } function clean_project_macros(macros, adapter) { diff --git a/src/app/services/project_service_utils.js b/src/app/services/project_service_utils.js new file mode 100644 index 00000000..2bd9db06 --- /dev/null +++ b/src/app/services/project_service_utils.js @@ -0,0 +1,89 @@ +const _ = require('lodash'); + + +function assignSearchRelevance(results, q) { + if(q === "") { + return results; + } + let criteriaArr = { + "name": 10, + "tags": 5, + "description": 3, + "raw_code": 2, + "columns": 1 + }; + + _.each(results, function(result){ + result.overallWeight = 0; + result.overallNameWeight = 0; + _.each(Object.keys(criteriaArr), function(criteria){ + if(result.model[criteria] !== undefined){ + let count = 0; + let body = result.model[criteria]; + let query = (q).toLowerCase(); + if(criteria === "columns"){ + _.each(body, function(column){ + // there a spark bug where columns are missign from the catalog. That + // needs to be fixed outside of docs but this if != null check will + // allow docs to continue to function now and also when the bug is + // fixed. + // relevant issue: https://github.com/dbt-labs/dbt-spark/issues/295 + if (column.name) { + let columnName = column.name.toLowerCase(); + let index = 0; + while(index !== -1){ + index = columnName.indexOf(query, index); + if (index !== -1) { + count++; index++; + } + } + } + }); + } + else if(criteria === "name"){ + const calculateNameMatchWeight = (body, query) => { + if (body === query) return 10; + const lowerBody = body.toLowerCase(); + if (lowerBody.startsWith(query)) return 5; + if (lowerBody.endsWith(query)) return 3; + if (lowerBody.includes(query)) return 1; + return 0; + }; + + count += calculateNameMatchWeight(body, (q).toLowerCase()); + result.overallNameWeight += (count * criteriaArr[criteria]); + + } + else if(criteria === "tags"){ + _.each(body, function(tag){ + let tagName = tag.toLowerCase(); + let index = 0; + while(index != -1){ + index = tagName.indexOf(query, index); + if (index != -1) { + count++; index++; + } + } + }); + } + else{ + body = body.toLowerCase(); + let index = 0; + while(index != -1){ + index = body.indexOf(query, index); + if(index != -1){ + count++; index++; + } + } + } + result.overallWeight += (count * criteriaArr[criteria]); + } + }); + }); + results.sort((a, b) => b.overallNameWeight - a.overallNameWeight || b.overallWeight - a.overallWeight); + return results + } + +module.exports = { + assignSearchRelevance, +}