X-Git-Url: http://git.veekun.com/zzz-floof.git/blobdiff_plain/efdbb22873232827398ba7605f8b35c605c043e9..e0b6c733c6bea7ff31b9361650fb8534b9433597:/floof/lib/search.py diff --git a/floof/lib/search.py b/floof/lib/search.py index 37d762d..8874824 100644 --- a/floof/lib/search.py +++ b/floof/lib/search.py @@ -1,43 +1,51 @@ -from floof.model import Art, Tag, TagText +from floof.model import Art, ArtUser, ArtUserType, Tag, TagText, User -def do_search(query): - tags = query.split() +def parse(search_string): + """Parses a search query, and returns a query object on Art. - tagtexts = TagText.query.filter(TagText.text.in_(tags)) - tagtext_ids = [_.id for _ in tagtexts] + Queries can contain: + - Regular tags: foo + - User relations: by:kalu, of:eevee, for:ootachi - # Fetch art that has all the tags - artwork = Art.query.join(Tag) \ - .filter(Tag.tagtext_id.in_(tagtext_ids)) \ - .all() - return artwork + Later: + - Negative versions of anything above: -by:eevee, -dongs + """ + # XXX doesn't do negative querying yet. + # XXX could use some sane limits. + # We'll be building this as we go. + q = Art.query + terms = search_string.split() + for tag in terms: + if ':' in tag: + # This is a special tag; at the moment, by/for/of to indicate + # related users + prefix, tag = tag.split(':', 1) + # XXX what to do if this fails? abort? return empty query? + target_user = User.get_by(name=tag) - -# unfinished stuff -def parse(query): - words = query.split() - - tags = [] - for word in words: - components = word.split(':') - if len(components) == 1: - # tags are plain. - tags.append(word) - elif components[0] == "rating": - if components[1].isnumeric(): - score = int(components[1]) + if prefix == 'by': + rel = ArtUserType.BY + elif prefix == 'for': + rel = ArtUserType.FOR + elif prefix == 'of': + rel = ArtUserType.OF else: - score = Rating.reverse_options.get(components[1]) + # Bogus tag. Not sure what to do here, so for the moment, + # ignore it + continue - if -1 <= score <= 3: - pass - # TODO: Find stuff that has this rating - # Rating.query.filter(Rating.s) + # Inner join to the ArtUser table + q = q.join(ArtUser, aliased=True) \ + .filter(ArtUser.user == target_user) \ + .filter(ArtUser.type == rel) - tagtexts = TagText.query.filter(TagText.text.in_(tags)) - tagtext_ids = map(lambda x:x.id, tagtexts) + else: + # Regular ol' tag + q = q.join(Tag, TagText, aliased=True) \ + .filter(TagText.text == tag) + return q