Skip to content
This repository was archived by the owner on Jun 19, 2022. It is now read-only.

Commit 85515fa

Browse files
committed
Added indexed_title_changed() method to handle title changes for an indexed entity.
1 parent ead15ef commit 85515fa

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

search/__init__.py

+31-2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@
5151
# Use python port of Porter2 stemmer.
5252
from search.pyporter2 import Stemmer
5353

54+
class Error(Exception):
55+
"""Base search module error type."""
56+
57+
class IndexTitleError(Error):
58+
"""Raised when INDEX_TITLE_FROM_PROP or title alterations are incorrect."""
59+
5460
# Following module-level constants are cached in instance
5561

5662
KEY_NAME_DELIMITER = '||' # Used to hold arbitrary strings in key names.
@@ -125,6 +131,14 @@ def get_title(key_name=''):
125131
else:
126132
return frags[2]
127133

134+
@staticmethod
135+
def get_index_num(key_name=''):
136+
frags = key_name.split(KEY_NAME_DELIMITER)
137+
if len(frags) < 2:
138+
return '1'
139+
else:
140+
return frags[1]
141+
128142
@classmethod
129143
def put_index(cls, parent, phrases, index_num=1):
130144
parent_key = parent.key()
@@ -136,11 +150,9 @@ def put_index(cls, parent, phrases, index_num=1):
136150

137151
class LiteralIndex(SearchIndex):
138152
"""Index model for non-inflected search phrases."""
139-
pass
140153

141154
class StemmedIndex(SearchIndex):
142155
"""Index model for stemmed (inflected) search phrases."""
143-
pass
144156

145157

146158
class Searchable(object):
@@ -409,6 +421,23 @@ def search(cls, phrase, limit=10, keys_only=False):
409421
else:
410422
return [cls.get(key_and_title[0]) for key_and_title in key_list]
411423

424+
def indexed_title_changed(self):
425+
"""Renames index entities for this model to match new title."""
426+
klass = StemmedIndex if self.INDEX_STEMMING else LiteralIndex
427+
query = klass.all(keys_only=True).ancestor(self.key())
428+
old_index_keys = query.fetch(1000)
429+
if not hasattr(self, 'INDEX_TITLE_FROM_PROP'):
430+
raise IndexTitleError('Must declare a property name via INDEX_TITLE_FROM_PROP')
431+
new_keys = []
432+
for old_key in old_index_keys:
433+
old_index = db.get(old_key)
434+
index_num = SearchIndex.get_index_num(old_key.name())
435+
index_key = klass.put_index(parent=self, index_num=index_num,
436+
phrases=old_index.phrases)
437+
new_keys.append(index_key)
438+
delete_keys = filter(lambda key: key not in new_keys, old_index_keys)
439+
db.delete(delete_keys)
440+
412441
def get_search_phrases(self, indexing_func=None):
413442
"""Returns search phrases from properties in a given Model instance.
414443

tests/test_search.py

+13
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,19 @@ def test_title_from_parent(self):
213213
assert page_list[0][0].name() == 'test3'
214214
assert page_list[0][1] == 'Third Post'
215215

216+
def test_title_change(self):
217+
pages = Page.search('second post')
218+
assert len(pages) == 1
219+
page = pages[0]
220+
page.title = 'My Great New Title'
221+
old_key = page.put()
222+
page.indexed_title_changed()
223+
assert search.StemmedIndex.all().count() == 3
224+
page_list = Page.search('second post', keys_only=True)
225+
assert len(page_list) == 1
226+
assert page_list[0][1] == 'My Great New Title'
227+
assert page_list[0][0].id_or_name() == old_key.id_or_name()
228+
216229
class TestMultiWordSearch:
217230
def setup(self):
218231
clear_datastore()

0 commit comments

Comments
 (0)