[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.
This commit is contained in:
shale 2015-07-16 13:08:05 -07:00
parent bc2072b8c6
commit 80e0bd875a
6 changed files with 105 additions and 25 deletions

View File

@ -15,7 +15,7 @@
{
"key": "SearchController",
"implementation": "controllers/SearchController.js",
"depends": [ "$scope", "searchService" ]
"depends": [ "$scope", "searchService", "objectService" ]
},
{
"key": "SearchbarController",

View File

@ -43,6 +43,6 @@
</div>
<mct-representation key="'grid-item'"
ng-repeat="result in results"
mct-object="result">
mct-object="result.object">
</mct-representation>
</div>

View File

@ -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;
});
}

View File

@ -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;

View File

@ -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;
});
}

View File

@ -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;
});
}