[Code Style] Refactor search to use prototypes

WTD-1482.
This commit is contained in:
Victor Woeltjen
2015-08-17 11:20:23 -07:00
parent bf417a14e0
commit 4481c44c4b
3 changed files with 239 additions and 237 deletions

View File

@@ -44,10 +44,45 @@ define(
* @param $http Angular's $http service, for working with urls. * @param $http Angular's $http service, for working with urls.
* @param {ObjectService} objectService the service from which * @param {ObjectService} objectService the service from which
* domain objects can be gotten. * domain objects can be gotten.
* @param ROOT the constant ELASTIC_ROOT which allows us to * @param root the constant `ELASTIC_ROOT` which allows us to
* interact with ElasticSearch. * interact with ElasticSearch.
*/ */
function ElasticsearchSearchProvider($http, objectService, ROOT) { function ElasticsearchSearchProvider($http, objectService, root) {
this.$http = $http;
this.objectService = objectService;
this.root = root;
}
/**
* Searches through the filetree for domain objects using a search
* term. This is done through querying elasticsearch. Returns a
* promise for a result object that has the format
* {hits: searchResult[], total: number, timedOut: boolean}
* where a searchResult has the format
* {id: string, object: domainObject, score: number}
*
* Notes:
* * The order of the results is from highest to lowest score,
* as elsaticsearch determines them to be.
* * Uses the fuzziness operator to get more results.
* * More about this search's behavior at
* https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html
*
* @param searchTerm The text input that is the query.
* @param timestamp The time at which this function was called.
* This timestamp is used as a unique identifier for this
* query and the corresponding results.
* @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. Elasticsearch
* does not guarentee that this timeout will be strictly followed.
*/
ElasticsearchSearchProvider.prototype.query = function query(searchTerm, timestamp, maxResults, timeout) {
var $http = this.$http,
objectService = this.objectService,
root = this.root,
esQuery;
// Add the fuzziness operator to the search term // Add the fuzziness operator to the search term
function addFuzziness(searchTerm, editDistance) { function addFuzziness(searchTerm, editDistance) {
@@ -137,9 +172,6 @@ define(
}); });
} }
// For documentation, see query below.
function query(searchTerm, timestamp, maxResults, timeout) {
var esQuery;
// Check to see if the user provided a maximum // Check to see if the user provided a maximum
// number of results to display // number of results to display
@@ -154,14 +186,14 @@ define(
searchTerm = processSearchTerm(searchTerm); searchTerm = processSearchTerm(searchTerm);
// Create the query to elasticsearch // Create the query to elasticsearch
esQuery = ROOT + "/_search/?q=" + searchTerm + esQuery = root + "/_search/?q=" + searchTerm +
"&size=" + maxResults; "&size=" + maxResults;
if (timeout) { if (timeout) {
esQuery += "&timeout=" + timeout; esQuery += "&timeout=" + timeout;
} }
// Get the data... // Get the data...
return $http({ return this.$http({
method: "GET", method: "GET",
url: esQuery url: esQuery
}).then(function (rawResults) { }).then(function (rawResults) {
@@ -175,37 +207,7 @@ define(
} else { } else {
return {hits: [], total: 0}; return {hits: [], total: 0};
} }
}
return {
/**
* Searches through the filetree for domain objects using a search
* term. This is done through querying elasticsearch. Returns a
* promise for a result object that has the format
* {hits: searchResult[], total: number, timedOut: boolean}
* where a searchResult has the format
* {id: string, object: domainObject, score: number}
*
* Notes:
* * The order of the results is from highest to lowest score,
* as elsaticsearch determines them to be.
* * Uses the fuzziness operator to get more results.
* * More about this search's behavior at
* https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html
*
* @param searchTerm The text input that is the query.
* @param timestamp The time at which this function was called.
* This timestamp is used as a unique identifier for this
* query and the corresponding results.
* @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. Elasticsearch
* does not guarentee that this timeout will be strictly followed.
*/
query: query
}; };
}
return ElasticsearchSearchProvider; return ElasticsearchSearchProvider;

View File

@@ -48,9 +48,13 @@ define(
* domain objects' IDs. * domain objects' IDs.
*/ */
function GenericSearchProvider($q, $timeout, objectService, workerService, ROOTS) { function GenericSearchProvider($q, $timeout, objectService, workerService, ROOTS) {
var worker = workerService.run('genericSearchWorker'), var indexed = {},
indexed = {}, pendingQueries = {},
pendingQueries = {}; worker = workerService.run('genericSearchWorker');
this.worker = worker;
this.pendingQueries = pendingQueries;
this.$q = $q;
// pendingQueries is a dictionary with the key value pairs st // pendingQueries is a dictionary with the key value pairs st
// the key is the timestamp and the value is the promise // the key is the timestamp and the value is the promise
@@ -71,19 +75,6 @@ define(
} }
} }
// Tell the worker to search for items it has that match this searchInput.
// Takes the searchInput, as well as a max number of results (will return
// less than that if there are fewer matches).
function workerSearch(searchInput, maxResults, timestamp, timeout) {
var message = {
request: 'search',
input: searchInput,
maxNumber: maxResults,
timestamp: timestamp,
timeout: timeout
};
worker.postMessage(message);
}
// Handles responses from the web worker. Namely, the results of // Handles responses from the web worker. Namely, the results of
// a search request. // a search request.
@@ -120,8 +111,6 @@ define(
} }
} }
worker.onmessage = handleResponse;
// Helper function for getItems(). Indexes the tree. // Helper function for getItems(). Indexes the tree.
function indexItems(nodes) { function indexItems(nodes) {
nodes.forEach(function (node) { nodes.forEach(function (node) {
@@ -194,43 +183,12 @@ define(
}); });
} }
// For documentation, see query below worker.onmessage = handleResponse;
function query(input, timestamp, maxResults, timeout) {
var terms = [],
searchResults = [],
defer = $q.defer();
// If the input is nonempty, do a search
if (input !== '' && input !== undefined) {
// Allow us to access this promise later to resolve it later
pendingQueries[timestamp] = defer;
// Check to see if the user provided a maximum
// number of results to display
if (!maxResults) {
// Else, we provide a default value
maxResults = DEFAULT_MAX_RESULTS;
}
// Similarly, check if timeout was provided
if (!timeout) {
timeout = DEFAULT_TIMEOUT;
}
// Send the query to the worker
workerSearch(input, maxResults, timestamp, timeout);
return defer.promise;
} else {
// Otherwise return an empty result
return {hits: [], total: 0};
}
}
// Index the tree's contents once at the beginning // Index the tree's contents once at the beginning
getItems(); getItems();
}
return {
/** /**
* Searches through the filetree for domain objects which match * Searches through the filetree for domain objects which match
* the search term. This function is to be used as a fallback * the search term. This function is to be used as a fallback
@@ -257,11 +215,54 @@ define(
* @param timeout (optional) The time after which the search should * @param timeout (optional) The time after which the search should
* stop calculations and return partial results. * stop calculations and return partial results.
*/ */
query: query GenericSearchProvider.prototype.query = function query(input, timestamp, maxResults, timeout) {
var terms = [],
searchResults = [],
pendingQueries = this.pendingQueries,
worker = this.worker,
defer = this.$q.defer();
// Tell the worker to search for items it has that match this searchInput.
// Takes the searchInput, as well as a max number of results (will return
// less than that if there are fewer matches).
function workerSearch(searchInput, maxResults, timestamp, timeout) {
var message = {
request: 'search',
input: searchInput,
maxNumber: maxResults,
timestamp: timestamp,
timeout: timeout
}; };
worker.postMessage(message);
} }
// If the input is nonempty, do a search
if (input !== '' && input !== undefined) {
// Allow us to access this promise later to resolve it later
pendingQueries[timestamp] = defer;
// Check to see if the user provided a maximum
// number of results to display
if (!maxResults) {
// Else, we provide a default value
maxResults = DEFAULT_MAX_RESULTS;
}
// Similarly, check if timeout was provided
if (!timeout) {
timeout = DEFAULT_TIMEOUT;
}
// Send the query to the worker
workerSearch(input, maxResults, timestamp, timeout);
return defer.promise;
} else {
// Otherwise return an empty result
return { hits: [], total: 0 };
}
};
return GenericSearchProvider; return GenericSearchProvider;
} }

View File

@@ -42,6 +42,28 @@ define(
* aggregated. * aggregated.
*/ */
function SearchAggregator($q, providers) { function SearchAggregator($q, providers) {
this.$q = $q;
this.providers = providers;
}
/**
* Sends a query to each of the providers. Returns a promise for
* a result object that has the format
* {hits: searchResult[], total: number, timedOut: boolean}
* where a searchResult has the format
* {id: string, object: domainObject, score: number}
*
* @param inputText The text input that is the query.
* @param maxResults (optional) The maximum number of results
* that this function should return. If not provided, a
* default of 100 will be used.
*/
SearchAggregator.prototype.query = function queryAll(inputText, maxResults) {
var $q = this.$q,
providers = this.providers,
i,
timestamp = Date.now(),
resultPromises = [];
// Remove duplicate objects that have the same ID. Modifies the passed // Remove duplicate objects that have the same ID. Modifies the passed
// array, and returns the number that were removed. // array, and returns the number that were removed.
@@ -82,12 +104,6 @@ define(
return results; return results;
} }
// For documentation, see query below.
function queryAll(inputText, maxResults) {
var i,
timestamp = Date.now(),
resultPromises = [];
if (!maxResults) { if (!maxResults) {
maxResults = DEFAULT_MAX_RESULTS; maxResults = DEFAULT_MAX_RESULTS;
} }
@@ -122,24 +138,7 @@ define(
}) })
}; };
}); });
}
return {
/**
* Sends a query to each of the providers. Returns a promise for
* a result object that has the format
* {hits: searchResult[], total: number, timedOut: boolean}
* where a searchResult has the format
* {id: string, object: domainObject, score: number}
*
* @param inputText The text input that is the query.
* @param maxResults (optional) The maximum number of results
* that this function should return. If not provided, a
* default of 100 will be used.
*/
query: queryAll
}; };
}
return SearchAggregator; return SearchAggregator;
} }