Merge pull request #14 from fedora-copr/master

added whoosheer option for whooshee_search method
This commit is contained in:
Slavek Kabrda
2016-05-11 15:49:18 +02:00
3 changed files with 56 additions and 16 deletions
+10
View File
@@ -108,6 +108,16 @@ Now you can search join queries like this:
Entry.query.join(User).whooshee_search('chuck norris').order_by(Entry.id.desc()).all()
```
The whoosheer that is used for searching is, by default, selected based on the models participating in the query.
This set of models is compared against the value of `models` attribute of each registered whoosheer and the one
with an exact match is selected. You can override this behaviour by explicitly passing whoosheer that should be
used for searching to the `whooshee_search` method. This is useful if you don't want to join on all the models that
form the search index. For example:
```python
Entry.query.whooshee_search('chuck norris', whoosheer=EntryUserWhoosheer).order_by(Entry.id.desc()).all()
```
If there exists an entry of a user called 'chuck norris', this entry will be found because the custom whoosheer, that contains field `username`, will be used. But without the whoosheer option, that entry won't be found (unless it has 'chuck norris' in content or title) because the model whoosheer will be used.
### Reindex
Available since v0.0.9.
+16 -16
View File
@@ -17,8 +17,7 @@ from sqlalchemy.orm.mapper import Mapper
class WhoosheeQuery(BaseQuery):
"""An override for SQLAlchemy query used to do fulltext search."""
# TODO: add an option to override used Whoosheer
def whooshee_search(self, search_string, group=whoosh.qparser.OrGroup,
def whooshee_search(self, search_string, group=whoosh.qparser.OrGroup, whoosheer=None,
match_substrings=True, limit=None, order_by_relevance=10):
"""Do a fulltext search on the query.
@@ -32,21 +31,22 @@ class WhoosheeQuery(BaseQuery):
Returns:
query filtered with results of the fulltext search
"""
### inspiration taken from flask-WhooshAlchemy
# find out all entities in join
entities = set()
# directly queried entities
for cd in self.column_descriptions:
entities.add(cd['type'])
# joined entities
if self._join_entities and isinstance(self._join_entities[0], Mapper):
# SQLAlchemy >= 0.8.0
entities.update(set([x.entity for x in self._join_entities]))
else:
# SQLAlchemy < 0.8.0
entities.update(set(self._join_entities))
if not whoosheer:
### inspiration taken from flask-WhooshAlchemy
# find out all entities in join
entities = set()
# directly queried entities
for cd in self.column_descriptions:
entities.add(cd['type'])
# joined entities
if self._join_entities and isinstance(self._join_entities[0], Mapper):
# SQLAlchemy >= 0.8.0
entities.update(set([x.entity for x in self._join_entities]))
else:
# SQLAlchemy < 0.8.0
entities.update(set(self._join_entities))
whoosheer = next(w for w in Whooshee.whoosheers if set(w.models) == entities)
whoosheer = next(w for w in Whooshee.whoosheers if set(w.models) == entities)
# TODO what if unique field doesn't exist or there are multiple?
for fname, field in list(whoosheer.schema._fields.items()):
+30
View File
@@ -76,6 +76,7 @@ class BaseTestCases(object):
title=entry.title,
content=entry.content)
self.User = User
self.Entry = Entry
self.EntryUserWhoosheer = EntryUserWhoosheer
@@ -189,6 +190,35 @@ class BaseTestCases(object):
titles = [int(entry.title) for entry in found_entries]
self.assertEqual(titles, sorted(titles))
def test_whoosheer_search_option(self):
# alternative whoosheer
@self.wh.register_whoosheer
class EntryWhoosheer(AbstractWhoosheer):
schema = whoosh.fields.Schema(
entry_id = whoosh.fields.NUMERIC(stored=True, unique=True),
title = whoosh.fields.TEXT()
)
models = [self.Entry]
@classmethod
def update_entry(cls, writer, entry):
writer.update_document(entry_id=entry.id, title=entry.title+'cookie')
@classmethod
def insert_entry(cls, writer, entry):
writer.add_document(entry_id=entry.id, title=entry.title+'cookie')
entry = self.Entry(title=u'secret_', content=u'blah blah blah', user=self.u1)
self.db.session.add(entry)
self.db.session.commit()
found = self.Entry.query.join(self.User).whooshee_search('secret_cookie').all()
self.assertEqual(len(found), 0)
found = self.Entry.query.join(self.User).whooshee_search('secret_cookie', whoosheer=EntryWhoosheer).all()
self.assertEqual(len(found), 1)
def test_reindex(self):
self.db.session.add_all(self.all_inst)
self.db.session.commit()