mirror of
https://github.com/nasa/openmct.git
synced 2025-02-21 01:42:31 +00:00
[Search] Partial loading
Changed the providers to return only the first search result. Each searchResult object has a function next() which returns the next search result. This allows the search aggregator to load more results without making a whole new search query. (Still requuires some cleaning up.)
This commit is contained in:
parent
c0c0371451
commit
5520037908
@ -41,6 +41,8 @@ define(
|
||||
* aggregated
|
||||
*/
|
||||
function SearchAggregator(providers) {
|
||||
var compiledResults = [];
|
||||
|
||||
|
||||
// Determines if a searchResult object is a valid type
|
||||
// to be displayed as a final result. Is passed to the
|
||||
@ -82,15 +84,15 @@ define(
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
console.log('score', results[i].score, 'for', results[i].object.getModel().name);
|
||||
}
|
||||
*/
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
// 'Loop' over the promises using recursion so that the promises are fufilled by the
|
||||
// time that we are done
|
||||
function getPromisedResults(resultsPromises, promiseIndex, finalResults) {
|
||||
if (promiseIndex >= resultsPromises.length) {
|
||||
return finalResults;
|
||||
@ -102,6 +104,60 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
function getPromisedItems(promises, index, fufilledPromises) {
|
||||
if (index >= promises.length) {
|
||||
return fufilledPromises;
|
||||
} else {
|
||||
return promises[index].then(function (results) {
|
||||
fufilledPromises = fufilledPromises.concat(results);
|
||||
return getPromisedItems(promises, index + 1, fufilledPromises);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add more results to compiledResults
|
||||
// (As if the user presed 'load more results')
|
||||
function loadMore() {
|
||||
|
||||
}
|
||||
|
||||
// Add x number of items to the compiledResults as the initial number of results that
|
||||
// we display
|
||||
function initialLoad(firstPromises) {
|
||||
return getPromisedItems(firstPromises, 0, []).then(function (current) {
|
||||
// Push the firsts onto the compiledResults
|
||||
for (var i = 0; i < current.length; i++) {
|
||||
if (current[i]) {
|
||||
compiledResults.push(current[i]);
|
||||
}
|
||||
}
|
||||
// Look for more results n times and add them to compiledResults
|
||||
var outOfResults = [];
|
||||
for (var i = 0; i < DEFAULT_MAX_RESULTS; i++) {
|
||||
// If all of the providers are returning undefined, there are
|
||||
// no more results to load
|
||||
if (current.every(function (c) {
|
||||
return c === undefined;
|
||||
})) {
|
||||
break;
|
||||
}
|
||||
|
||||
// For each provider, load the next result and add it to compiledResults
|
||||
for (var j = 0; j < current.length; j++) {
|
||||
if (current[j]) {
|
||||
var nextResult = current[j].next();
|
||||
if (nextResult) {
|
||||
compiledResults.push(nextResult);
|
||||
}
|
||||
current[j] = nextResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return compiledResults;
|
||||
});
|
||||
}
|
||||
|
||||
// Recieves results in the format of a serachResult object. It
|
||||
// has the members id, object, and score. It has a function
|
||||
// next() which returns the next highest score search result
|
||||
@ -111,11 +167,15 @@ define(
|
||||
// merges the results lists so that there are not redundant
|
||||
// results
|
||||
function mergeResults(inputID) {
|
||||
var resultsPromises = [];
|
||||
//var resultsPromises = [];
|
||||
|
||||
// Get result list promises
|
||||
// The first result from each provider. Each should have a next() function.
|
||||
var firstPromises = [];
|
||||
|
||||
// Get the initial result promises
|
||||
for (var i = 0; i < providers.length; i += 1) {
|
||||
resultsPromises.push(
|
||||
//resultsPromises.push(
|
||||
firstPromises.push(
|
||||
providers[i].query(
|
||||
inputID, validType, DEFAULT_MAX_RESULTS, DEFUALT_TIMEOUT
|
||||
)
|
||||
@ -123,12 +183,20 @@ define(
|
||||
}
|
||||
|
||||
// Wait for the promises to fufill
|
||||
return initialLoad(firstPromises).then(function (c) {
|
||||
// Get rid of the repeated objects and put in correct order
|
||||
c = filterRepeats(c);
|
||||
c = orderByScore(c);
|
||||
return c;
|
||||
});
|
||||
/*
|
||||
return getPromisedResults(resultsPromises, 0, []).then(function (c) {
|
||||
// Get rid of the repeated objects and put in correct order
|
||||
c = filterRepeats(c);
|
||||
c = orderByScore(c);
|
||||
return c;
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -48,6 +48,8 @@ define(
|
||||
*/
|
||||
function ElasticsearchSearchProvider($http, objectService, ROOT) {
|
||||
// TODO: Fix the above docstring
|
||||
var latestSearchResults = [],
|
||||
currentResultIndex = 0;
|
||||
|
||||
// Check to see if the input has any special options
|
||||
function isDefaultFormat(searchTerm) {
|
||||
@ -67,7 +69,6 @@ define(
|
||||
|
||||
return searchTerm.split(' ').map(function (s) {
|
||||
if (s.includes('"')) {
|
||||
console.log('true');
|
||||
return s;
|
||||
} else {
|
||||
return s + '~' + editDistance;
|
||||
@ -97,6 +98,28 @@ define(
|
||||
return searchTerm;
|
||||
}
|
||||
|
||||
// Get the next search result
|
||||
function next() {
|
||||
// Because elasticsearch only returns matching things, we just
|
||||
// need to step through the array
|
||||
|
||||
currentResultIndex++;
|
||||
|
||||
if (currentResultIndex > latestSearchResults.length) {
|
||||
// If we go past the end of the array, we return undefined
|
||||
return undefined;
|
||||
} else {
|
||||
return latestSearchResults[currentResultIndex];
|
||||
}
|
||||
}
|
||||
|
||||
function first() {
|
||||
// Since next() immeditely does 'i++', start before the start of the array
|
||||
currentResultIndex = -1;
|
||||
var n = next();
|
||||
return n;
|
||||
}
|
||||
|
||||
// Processes results from the format that elasticsearch returns to
|
||||
// a list of objects in the format that mct-representation can use
|
||||
function processResults(rawResults, validType) {
|
||||
@ -104,8 +127,7 @@ define(
|
||||
resultsLength = results.length,
|
||||
ids = [],
|
||||
scores = {},
|
||||
searchResults = [],
|
||||
i;
|
||||
searchResults = [];
|
||||
|
||||
if (rawResults.data.hits.total > resultsLength) {
|
||||
// TODO: Somehow communicate this to the user
|
||||
@ -113,24 +135,21 @@ define(
|
||||
}
|
||||
|
||||
// Get the result objects' IDs
|
||||
for (i = 0; i < resultsLength; i += 1) {
|
||||
for (var i = 0; i < resultsLength; i += 1) {
|
||||
ids.push(results[i][ID]);
|
||||
}
|
||||
|
||||
// Get the result objects' scores
|
||||
for (i = 0; i < resultsLength; i += 1) {
|
||||
//scores.push(results[i][SCORE]);
|
||||
for (var i = 0; i < resultsLength; i += 1) {
|
||||
scores[ ids[i] ] = results[i][SCORE];
|
||||
}
|
||||
|
||||
// Get the domain objects from their IDs
|
||||
return objectService.getObjects(ids).then(function (objects) {
|
||||
var id,
|
||||
j;
|
||||
|
||||
// Filter by search term
|
||||
for (j = 0; j < resultsLength; j += 1) {
|
||||
id = ids[j];
|
||||
for (var j = 0; j < resultsLength; j += 1) {
|
||||
var id = ids[j];
|
||||
|
||||
// Include items we can get models for
|
||||
if (objects[id].getModel) {
|
||||
@ -140,13 +159,15 @@ define(
|
||||
searchResults.push({
|
||||
id: id,
|
||||
object: objects[id],
|
||||
score: scores[id]
|
||||
score: scores[id],
|
||||
next: next
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//console.log('searchResults (in ES provider)', searchResults);
|
||||
console.log('setting latest search results with', searchResults);
|
||||
latestSearchResults = searchResults;
|
||||
return searchResults;
|
||||
});
|
||||
}
|
||||
@ -191,8 +212,7 @@ define(
|
||||
searchTerm = processSearchTerm(searchTerm);
|
||||
|
||||
// Create the query to elasticsearch
|
||||
esQuery = ROOT + "/_search/?q=" + searchTerm +
|
||||
"&size=" + maxResults;
|
||||
esQuery = ROOT + "/_search/?q=" + searchTerm + "&size=" + maxResults;
|
||||
if (timeout) {
|
||||
esQuery += "&timeout=" + timeout;
|
||||
}
|
||||
@ -203,7 +223,11 @@ define(
|
||||
url: esQuery
|
||||
}).then(function (rawResults) {
|
||||
// ...then process the data
|
||||
return processResults(rawResults, validType);
|
||||
processResults(rawResults, validType);
|
||||
// and return the first result
|
||||
var f = first();
|
||||
// console.log('ES return', f);
|
||||
return f;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,12 @@ define(
|
||||
* more easy creation of web workers.
|
||||
*/
|
||||
function GenericSearchProvider($rootScope, objectService, workerService) {
|
||||
var latestItems = [],
|
||||
currentResultIndex = 0,
|
||||
currentSeachInput = '',
|
||||
curentSearchTerms = [],
|
||||
validType = function () {return true;};
|
||||
|
||||
/*
|
||||
var worker = workerService.run('genericSearchWorker'),
|
||||
lastestItems;
|
||||
@ -77,21 +83,19 @@ define(
|
||||
});
|
||||
//counter += 1;
|
||||
}
|
||||
*/
|
||||
|
||||
function handleResponse(event) {
|
||||
latest = event.data;
|
||||
$rootScope.$apply();
|
||||
//requestNext();
|
||||
}
|
||||
*/
|
||||
|
||||
// Recursive helper function for getItems()
|
||||
function itemsHelper(children, i) {
|
||||
var date = new Date;
|
||||
if (stopTime && date.getTime() >= stopTime) {
|
||||
// This indexing of items has timed out
|
||||
console.log('timed out');
|
||||
console.log('returning', children);
|
||||
return children;
|
||||
} else if (i >= children.length) {
|
||||
// Done!
|
||||
@ -131,7 +135,8 @@ define(
|
||||
searchResultItems.push({
|
||||
id: items[i].getId(),
|
||||
object: items[i],
|
||||
score: 0 // Assign actual score when filtering for term
|
||||
score: 0, // Assign actual score when filtering for term
|
||||
next: next
|
||||
});
|
||||
}
|
||||
|
||||
@ -141,8 +146,6 @@ define(
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Process the search input. Makes an array of search terms
|
||||
// by splitting up the input at spaces.
|
||||
function process(input) {
|
||||
@ -179,8 +182,9 @@ define(
|
||||
return score * weight;
|
||||
}
|
||||
|
||||
/*
|
||||
// Filter through a list of searchResults based on a search term
|
||||
function filterResults(results, originalInput, resultsLength, validType) {
|
||||
function filterResults(results, originalInput, resultsLength) {
|
||||
var terms,
|
||||
searchResults = [],
|
||||
itemModel;
|
||||
@ -202,6 +206,51 @@ define(
|
||||
|
||||
return searchResults;
|
||||
}
|
||||
*/
|
||||
|
||||
// Get the next item from latestItems
|
||||
function next() {
|
||||
var i = currentResultIndex,
|
||||
gotNext = false,
|
||||
nextResult;
|
||||
|
||||
// Look for the next item that qualifies as a search result
|
||||
while (!gotNext) {
|
||||
i++;
|
||||
if (i > latestItems.length) {
|
||||
// If we go past the end of the array, we return undefined
|
||||
gotNext = true;
|
||||
nextResult = undefined;
|
||||
//currentResultIndex = i;
|
||||
} else if (latestItems[i]) {
|
||||
// Prevent errors from getModel not being defined
|
||||
if (latestItems[i].object.getModel) {
|
||||
latestItems[i].score = score(latestItems[i], curentSearchTerms, currentSeachInput);
|
||||
|
||||
// Include any items that match the terms and are of valid type
|
||||
if (latestItems[i].score > 0 && validType(latestItems[i].object.getModel())) {
|
||||
// Add the result to the result list
|
||||
nextResult = latestItems[i];
|
||||
//nextResult.next = next;
|
||||
currentResultIndex = i;
|
||||
gotNext = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nextResult;
|
||||
}
|
||||
|
||||
// Get the first result in latestItems that is a search result
|
||||
function first(input) {
|
||||
// Set up the global variables
|
||||
currentSeachInput = input;
|
||||
curentSearchTerms = process(input);
|
||||
// Since next() immeditely does 'i++', start before the start of the array
|
||||
currentResultIndex = -1;
|
||||
return next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches through the filetree for domain objects which match
|
||||
@ -216,15 +265,15 @@ define(
|
||||
*
|
||||
* @param inputID the name of the ID property of the html text
|
||||
* input where this funcion should find the search term
|
||||
* @param validType a function which takes a model for an object
|
||||
* and determines if it is of a valid type to include in the
|
||||
* final list of results
|
||||
* @param passedValidType (optional) a function which takes a model
|
||||
* for an object and determines if it is of a valid type to include
|
||||
* in the final list of results; default returns true
|
||||
* @param maxResults (optional) the maximum number of results
|
||||
* that this function should return
|
||||
* @param timeout (optional) the time after which the search should
|
||||
* stop calculations and return partial results
|
||||
*/
|
||||
function queryGeneric(inputID, validType, maxResults, timeout) {
|
||||
function queryGeneric(inputID, passedValidType, maxResults, timeout) {
|
||||
var input,
|
||||
terms = [],
|
||||
searchResults = [],
|
||||
@ -237,6 +286,8 @@ define(
|
||||
maxResults = DEFAULT_MAX_RESULTS;
|
||||
}
|
||||
|
||||
// Set the global validType function with the passed one
|
||||
validType = passedValidType;
|
||||
|
||||
// Get the user input
|
||||
input = document.getElementById(inputID).value;
|
||||
@ -244,6 +295,9 @@ define(
|
||||
// Get items list
|
||||
//requestItems(); // Test out the worker
|
||||
return getItems(timeout).then(function (searchResultItems) {
|
||||
// Set global items variable
|
||||
latestItems = searchResultItems;
|
||||
|
||||
// Keep track of the number of results to display
|
||||
if (searchResultItems.length < maxResults) {
|
||||
resultsLength = searchResultItems.length;
|
||||
@ -252,10 +306,13 @@ define(
|
||||
}
|
||||
|
||||
// Then filter through the items list
|
||||
searchResults = filterResults(searchResultItems, input, resultsLength, validType);
|
||||
//searchResults = filterResults(searchResultItems, input, resultsLength);
|
||||
|
||||
//console.log('filtered searchResults (in Everything)', searchResults);
|
||||
return searchResults;
|
||||
// Get the first search result
|
||||
var firstResult = first(input);
|
||||
console.log('generic return', firstResult);
|
||||
|
||||
return firstResult;
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user