Archived
1
0

New multiple-notebook search query was way too slow. Now fixed.

- make model.Notebook.sql_search_notes() search either with user_id or an anonymous user_id, not both
  - update controller.Notebooks.search(), so if the anonymous user has access to the given notebook,
    then run the search as the anonymous user instead of the given user id
  - update unit tests
  - don't search trash/deleted notebooks
This commit is contained in:
Dan Helfman 2008-05-19 22:36:21 -07:00
parent 46b767ec27
commit ae5c911c1c
4 changed files with 27 additions and 14 deletions

3
NEWS
View File

@ -1,3 +1,6 @@
1.3.34: May 19, 2008
* Improved performance of searching multiple notebooks.
1.3.33: May 19, 2008
* Searching now displays results from multiple notebooks and not just the
current notebook.

View File

@ -920,9 +920,11 @@ class Notebooks( object ):
if not self.__users.check_access( user_id, notebook_id ):
raise Access_error()
anonymous = self.__database.select_one( User, User.sql_load_by_username( u"anonymous" ), use_cache = True )
if not anonymous:
raise Access_error()
# if the anonymous user has access to the given notebook, then run the search as the anonymous
# user instead of the given user id
if self.__users.check_access( user_id = None, notebook_id = notebook_id ) is True:
anonymous = self.__database.select_one( User, User.sql_load_by_username( u"anonymous" ), use_cache = True )
user_id = anonymous.object_id
MAX_SEARCH_TEXT_LENGTH = 256
if len( search_text ) > MAX_SEARCH_TEXT_LENGTH:
@ -931,7 +933,7 @@ class Notebooks( object ):
if len( search_text ) == 0:
raise Validation_error( u"search_text", None, unicode, message = u"is missing" )
notes = self.__database.select_many( Note, Notebook.sql_search_notes( user_id, anonymous.object_id, notebook_id, search_text ) )
notes = self.__database.select_many( Note, Notebook.sql_search_notes( user_id, notebook_id, search_text ) )
return dict(
notes = notes,

View File

@ -276,15 +276,23 @@ class Test_controller( object ):
Notebook.sql_load_note_by_title = lambda self, title: \
lambda database: sql_load_note_by_title( self, title, database )
def sql_search_notes( user_id, anonymous_user_id, first_notebook_id, search_text, database ):
def sql_search_notes( user_id, first_notebook_id, search_text, database ):
first_notes = []
other_notes = []
search_text = search_text.lower()
for ( object_id, obj_list ) in database.objects.items():
obj = obj_list[ -1 ]
if isinstance( obj, Note ) and ( database.user_notebook.get( user_id ) or \
( database.user_notebook.get( anonymous_user_id ) and note.notebook_id == first_notebook_id ) ) and \
if not isinstance( obj, Note ):
continue
if user_id in database.user_notebook:
for notebook_info in database.user_notebook[ user_id ]:
if notebook_info[ 0 ] != obj.notebook_id:
continue
if obj.deleted_from_id == None and \
search_text in obj.contents.lower():
if obj.notebook_id == first_notebook_id:
first_notes.append( obj )
@ -293,8 +301,8 @@ class Test_controller( object ):
return first_notes + other_notes
Notebook.sql_search_notes = staticmethod( lambda user_id, anonymous_user_id, first_notebook_id, search_text: \
lambda database: sql_search_notes( user_id, anonymous_user_id, first_notebook_id, search_text, database ) )
Notebook.sql_search_notes = staticmethod( lambda user_id, first_notebook_id, search_text: \
lambda database: sql_search_notes( user_id, first_notebook_id, search_text, database ) )
def sql_highest_note_rank( self, database ):
max_rank = -1

View File

@ -167,7 +167,7 @@ class Notebook( Persistent ):
return "select id, revision, title, contents, notebook_id, startup, deleted_from_id, rank, user_id from note_current where notebook_id = %s and title = %s;" % ( quote( self.object_id ), quote( title ) )
@staticmethod
def sql_search_notes( user_id, anonymous_user_id, first_notebook_id, search_text ):
def sql_search_notes( user_id, first_notebook_id, search_text ):
"""
Return a SQL string to perform a full-text search for notes within notebooks readable by the
given user whose contents contain the given search_text. This is a case-insensitive search.
@ -192,12 +192,12 @@ class Notebook( Persistent ):
from
note_current, user_notebook, to_tsquery( 'default', %s ) query
where
note_current.notebook_id = user_notebook.notebook_id and ( user_notebook.user_id = %s or
( user_notebook.user_id = %s and note_current.notebook_id = %s ) ) and
note_current.notebook_id = user_notebook.notebook_id and user_notebook.user_id = %s and
note_current.deleted_from_id is null and
query @@ search order by note_current.notebook_id = %s desc, rank desc limit 20
) as sub;
""" % ( quote( search_text ), quote( user_id ), quote( anonymous_user_id ),
quote( first_notebook_id ), quote( first_notebook_id ) )
""" % ( quote( search_text ), quote( user_id ),
quote( first_notebook_id ) )
def sql_highest_note_rank( self ):
"""