#NEWLINE# @ defer . inlineCallbacks #NEWLINE# def search_msgs( self , room_ids , search_term , keys ) : #NEWLINE# #INDENT# 'Performs a full text search over events with given keys.\n\n        Args:\n            room_ids (list): List of room ids to search in\n            search_term (str): Search term to search for\n            keys (list): List of keys to search in, currently supports\n                "content.body", "content.name", "content.topic"\n\n        Returns:\n            list of dicts\n        ' #NEWLINE# clauses = [ ] #NEWLINE# search_query = search_query = _parse_query ( self . database_engine , search_term ) #NEWLINE# args = [ ] #NEWLINE# if ( len ( room_ids ) < 500 ) : #NEWLINE# #INDENT# clauses . append ( ( 'room_id IN (%s)' % ( ',' . join ( ( [ '?' ] * len ( room_ids ) ) ) , ) ) ) #NEWLINE# args . extend ( room_ids ) #NEWLINE# #UNINDENT# local_clauses = [ ] #NEWLINE# for key in keys : #NEWLINE# #INDENT# local_clauses . append ( 'key = ?' ) #NEWLINE# args . append ( key ) #NEWLINE# #UNINDENT# clauses . append ( ( '(%s)' % ( ' OR ' . join ( local_clauses ) , ) ) ) #NEWLINE# count_args = args #NEWLINE# count_clauses = clauses #NEWLINE# if isinstance ( self . database_engine , PostgresEngine ) : #NEWLINE# #INDENT# sql = "SELECT ts_rank_cd(vector, to_tsquery('english', ?)) AS rank, room_id, event_id FROM event_search WHERE vector @@ to_tsquery('english', ?)" #NEWLINE# args = ( [ search_query , search_query ] + args ) #NEWLINE# count_sql = "SELECT room_id, count(*) as count FROM event_search WHERE vector @@ to_tsquery('english', ?)" #NEWLINE# count_args = ( [ search_query ] + count_args ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if isinstance ( self . database_engine , Sqlite3Engine ) : #NEWLINE# #INDENT# sql = 'SELECT rank(matchinfo(event_search)) as rank, room_id, event_id FROM event_search WHERE value MATCH ?' #NEWLINE# args = ( [ search_query ] + args ) #NEWLINE# count_sql = 'SELECT room_id, count(*) as count FROM event_search WHERE value MATCH ?' #NEWLINE# count_args = ( [ search_term ] + count_args ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# raise Exception ( 'Unrecognized database engine' ) #NEWLINE# #UNINDENT# #UNINDENT# for clause in clauses : #NEWLINE# #INDENT# sql += ( ' AND ' + clause ) #NEWLINE# #UNINDENT# for clause in count_clauses : #NEWLINE# #INDENT# count_sql += ( ' AND ' + clause ) #NEWLINE# #UNINDENT# sql += ' ORDER BY rank DESC LIMIT 500' #NEWLINE# results = ( yield self . _execute ( 'search_msgs' , self . cursor_to_dict , sql , * args ) ) #NEWLINE# results = filter ( ( lambda row : ( row [ 'room_id' ] in room_ids ) ) , results ) #NEWLINE# events = ( yield self . _get_events ( [ r [ 'event_id' ] for r in results ] ) ) #NEWLINE# event_map = { ev . event_id : ev for ev in events } #NEWLINE# highlights = None #NEWLINE# if isinstance ( self . database_engine , PostgresEngine ) : #NEWLINE# #INDENT# highlights = ( yield self . _find_highlights_in_postgres ( search_query , events ) ) #NEWLINE# #UNINDENT# count_sql += ' GROUP BY room_id' #NEWLINE# count_results = ( yield self . _execute ( 'search_rooms_count' , self . cursor_to_dict , count_sql , * count_args ) ) #NEWLINE# count = sum ( ( row [ 'count' ] for row in count_results if ( row [ 'room_id' ] in room_ids ) ) ) #NEWLINE# defer . returnValue ( { #NEWLINE# #INDENT# 'results' : [ { #NEWLINE# #INDENT# 'event' : event_map [ r [ 'event_id' ] ] , #NEWLINE# 'rank' : r [ 'rank' ] , #NEWLINE# #UNINDENT# } for r in results if ( r [ 'event_id' ] in event_map ) ] , #NEWLINE# 'highlights' : highlights , #NEWLINE# 'count' : count , #NEWLINE# #UNINDENT# } )