Search
The Search Aptitude provides the ability to index a set of documents and search the data using query strings and fuzzy searching.
API
Example
Permissions

createIndex

Builds a searchable index out of the supplied documents.
1
import { search } from '@oliveai/ldk';
2
3
const indexName = 'myIndex';
4
const documents = getDocuments();
5
const config = getConfig();
6
7
search.createIndex(indexName, documents, config).then((myNewIndex) => {
8
// We can now search the documents on the myNewIndex object
9
// See the Index sub-page for more info on searching
10
});
11
12
// There are many ways you could retrieve or build up your document objects
13
// for now we've just built up a small set of various first and last names
14
function getDocuments() {
15
return getPeople().map(personToDocument);
16
}
17
18
// See https://open-olive.github.io/loop-development-kit/ldk/javascript/interfaces/config.html
19
// for info on the config object
20
function getConfig() {
21
return {
22
sortBy: ['-lastName', 'firstName'], // Sort by last name descending, then first name ascending
23
searchSize: 2,
24
exactMatchThreshold: 4,
25
beginWithSearch: true,
26
};
27
}
28
29
function personToDocument(person) {
30
return {
31
name: person,
32
fields: [
33
{
34
name: 'firstName',
35
displayName: 'First Name', // Optional
36
type: search.FieldType.standard, // Optional - see https://open-olive.github.io/loop-development-kit/ldk/javascript/enums/fieldtype.html
37
// for a description of available types
38
},
39
{
40
name: 'lastName',
41
displayName: 'Last Name',
42
type: search.FieldType.standard,
43
},
44
],
45
// Note: The data field must be a stringified array of objects
46
data: JSON.stringify([{
47
firstName: person.split(' ')[0],
48
lastName: person.split(' ')[1],
49
}]),
50
};
51
}
52
53
function getPeople() {
54
return ['George Smith', 'George Jones', 'Alex Smith', 'Geoffrey McPerson', 'Jones Gregory'];
55
}
Copied!

openIndex

Open a previously created index with a new configuration object to search upon.
1
import { search } from '@oliveai/ldk';
2
3
const indexName = 'myIndex';
4
const config = {
5
sortBy: ['firstName', 'lastName'],
6
searchSize: 100,
7
exactMatchThreshold: 20,
8
beginWithSearch: true,
9
};
10
11
search.openIndex(indexName, config).then((index) => {
12
// We can now query the previously created 'myIndex' using an updated config
13
});
Copied!

exists

Checks to see if an index with the given name exists.
1
import { search } from '@oliveai/ldk';
2
3
const indexName = 'myIndex';
4
5
search.exists(indexName).then((indexExists) => {
6
if (indexExists) {
7
// The index exists, we could use openIndex here to begin a search on it
8
} else {
9
// The index does not exist, perhaps we should create it or throw an error
10
}
11
});
Copied!
Let's pretend we have several spreadsheets of error codes with the following columns: error number, name, and description. Each spreadsheet may pertain to a certain product or technology (i.e, one spreadsheet has HTML error codes, while another might have SQL error codes). We'd like to search this data whenever the user copies text to their clipboard and provide a whisper with detailed information about what went wrong.
1
/* index.tsx */
2
3
import * as React from 'react';
4
import { clipboard, search, document, filesystem } from '@oliveai/ldk';
5
import * as Renderer from '@oliveai/ldk/dist/whisper/react/renderer';
6
import { Row, Worksheet } from '@oliveai/ldk/dist/document/types';
7
8
// Put the file wherever you'd like on your filesystem
9
// Just make sure to update your path permissions accordingly
10
const ERROR_CODES_FILEPATH = './error_codes.xlsx';
11
const INDEX_NAME = 'ERROR_CODES';
12
const WHISPER_LABEL = 'Error Code';
13
14
// Setting up the whisper component
15
interface ErrorProps {
16
errorCode: string;
17
description: string;
18
}
19
20
const ErrorDisplay: React.FunctionComponent<ErrorProps> = (props) => {
21
const messageHeader = `${props.errorCode}`;
22
const messageBody = `${props.description}`;
23
24
return (
25
<oh-whisper label={WHISPER_LABEL} onClose={() => {}}>
26
<oh-message header={messageHeader} body={messageBody} />
27
</oh-whisper>
28
);
29
};
30
31
// We'll iterate over each worksheet in the spreadsheet and group
32
// all the rows per worksheet into a single document
33
function workSheet2Document(worksheet: Worksheet) {
34
const { name, rows } = worksheet;
35
const data = JSON.stringify(
36
rows.map((row: Row) => ({
37
errorCode: row.cells[0].value,
38
name: row.cells[1].value,
39
description: row.cells[2].value,
40
})),
41
);
42
43
return {
44
name,
45
data,
46
};
47
}
48
49
(async () => {
50
// Reading in the file and converting it is simple, even more so with async/await
51
const fileRaw = await filesystem.readFile(ERROR_CODES_FILEPATH);
52
const workbook = await document.xlsxDecode(fileRaw);
53
const documents = workbook.worksheets.map(workSheet2Document);
54
const index = await search.createIndex(INDEX_NAME, documents, {});
55
56
clipboard.listen(false, async (text: string) => {
57
const trimmedText = text.trim();
58
59
// We're going to just be searching the error code, so if its multiple words
60
// assume they copied something else for now
61
if (trimmedText.split(/\s+/).length != 1) {
62
return;
63
}
64
65
const results = await index.search(trimmedText);
66
67
if (results.total === 0) {
68
return;
69
}
70
71
const firstResult = results.data[0];
72
Renderer.renderNewWhisper(
73
<ErrorDisplay errorCode={firstResult.errorCode} description={firstResult.description} />,
74
);
75
});
76
})();
Copied!
We'll need to setup our permissions in our package.json as well.
1
...
2
"ldk": {
3
"permissions": {
4
"clipboard": {},
5
"document": {},
6
"filesystem": {
7
"pathGlobs": [
8
{
9
"value": "./error_codes.xlsx"
10
}
11
]
12
},
13
"search": {},
14
"whisper": {}
15
}
16
}
17
...
Copied!
To use the Search Aptitude, simply set the following permissions in your package.json under the ldk object.
Please see our Permissions page for more information.
1
...
2
"ldk": {
3
"permissions": {
4
"search": {},
5
...
6
}
7
},
8
...
Copied!
Copy link