+# Dictionary of table name => table class.
+# Need the table name so we can get the class from the table name after we
+# retrieve something from the index
+indexed_tables = {}
+for cls in [
+ tables.Pokemon,
+ ]:
+ indexed_tables[cls.__tablename__] = cls
+
+index_bits = {}
+def get_index(session):
+ """Returns (index, speller).
+
+ Creates an index if one does not exist.
+ """
+
+ if index_bits:
+ return index_bits['index'], index_bits['speller']
+
+ store = whoosh.store.RamStorage()
+ schema = whoosh.fields.Schema(
+ name=whoosh.fields.ID(stored=True),
+ spelling_name=whoosh.fields.ID(stored=True),
+ table=whoosh.fields.STORED,
+ row_id=whoosh.fields.STORED,
+ language_id=whoosh.fields.STORED,
+ )
+
+ index = whoosh.index.Index(store, schema=schema, create=True)
+ writer = index.writer()
+
+ # Index every name in all our tables of interest
+ for cls in indexed_tables.values():
+ q = session.query(cls)
+
+ # Only index base Pokémon formes
+ if hasattr(cls, 'forme_base_pokemon_id'):
+ q = q.filter_by(forme_base_pokemon_id=None)
+
+ for row in q.yield_per(5):
+ name = row.name.lower()
+ spelling_name = re.sub('[^a-z]', '', name)
+ writer.add_document(name=name,
+ spelling_name=spelling_name,
+ table=cls.__tablename__,
+ row_id=row.id)
+
+ writer.commit()
+
+ ### Construct a spell-checker index
+ speller = whoosh.spelling.SpellChecker(index.storage)
+
+ # Can't use speller.add_field because it tries to intuit a frequency, and
+ # names are in an ID field, which seems to be immune to frequency.
+ # Not hard to add everything ourselves, though
+ reader = index.doc_reader()
+ speller.add_words([ _['spelling_name'] for _ in reader ])
+ reader.close()
+
+ index_bits['index'] = index
+ index_bits['speller'] = speller
+ index_bits['store'] = store
+ return index_bits['index'], index_bits['speller']
+
+def lookup(session, name, exact_only=False):