123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- from django.conf import settings
- import fstools
- import logging
- from .models import Item
- import os
- from whoosh.fields import Schema, ID, TEXT, KEYWORD, NUMERIC, DATETIME
- from whoosh.qparser.dateparse import DateParserPlugin
- from whoosh import index, qparser
- from pygal.models import TYPE_FOLDER
-
- logger = logging.getLogger(settings.ROOT_LOGGER_NAME).getChild(__name__)
-
-
- SCHEMA = Schema(
- rel_path=ID(unique=True, stored=True),
- # Item
- name=TEXT,
- type=TEXT,
- favourite_of=KEYWORD,
- datetime=DATETIME,
- size=NUMERIC,
- # Tag
- tag=KEYWORD,
- # Image Cache
- exposure_program=TEXT,
- exposure_time=NUMERIC,
- flash=TEXT,
- f_number=NUMERIC,
- focal_length=NUMERIC,
- lon=NUMERIC,
- lat=NUMERIC,
- height=NUMERIC,
- iso=NUMERIC,
- camera=TEXT,
- orientation=NUMERIC,
- width=NUMERIC,
- # Audio Cache
- album=TEXT,
- artist=TEXT,
- bitrate=NUMERIC,
- duration=NUMERIC,
- genre=TEXT,
- title=TEXT,
- track=NUMERIC,
- year=NUMERIC,
- #
- ratio=NUMERIC,
- )
-
-
- def create_index():
- logger.debug('Search Index created.')
- return index.create_in(settings.WHOOSH_PATH, schema=SCHEMA)
-
-
- def load_index():
- if not os.path.exists(settings.WHOOSH_PATH):
- fstools.mkdir(settings.WHOOSH_PATH)
- try:
- ix = index.open_dir(settings.WHOOSH_PATH)
- except index.EmptyIndexError:
- ix = create_index()
- else:
- logger.debug('Search Index opened.')
- return ix
-
-
- def item_is_supported(item):
- return item.type != TYPE_FOLDER
-
-
- def add_item(ix, item):
- # Collect data for the item
- #
- data = {
- 'rel_path': item.rel_path,
- 'name': os.path.splitext(item.rel_path.split('/')[-1])[0],
- 'type': item.type,
- }
- favourite_of = item.favourite_of.all()
- if len(favourite_of) > 0:
- data['favourite_of'] = ' '.join([u.username for u in favourite_of])
- tags = item.tag_set.all()
- if len(tags) > 0:
- data['tag'] = ' '.join([t.text for t in tags])
- for key, value in item.cached_item_data.items():
- data[key] = value
- # Write data to the index
- #
- with ix.writer() as w:
- logger.info('Adding document with rel_path=%s to the search index.', data.get('rel_path'))
- w.add_document(**data)
- for key in data:
- logger.debug(' - Adding %s=%s', key, repr(data[key]))
-
-
- def delete_item(ix, item):
- with ix.writer() as w:
- logger.info('Removing document with rel_path=%s from the search index.', item.rel_path)
- w.delete_by_term("rel_path", item.rel_path)
-
-
- def update_item(ix, item):
- if item_is_supported(item):
- delete_item(ix, item)
- add_item(ix, item)
-
-
- def rebuild_index(ix):
- for item in Item.objects.all().exclude(type=TYPE_FOLDER):
- add_item(ix, item)
- return len(Item.objects.all().exclude(type=TYPE_FOLDER))
-
-
- def search(ix, search_txt):
- qp = qparser.MultifieldParser(['name', 'tag'], ix.schema)
- qp.add_plugin(DateParserPlugin(free=True))
- q = qp.parse(search_txt)
- with ix.searcher() as s:
- results = s.search(q, limit=None)
- rpl = []
- for hit in results:
- rpl.append(hit['rel_path'])
- return Item.objects.filter(rel_path__in=rpl)
|