[search-index] Add isSearchIndexed field to searchable models

Summary:
The isModelIndexed function was extremely slow because it was scanning
the unindexed 'content_id' field in the search index table. This diff
adds a field to the searchable models (currently Thread, Contact, and
Event) that stores whether that particular model has been indexed or
not, allowing us to avoid doing the O(n) scan of the search index table.

Test Plan: Run locally, verify that isModelIndexed is no longer a bottleneck

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3695
This commit is contained in:
Mark Hahnenberg 2017-01-15 14:39:00 -08:00
parent eb6001480c
commit 93b4031bcc
4 changed files with 29 additions and 10 deletions

View file

@ -75,6 +75,11 @@ export default class Contact extends Model {
company: Attributes.String({
modelKey: 'company',
}),
isSearchIndexed: Attributes.Boolean({
modelKey: 'isSearchIndexed',
jsonKey: 'is_search_indexed',
}),
});
static additionalSQLiteConfig = {

View file

@ -110,6 +110,11 @@ export default class Event extends Model {
modelKey: 'end',
jsonKey: '_end',
}),
isSearchIndexed: Attributes.Boolean({
modelKey: 'isSearchIndexed',
jsonKey: 'is_search_indexed',
}),
});
static additionalSQLiteConfig = {

View file

@ -105,6 +105,11 @@ class Thread extends ModelWithMetadata {
modelKey: 'inAllMail',
jsonKey: 'in_all_mail',
}),
isSearchIndexed: Attributes.Boolean({
modelKey: 'isSearchIndexed',
jsonKey: 'is_search_indexed',
}),
})
static naturalSortOrder = () => {

View file

@ -772,13 +772,7 @@ class DatabaseStore extends NylasStore {
if (isIndexed === true) {
return Promise.resolve(true);
}
const searchTableName = `${model.constructor.name}Search`
const exists = (
`SELECT rowid FROM \`${searchTableName}\` WHERE \`${searchTableName}\`.\`content_id\` = ?`
)
return this._query(exists, [model.id]).then((results) =>
Promise.resolve(results.length > 0)
)
return Promise.resolve(!!model.isSearchIndexed);
}
indexModel(model, indexData, isModelIndexed) {
@ -795,7 +789,10 @@ class DatabaseStore extends NylasStore {
const sql = (
`INSERT INTO \`${searchTableName}\`(${keysSql}) VALUES (${valsSql})`
)
return this._query(sql, values);
return this._query(sql, values).then(() => {
model.isSearchIndexed = true;
return this.inTransaction((t) => t.persistModel(model))
});
});
}
@ -825,17 +822,24 @@ class DatabaseStore extends NylasStore {
const sql = (
`DELETE FROM \`${searchTableName}\` WHERE \`${searchTableName}\`.\`content_id\` = ?`
);
return this._query(sql, [model.id]);
return this._query(sql, [model.id]).then(() => {
model.isSearchIndexed = false;
return this.inTransaction((t) => t.persistModel(model))
});
}
unindexModelsForAccount(accountId, modelKlass) {
const modelTable = modelKlass.name;
const searchTableName = `${modelTable}Search`;
/* TODO: We don't correctly clean up the model tables right now, so we don't
* want to destroy the index until we do so.
const sql = (
`DELETE FROM \`${searchTableName}\` WHERE \`${searchTableName}\`.\`content_id\` IN
(SELECT \`id\` FROM \`${modelTable}\` WHERE \`${modelTable}\`.\`account_id\` = ?)`
);
return this._query(sql, [accountId]);
return this._query(sql, [accountId])
*/
return Promise.resolve()
}
}