-
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,
+}