Here's what's in `IndexableText` right now:
1. Title
2. Collections
3. Authors
4. Tags
5. LocSubjects
6. TocEntries
Here is the proposed new ranking:
```
10 * Title +
8 * Authors +
3 * Collections +
IndexableText
```
New indices for existing DBs:
```
ALTER TABLE `Ebooks` ADD COLUMN `IndexableAuthors` text NOT NULL;
ALTER TABLE `Ebooks` ADD COLUMN `IndexableCollections` text NULL;
ALTER TABLE `Ebooks` ADD FULLTEXT `indexSearchTitle` (`Title`);
ALTER TABLE `Ebooks` ADD FULLTEXT `idxSearchAuthors` (`IndexableAuthors`);
ALTER TABLE `Ebooks` ADD FULLTEXT `idxSearchCollections` (`IndexableCollections`);
```
Instead of `USING(EbookId)`, it would be easier to handle
`MultiTableSelect` queries in `FromMultiTableRow()` if the queries used
`ON Projects.EbookId = Ebooks.Ebooks`
This is because `USING` will return only one `EbookId` column, but `ON`
will return all columns from both tables.
On `Ebook::Save()` and `Ebook::Delete()`, remove any unreferenced `Tag`,
`LocSubject`, and `Collection` records. These are analogous to these lines in
`Ebook::Create()`:
```
$this->CreateTags();
$this->CreateLocSubjects();
$this->CreateCollections();
```
`EbookPlaceholder`s can't have `Tags` or `LocSubjects` at the moment, but other
mistakes in production that are later corrected could leave unused `Tags` and
`LocSubjects`.
Context: https://github.com/standardebooks/web/pull/447#issuecomment-2555734692
`Ebook` to `Contributor` is one to many, and we don't query by ContributorId.
The table already has a SortOrder column, and we use that to order the queries.
There is a one to many relationship between `Ebook` and `EbookSource`, and we
don't query by `EbookSourceId`. We add a `SortOrder` column to keep the sources
in the same order as specified in `content.opf`.