fulltext search in macosx

This commit is contained in:
j 2019-01-15 14:08:42 +05:30
parent 6c7d6bb6b0
commit 1c8a5c3764
5 changed files with 59 additions and 2 deletions

View File

@ -241,6 +241,12 @@
"format": {"type": "boolean", "args": []},
"sort": true
},
{
"id": "fulltext",
"title": "Full Text",
"find": true,
"type": "text"
},
{
"id": "random",
"title": "Random",

28
oml/fulltext.py Normal file
View File

@ -0,0 +1,28 @@
import logging
import os
import subprocess
import sys
logger = logging.getLogger(__name__)
def find_fulltext_macos(query):
import settings
from item.models import File
prefix = os.path.join(os.path.expanduser(settings.preferences['libraryPath']), 'Books/')
cmd = ["mdfind", "-onlyin", prefix, query]
books = subprocess.check_output(cmd).decode().strip().split('\n')
books = [path[len(prefix):] for path in books]
ids = [b[0] for b in File.query.filter(operators.in_op(File.path, books)).values('sha1')]
return ids
def find_fulltext(query):
ids = []
if sys.platform == 'darwin':
ids = find_fulltext_macos(query)
else:
logger.debug('missing fulltext search implementation for %s', sys.platform)
return ids
def platform_supported():
return sys.platform == 'darwin'

View File

@ -9,6 +9,7 @@ from sqlalchemy.sql.expression import text
import utils
import settings
from fulltext import find_fulltext
import logging
logger = logging.getLogger(__name__)
@ -25,7 +26,7 @@ def get_operator(op, type='str'):
'$': operators.endswith_op,
'&': operators.in_op,
},
'int': {
'int': {
'==': operators.eq,
'>': operators.gt,
'>=': operators.ge,
@ -65,7 +66,7 @@ class Parser(object):
...
'''
#logger.debug('parse_condition %s', condition)
if not 'value' in condition:
if 'value' not in condition:
return None
k = condition.get('key', '*')
if not k:
@ -122,6 +123,18 @@ class Parser(object):
in_op = operators.notin_op if exclude else operators.in_op
q = in_op(self._model.id, ids)
return q
elif k == 'fulltext':
ids = find_fulltext(v)
if ids:
in_op = operators.notin_op if exclude else operators.in_op
q = in_op(self._model.id, ids)
else:
# nothing
q = operators.eq(self._model.id, -1)
if exclude:
q = ~q
return q
elif key_type in ("string", "text"):
if isinstance(v, str):
v = unicodedata.normalize('NFKD', v).lower()

View File

@ -6,6 +6,7 @@ import os
from oml.pdict import pdict
from oml.utils import get_user_id
from oml import fulltext
base_dir = os.path.normpath(os.path.join(os.path.abspath(os.path.dirname(__file__)), '..'))
static_path = os.path.join(base_dir, 'static')
@ -90,3 +91,10 @@ DEBUG_HTTP = server.get('debug_http', False)
DEBUG_API = server.get('debug_api', False)
DB_VERSION = 13
FULLTEXT_SUPPORT = fulltext.platform_supported()
if not FULLTEXT_SUPPORT:
config['itemKeys'] = [k for k in config['itemKeys'] if k['id'] != 'fulltext']

View File

@ -35,6 +35,8 @@ def init(data):
if os.path.exists(settings.oml_data_path):
with open(settings.oml_data_path) as fd:
config = json.load(fd)
if not settings.FULLTEXT_SUPPORT:
config['itemKeys'] = [k for k in config['itemKeys'] if k['id'] != 'fulltext']
else:
config = {}
response['config'] = config