From 8b715f331cdc32b623a24fbdc0dd266d5431c15b Mon Sep 17 00:00:00 2001 From: Deep Tailor Date: Tue, 22 Oct 2019 16:53:06 -0700 Subject: [PATCH] Search indexer (#2445) * add a bare bones indexer * use constant to fallback to legacy indexer --- platform/search/bundle.js | 12 +++ .../src/services/BareBonesSearchWorker.js | 80 +++++++++++++++++++ .../src/services/GenericSearchProvider.js | 44 +++++++--- src/ui/layout/tree-item.vue | 2 +- 4 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 platform/search/src/services/BareBonesSearchWorker.js diff --git a/platform/search/bundle.js b/platform/search/bundle.js index 6a5b578dae..02bc333168 100644 --- a/platform/search/bundle.js +++ b/platform/search/bundle.js @@ -29,6 +29,7 @@ define([ "./res/templates/search.html", "./res/templates/search-menu.html", "raw-loader!./src/services/GenericSearchWorker.js", + "raw-loader!./src/services/BareBonesSearchWorker.js", 'legacyRegistry' ], function ( SearchController, @@ -39,6 +40,7 @@ define([ searchTemplate, searchMenuTemplate, searchWorkerText, + BareBonesSearchWorkerText, legacyRegistry ) { @@ -53,6 +55,11 @@ define([ "ROOT" ], "priority": "fallback" + }, + { + "key": "USE_LEGACY_INDEXER", + "value": false, + "priority": 2 } ], "controllers": [ @@ -101,6 +108,7 @@ define([ "workerService", "topic", "GENERIC_SEARCH_ROOTS", + "USE_LEGACY_INDEXER", "openmct" ] }, @@ -115,6 +123,10 @@ define([ } ], "workers": [ + { + "key": "bareBonesSearchWorker", + "scriptText": BareBonesSearchWorkerText + }, { "key": "genericSearchWorker", "scriptText": searchWorkerText diff --git a/platform/search/src/services/BareBonesSearchWorker.js b/platform/search/src/services/BareBonesSearchWorker.js new file mode 100644 index 0000000000..6629670d08 --- /dev/null +++ b/platform/search/src/services/BareBonesSearchWorker.js @@ -0,0 +1,80 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2018, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +/*global self*/ + +/** + * Module defining BareBonesSearchWorker. Created by deeptailor on 10/03/2019. + */ +(function () { + + // An array of objects composed of domain object IDs and names + // {id: domainObject's ID, name: domainObject's name} + var indexedItems = []; + + function indexItem(id, model) { + indexedItems.push({ + id: id, + name: model.name.toLowerCase() + }); + } + + /** + * Gets search results from the indexedItems based on provided search + * input. Returns matching results from indexedItems + * + * @param data An object which contains: + * * input: The original string which we are searching with + * * maxResults: The maximum number of search results desired + * * queryId: an id identifying this query, will be returned. + */ + function search(data) { + // This results dictionary will have domain object ID keys which + // point to the value the domain object's score. + var results, + input = data.input.trim().toLowerCase(), + message = { + request: 'search', + results: {}, + total: 0, + queryId: data.queryId + }; + + results = indexedItems.filter((indexedItem) => { + return indexedItem.name.includes(input); + }); + + message.total = results.length; + message.results = results + .slice(0, data.maxResults); + + return message; + } + + self.onmessage = function (event) { + if (event.data.request === 'index') { + indexItem(event.data.id, event.data.model); + } else if (event.data.request === 'search') { + self.postMessage(search(event.data)); + } + }; +}()); diff --git a/platform/search/src/services/GenericSearchProvider.js b/platform/search/src/services/GenericSearchProvider.js index a2b7d785a1..5bfebe24e9 100644 --- a/platform/search/src/services/GenericSearchProvider.js +++ b/platform/search/src/services/GenericSearchProvider.js @@ -44,7 +44,7 @@ define([ * @param {TopicService} topic the topic service. * @param {Array} ROOTS An array of object Ids to begin indexing. */ - function GenericSearchProvider($q, $log, modelService, workerService, topic, ROOTS, openmct) { + function GenericSearchProvider($q, $log, modelService, workerService, topic, ROOTS, USE_LEGACY_INDEXER, openmct) { var provider = this; this.$q = $q; this.$log = $log; @@ -58,6 +58,8 @@ define([ this.pendingQueries = {}; + this.USE_LEGACY_INDEXER = USE_LEGACY_INDEXER; + this.worker = this.startWorker(workerService); this.indexOnMutation(topic); @@ -101,8 +103,14 @@ define([ * @returns worker the created search worker. */ GenericSearchProvider.prototype.startWorker = function (workerService) { - var worker = workerService.run('genericSearchWorker'), - provider = this; + var provider = this, + worker; + + if (this.USE_LEGACY_INDEXER) { + worker = workerService.run('genericSearchWorker'); + } else { + worker = workerService.run('bareBonesSearchWorker'); + } worker.addEventListener('message', function (messageEvent) { provider.onWorkerMessage(messageEvent); @@ -242,18 +250,34 @@ define([ return; } - var pendingQuery = this.pendingQueries[event.data.queryId], + var pendingQuery, + modelResults; + + if (this.USE_LEGACY_INDEXER) { + pendingQuery = this.pendingQueries[event.data.queryId]; modelResults = { total: event.data.total }; - modelResults.hits = event.data.results.map(function (hit) { - return { - id: hit.item.id, - model: hit.item.model, - score: hit.matchCount + modelResults.hits = event.data.results.map(function (hit) { + return { + id: hit.item.id, + model: hit.item.model, + score: hit.matchCount + }; + }); + } else { + pendingQuery = this.pendingQueries[event.data.queryId]; + modelResults = { + total: event.data.total }; - }); + + modelResults.hits = event.data.results.map(function (hit) { + return { + id: hit.id + }; + }); + } pendingQuery.resolve(modelResults); delete this.pendingQueries[event.data.queryId]; diff --git a/src/ui/layout/tree-item.vue b/src/ui/layout/tree-item.vue index 398eeeae70..3b8feb7f84 100644 --- a/src/ui/layout/tree-item.vue +++ b/src/ui/layout/tree-item.vue @@ -69,8 +69,8 @@ let removeListener = this.openmct.objects.observe(this.domainObject, '*', (newObject) => { this.domainObject = newObject; }); - this.$once('hook:destroyed', removeListener); + this.$once('hook:destroyed', removeListener); if (this.openmct.composition.get(this.node.object)) { this.hasChildren = true; }