From 80e0bd875a89007c15617c33a74457363ed1f9f7 Mon Sep 17 00:00:00 2001 From: shale Date: Thu, 16 Jul 2015 13:08:05 -0700 Subject: [PATCH] [Search] Aggregator merges results The search aggregator now merges search results from different providers better. It removed duplicate results, and orders the list of results from highest to lowest score. --- platform/features/search/bundle.json | 2 +- .../features/search/res/templates/search.html | 2 +- .../features/search/src/SearchAggregator.js | 43 +++++++++++++++++-- .../src/controllers/SearchController.js | 30 ++++++++++--- .../providers/ElasticsearchSearchProvider.js | 24 ++++++++--- .../src/providers/EverythingSearchProvider.js | 29 +++++++++---- 6 files changed, 105 insertions(+), 25 deletions(-) diff --git a/platform/features/search/bundle.json b/platform/features/search/bundle.json index 095abaab28..0ba248ebc0 100644 --- a/platform/features/search/bundle.json +++ b/platform/features/search/bundle.json @@ -15,7 +15,7 @@ { "key": "SearchController", "implementation": "controllers/SearchController.js", - "depends": [ "$scope", "searchService" ] + "depends": [ "$scope", "searchService", "objectService" ] }, { "key": "SearchbarController", diff --git a/platform/features/search/res/templates/search.html b/platform/features/search/res/templates/search.html index f1e7a8fb5d..b44005f163 100644 --- a/platform/features/search/res/templates/search.html +++ b/platform/features/search/res/templates/search.html @@ -43,6 +43,6 @@ + mct-object="result.object"> \ No newline at end of file diff --git a/platform/features/search/src/SearchAggregator.js b/platform/features/search/src/SearchAggregator.js index 312416d184..d509eeee16 100644 --- a/platform/features/search/src/SearchAggregator.js +++ b/platform/features/search/src/SearchAggregator.js @@ -50,12 +50,48 @@ define( } } + // Remove extra objects that have the same ID + function filterRepeats(results) { + var ids = []; + + for (var i = 0; i < results.length; i += 1) { + //if (ids.includes(results[i].id)) { + if (ids.indexOf(results[i].id) !== -1) { + // If this result's ID is already there, remove the object + results.splice(i, 1); + // Reduce loop index because we shortened the array + i -= 1; + } else { + // Otherwise add the ID to the list of the ones we have seen + ids.push(results[i].id); + } + } + + return results; + } + + // Order the objects from highest to lowest score in the array + function orderByScore(results) { + + results = results.sort(function (a, b) { + if (a.score > b.score) { + return -1; + } else if (b.score < a.score) { + return 1; + } else { + return 0; + } + }); + + return results; + } + // Calls the searches of each of the providers, then // merges the results lists so that there are not redundant // results function mergeResults(inputID) { var resultsPromises = [], - mergedResults = []; + mergedResults; for (var i = 0; i < providers.length; i += 1) { resultsPromises.push(providers[i].query(inputID)); @@ -63,9 +99,10 @@ define( mergedResults = getPromisedResults(resultsPromises, 0, []); - //return mergedResults; return mergedResults.then(function (c) { - //console.log('returning ', c); + // Get rid of the repeated objects and put in correct order + c = filterRepeats(c); + c = orderByScore(c); return c; }); } diff --git a/platform/features/search/src/controllers/SearchController.js b/platform/features/search/src/controllers/SearchController.js index 423e6253bb..adb32744b9 100644 --- a/platform/features/search/src/controllers/SearchController.js +++ b/platform/features/search/src/controllers/SearchController.js @@ -27,15 +27,22 @@ define(function () { "use strict"; - function SearchController($scope, searchService) { + function SearchController($scope, searchService, objectService) { + + function getResults(inputID) { + + // Later, the search result format will be different + // Will need to compile search result list (for this + // result page) here, using pseudo linkedlist searchResult + + searchService.query(inputID).then(function (c) { + $scope.results = c; + }); + } return { // Search the database using the user input of id "searchinput" - search: function (inputID) { - searchService.query(inputID).then(function (c) { - $scope.results = c; - }); - }, + search: getResults, // Check to see if there are any search results to display. areResults: function () { @@ -44,7 +51,16 @@ define(function () { } else { return false; } - } + }/*, + + // Get a domain object from its ID + getObjectByID: function (id) { + return objectService.getObjects([id]).then(function (objects) { + var obj = objects[id]; + console.log('get object', obj); + return obj; + }); + }*/ }; } return SearchController; diff --git a/platform/features/search/src/providers/ElasticsearchSearchProvider.js b/platform/features/search/src/providers/ElasticsearchSearchProvider.js index fefbd64be1..f039e2bbff 100644 --- a/platform/features/search/src/providers/ElasticsearchSearchProvider.js +++ b/platform/features/search/src/providers/ElasticsearchSearchProvider.js @@ -92,7 +92,7 @@ define( searchTerm = 'name:' + searchTerm; } - console.log('search term ', searchTerm); + //console.log('search term ', searchTerm); return searchTerm; } @@ -102,6 +102,8 @@ define( var results = rawResults.data.hits.hits, resultsLength = results.length, ids = [], + scores = {}, + searchResults = [], i; if (rawResults.data.hits.total > resultsLength) { @@ -114,24 +116,36 @@ define( ids.push(results[i][ID]); } + // Get the result objects' scores + for (i = 0; i < resultsLength; i += 1) { + //scores.push(results[i][SCORE]); + scores[ ids[i] ] = results[i][SCORE]; + } + // Get the domain objects from their IDs return objectService.getObjects(ids).then(function (objects) { - var output = [], - id, + var id, j; + // Filter by search term for (j = 0; j < resultsLength; j += 1) { id = ids[j]; // Include any item except folders if (objects[id].getModel) { if (objects[id].getModel().type !== "folder") { - output.push(objects[id]); + // Format the results as searchResult objects + searchResults.push({ + id: id, + object: objects[id], + score: scores[id] + }); } } } - return output; + //console.log('searchResults (in ES provider)', searchResults); + return searchResults; }); } diff --git a/platform/features/search/src/providers/EverythingSearchProvider.js b/platform/features/search/src/providers/EverythingSearchProvider.js index 2b204c3f17..927e676055 100644 --- a/platform/features/search/src/providers/EverythingSearchProvider.js +++ b/platform/features/search/src/providers/EverythingSearchProvider.js @@ -67,8 +67,20 @@ define( // Aquire My Items (root folder) return objectService.getObjects(['mine']).then(function (objects) { // Get all of its descendents - return itemsHelper([objects.mine], 0).then(function (c) { - return c; + return itemsHelper([objects.mine], 0).then(function (items) { + // Turn them into searchResult objects (object, id, and score) + var searchResultItems = []; + + for (var i = 0; i < items.length; i += 1) { + searchResultItems.push({ + id: items[i].getId(), + object: items[i], + score: 1 // TODO: Find how to score these properly + }); + } + + //console.log('searchResultItems (in Everything)', searchResultItems); + return searchResultItems; }); }); } @@ -112,10 +124,10 @@ define( term = term.toLocaleLowerCase(); // Get items list - return getItems().then(function (items) { + return getItems().then(function (searchResultItems) { // Keep track of the number of results to display - if (items.length < maxResults) { - resultsLength = items.length; + if (searchResultItems.length < maxResults) { + resultsLength = searchResultItems.length; } else { resultsLength = maxResults; } @@ -123,17 +135,18 @@ define( // Then filter through the items list for (i = 0; i < resultsLength; i += 1) { // Prevent errors from getModel not being defined - if (items[i].getModel) { - itemModel = items[i].getModel(); + if (searchResultItems[i].object.getModel) { + itemModel = searchResultItems[i].object.getModel(); itemName = itemModel.name.toLocaleLowerCase(); // Include any matching items, except folders if (itemName.includes(term) && itemModel.type !== "folder") { - searchResults.push(items[i]); + searchResults.push(searchResultItems[i]); } } } + //console.log('filtered searchResults (in Everything)', searchResults); return searchResults; }); }