Workout With Friends Stay fit with a little motivation

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Properties
fulltext.py
Go to the documentation of this file.
1 ##
2 #
3 # Helpers to assist in Whoosh fulltext indexing and searching.
4 #
5
6 from __future__ import unicode_literals
7 import os
8 from whoosh.analysis import NgramFilter, StandardAnalyzer
9 from whoosh.fields import ID, SchemaClass, TEXT
10 from whoosh.filedb.filestore import FileStorage, RamStorage
11 from whoosh.index import exists_in
12 from whoosh.qparser import QueryParser
13
14
15 index = None
16 parser = QueryParser
17 analyzer = StandardAnalyzer() | NgramFilter(minsize=2, maxsize=2)
18
19
20 def initialize_fulltext(settings):
21 global index
22 index_path = settings.get('fulltext_dir')
23 if not index_path:
24 storage = RamStorage()
25 index = storage.create_index(schema=WhooshSchema)
26 return
27 if not os.path.exists(index_path):
28 os.makedirs(index_path)
29 storage = FileStorage(index_path)
30 if not exists_in(index_path):
31 index = storage.create_index(schema=WhooshSchema)
32 else:
33 index = storage.open_index(schema=WhooshSchema)
34
35
36 ##
37 #
38 # Very generic indexing schema.
39 #
40 class WhooshSchema(SchemaClass):
41
42 index_id = ID(stored=True, unique=True)
43 data = TEXT(stored=False, analyzer=analyzer)
44
45
46 ##
47 #
48 # Adds support for fulltext searching to SQLAlchemy's Base object.
49 #
50 class FulltextBase(object):
51
52 index_fields = []
53
54 @classmethod
55 def index_type(cls):
56 return cls.__name__
57
58 def index_id(self):
59 return '%s:%s' % (self.index_type(), self.id)
60
61 def index_data(self):
62 return ' '.join([unicode(getattr(self, attr)) for attr in self.index_fields])
63
64 ##
65 #
66 # Add a fulltext index for this instance.
67 #
68 def add_index(self, writer):
69 if self.index_fields:
70 writer.add_document(index_id=self.index_id(), data=self.index_data())
71
72 ##
73 #
74 # Delete the fulltext index for this instance.
75 #
76 def delete_index(self, writer):
77 if self.index_fields:
78 writer.delete_by_term('index_id', self.index_id())
79
80 ##
81 #
82 # Update the fulltext index for this instance.
83 #
84 def update_index(self, writer):
85 if self.index_fields:
86 writer.update_document(index_id=self.index_id(), data=self.index_data())
87
88 @classmethod
89 ##
90 #
91 # Return a query for items after performing a fulltext search.
92 #
93 def _get_fulltext_query(cls, terms):
94 ids = _search(terms, cls.index_type())
95 return cls.query.filter(cls.id.in_(ids))
96
97
98 ##
99 #
100 # Perform a search of the given type using the terms. Return all ids which
101 # match.
102 #
103 def _search(terms, index_type):
104 query = parser('data', index.schema).parse(terms)
105 with index.searcher() as searcher:
106 results = searcher.search(query)
107 ids = _results_to_ids(results, index_type)
108 return ids
109
110
111 ##
112 #
113 # Convert search results to ids to be used in a SQLAlchemy query.
114 #
115 def _results_to_ids(results, index_type):
116 ids = set()
117 for result in results:
118 type, id = result.get('index_id').split(':')
119 if type == index_type:
120 ids.add(id)
121 return ids
122